2

您好,我必须用列表解决一些序言问题,但我无法弄清楚这些是如何工作的。我必须在列表中的每个偶数元素之后添加“1”,并区分 2 个列表。我知道这看起来很容易,用其他语言(如 java 或 c#)我会很容易,但 prolog 让我头疼。请帮助我:|

4

1 回答 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 回答