您好,我必须用列表解决一些序言问题,但我无法弄清楚这些是如何工作的。我必须在列表中的每个偶数元素之后添加“1”,并区分 2 个列表。我知道这看起来很容易,用其他语言(如 java 或 c#)我会很容易,但 prolog 让我头疼。请帮助我:|
问问题
889 次
1 回答
1
编辑以注意澄清的问题陈述(“偶数项”表示该项的值是偶数(而不是该项在列表中的序数位置):
insert_one_after_even_items( [] , [] ). % if the source list is exhaused, we're done.
insert_one_after_even_items( [X|Xs] , [X,1|Ys] ) :- % otherwise,
0 is X mod 2 , % - if the number is even, prepend it and a 1 to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. %
insert_one_after_even_items( [X|Xs] , [X|Ys] ) :- % otherwise,
1 is X mod 2 , % - if the number is odd, prepend it to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. % Easy!
对于您的第二个问题,产生两个列表之间的差异,您是在谈论集合差异吗?如果是这样,给定两个集合 A 和 B,您是在谈论相对差异(B 中不存在的 A 的所有元素)还是绝对差异(两个集合中都不存在的 A 或 B 的所有元素) ?
要解决相对集差问题(查找 A 中不存在于 B 中的所有成员),可以使用内置member/2
谓词:
relative_difference( [] , _ , [] ) . % if the source list is exhausted, we're done
relative_difference( [A|As] , Bs , R ) :- % if the source list is non-empty, and
member(A,Bs) , % - the current A is an element of B,
! , % - we insert a deterministic cut (no backtracking)
relative_difference( As , Bs , R ) % - and recurse down, discarding the current A
. %
relative_difference( [A|As] , Bs , [A|R] ) :- % if the source list is non-empty (and A is not an element of B due to the cut inserted earlier)
relative_difference( As , Bs , R ) % we simply add A to the result list and recurse down.
.
您将在此处注意一件事:我们在所有这些示例中构建的结果列表都是从变量构建的。列表的尾部是未绑定的(并作为新结果传递给下一个递归调用,在那里它要么成为新的列表节点,要么在最后成为空列表。
这具有以下效果
- 按顺序(而不是相反的顺序)构建列表。
- 如果结果是在初始调用时绑定的,则随着递归的进行,与预期结果的统一会逐项发生,这意味着
- 当第一次统一失败发生时,执行被短路。
如果您的 prolog 实现没有member/2
内置,那么它很容易实现。这样的事情应该这样做:
member(X,[X|T]) :- ! . % A hit! cut and succeed.
member(X,[_|T]) :- member(X,T) . % ... and a miss. Just recurse down on the tail.
于 2013-10-22T22:59:19.657 回答