我正在研究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).
显示对我有用的结果的唯一方法是引入写入功能,但它不适用于该任务。据我记忆,我们不能直接使用Elem
和List
,所以我有点困惑。我请求帮助,我将非常感谢你的帮助=)
答案 0 :(得分: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,看看你得到了什么。这个也不需要削减。削减你必须保守。它们意味着您想要修剪搜索树。在这种情况下,这意味着你可以停止寻找有效的解决方案(找到所有偶数成员)。
请注意,我给出的描述假定您希望在每次调用谓词时获得列表中的单个(下一个,更具体地)偶数成员,而不是一次性获得整个偶数列表,因为这就是原始描述表明。
答案 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).
以下是这些行的翻译:
第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以来已经一年多了,所以希望我仍然知道我在说什么。