【问题标题】:Prolog - solving problems with listsProlog - 用列表解决问题
【发布时间】:2013-10-22 21:08:52
【问题描述】:

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

【问题讨论】:

  • 对于第一个问题:你必须给一个数字加 1 还是你必须给一个字符串加上“1”。您的列表元素的类型是什么?第二个问题:您如何定义两个列表之间的“差异”?你的意思是 A - B = C (A, B, C 是列表) where C[i] = A[i] - B[i]?
  • 对我而言,在编写 Prolog 时,首先考虑以自然语言形式定义我想要的内容的规则会有所帮助。通常,有不止一个。例如,“在 EMPTY 列表中的每个偶数元素之后插入 1 的结果是......”(在这里你会指出你是否想要 [1][]。然后你可能有另一个给出递归的规则根据列表的头部和尾部 ([H|T]) 或头部和尾部中的两个元素 ([H1, H2|T]) 定义您想要的内容。然后将自然语言翻译成 Prolog 语句。
  • 第一个例子:[4,3,5,7,2,6,3] -->[4,3,1,5,1,7,1,2,6 ,3,1] 和区别:A=[3,4,5,6,7], B=[4,7] --> C=[3,5,6]
  • 您的示例在每个奇数元素之后插入一个1。这是你的意图吗?
  • 这似乎是一个课堂作业。很抱歉看起来像个无聊的老头,但在做作业之前,我建议你先阅读课程笔记,并尝试理解教授已经给你提供的更简单的例子。

标签: prolog


【解决方案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.

【讨论】:

  • 它有效,谢谢,但你能解释一下在那里做了什么吗?你在哪里检查NR。是偶数吗?
  • 第二个是相对差异
  • @jojuk:查看我修改后的答案。
  • 非常感谢!这对我很有帮助!
  • 在第二个中,它给了我一个错误。如果我在谓词部分声明“成员”,则表示我没有该谓词的子句,如果我不声明它,则表示未声明。我该怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-01
相关资源
最近更新 更多