Prolog谓词用于显示位于偶数位置的列表的每个成员

时间:2013-10-09 20:51:24

标签: list recursion prolog

我正在研究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).

显示对我有用的结果的唯一方法是引入写入功能,但它不适用于该任务。据我记忆,我们不能直接使用ElemList,所以我有点困惑。我请求帮助,我将非常感谢你的帮助=)

3 个答案:

答案 0 :(得分:2)

在Prolog中,首先要考虑逻辑自然语言中的问题,然后尝试将其转换为Prolog。

您要求的是规则evenmember( X, L ),如果XL的偶数成员,则为真。如果我们可以正确定义此规则,则解决方案将成为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,看看你得到了什么。这个也不需要削减。削减你必须保守。它们意味着您想要修剪搜索树。在这种情况下,这意味着你可以停止寻找有效的解决方案(找到所有偶数成员)。

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

答案 1 :(得分: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。
  5. 第4行的规则选择列表的前两个元素,并将第二个,甚至放置的元素放入均匀放置的元素列表中。如果您在swi-prolog解释器中运行它,它应该为您提供解决方案,而无需使用write/1。但是,如果要使用io谓词格式化输出,可以通过添加辅助谓词来实现:

    format_evenmembers(List) :-
        evenmember(List, Evens),
        format("Even members are ~w", [Evens]).
    

答案 2 :(得分: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个元素,对于偶数长度列表,我们将到达空列表,对于奇数长度列表,将剩下单个元素(如由病理学家指出的)。一旦我们到达基本案例,我们就会建立一个返回递归树的列表。

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

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