1

我正在用 Prolog 研究这种逻辑编程的新概念。我已经处理过削减,失败了,现在我正在讨论列表的主题。我有以下任务要做: - 编写一个函数evenmember(Element, List),它将显示一个元素是否位于列表中的偶数位置。例如evenmember(X,[1,5,3,2])将连续显示解决方案X=5,X=2

我已经玩了一段时间并写了以下内容:

evenmember(_, []) :- !, fail.  
evenmember(_, [_]) :- !, fail.  
evenmember(X, [_, X]) :- !.  
evenmember(Elem, List):-  
    [_, Elem1|Tail] = List,  
    Elem is Elem1,  
    evenmember(Elem1, Tail).

显示对我有用的结果的唯一方法是引入 write 函数,但它不适用于该任务。据我记得,我们不能直接使用ElemList,所以我有点困惑。我寻求帮助,我将感谢您的帮助 =)

4

3 回答 3

2

在 Prolog 中,首先用逻辑自然语言思考问题通常会有所帮助,然后尝试将其翻译为 Prolog。

您要求的是一个规则evenmember( X, L ),如果X它是 的偶数成员,则该规则为真L。如果我们能正确定义这个规则,解决方案将是每个偶数成员L。所以用自然语言表达:

1) X is an even member of L if X is the second element of L.

所以我将在 Prolog 中声明:

evenmember(X, [_, X|_]).   % The 2nd member of a 2-element list is an even member

这仅描述了第一个偶数成员。剩余的偶数成员可以递归描述:

2) X is an even member of L if X is an even member of the tail of L
   ignoring the first two elements.

把它翻译成 Prolog,看看你得到了什么。这个也不需要剪。你必须对削减持保守态度。他们的意思是你想修剪搜索树。在这种情况下,这意味着您可以停止寻找有效的解决方案(找到所有偶数成员)。

请注意,我给出的描述假设您希望在每次调用谓词时获得列表的单个(下一个,更具体地说)偶数成员,而不是一次获得整个偶数列表,因为这是原始描述所表明的.

于 2013-10-10T00:04:13.077 回答
1

这是一个解决方案:

%% evenmembers(+List, -ListOfEvenPlacedMembers).
%    true when ListOfEvenPlacedMembers is a list of the elements of List at even places.
% 
1| evenmembers([],[]).
2| evenmembers([_Odd], []).
3| evenmembers([_Odd,Even|List], [Even|Evens]) :-
4|    evenmembers(List, Evens).

以下是这些行的翻译:

  1. 空列表的偶数成员是一个空列表(没有)。
  2. 具有一个元素的列表的偶数成员是一个空列表(同样,没有)。
  3. 具有前两个元素 _Odd 和 Even,其余 List 的列表的偶数成员是一个列表,其第一个成员是 [Even],其后续成员是 Evens IF
  4. List 的偶数成员是 Evens。

第 4 行的规则选取列表的前两个元素,并将第二个(偶数放置)元素放入均匀放置元素的列表中。如果您在 swi-prolog 解释器中运行它,它应该为您提供解决方案,而无需使用write/1. 但是,如果您想使用 io 谓词来格式化输出,您可以通过添加辅助谓词来实现:

format_evenmembers(List) :-
    evenmember(List, Evens),
    format("Even members are ~w", [Evens]).
于 2013-10-09T21:39:14.373 回答
1

这看起来像家庭作业,但我会通过展示一个类似的示例为您指明正确的方向。

even_members([], []).
even_members([_], []) :- !.
even_members([_,Even|Tail], [Even|Result]) :-
  even_members(Tail, Result).

这使

?- even_members([1,5,3,2], X).
X = [5, 2].

我们取列表头部的第二个元素(始终是均匀定位的元素),并将其添加到包含答案的列表中。然后使用尾部递归遍历列表。

基本情况是当我们到达列表末尾时。由于我们一次遍历列表 2 个元素,因此对于偶数长度的列表,我们将到达一个空列表,而对于奇数长度的列表,将只剩下一个元素(正如 aBathologist 所指出的那样)。一旦我们到达一个基本情况,我们就建立一个返回递归树的列表。

我的示例将答案存储在一个列表中,这通常是您想要的(列表在 Prolog 中很常见)。在您的解决方案中,您不想将结果存储在列表中。

PS自从我写任何Prolog以来已经一年多了,所以希望我仍然知道我在说什么。

于 2013-10-09T21:41:41.150 回答