Prolog 序言:遍历列表A的元素并与列表B的成员进行比较

Prolog 序言:遍历列表A的元素并与列表B的成员进行比较,prolog,Prolog,我第一次尝试编写Prolog逻辑,但遇到了麻烦。我要写的逻辑,需要两个列表,并检查两者之间的相似元素。例如,考虑谓词相似性/ 2 < /代码>: ?- similarity([2,4,5,6,8], [1,3,5,6,9]). true. ?- similarity([1,2,3], [5,6,8]). false. 第一个查询将返回true,因为这两个列表共有5个和6个。第二个返回false,因为该查询中的两个列表之间没有公共元素 我不能使用内置逻辑,如成员、不相交、相交等。我正在考虑遍历

我第一次尝试编写Prolog逻辑,但遇到了麻烦。我要写的逻辑,需要两个列表,并检查两者之间的相似元素。例如,考虑谓词<代码>相似性/ 2 < /代码>:

?- similarity([2,4,5,6,8], [1,3,5,6,9]).
true.

?- similarity([1,2,3], [5,6,8]).
false.
第一个查询将返回
true
,因为这两个列表共有5个和6个。第二个返回
false
,因为该查询中的两个列表之间没有公共元素


我不能使用内置逻辑,如成员、不相交、相交等。我正在考虑遍历提供的第一个列表,并检查它是否与第二个列表中的每个元素匹配。这是解决这个问题的有效方法吗?我将感谢任何建议和帮助。非常感谢。

第一次编写Prolog可能会让人望而生畏,因为它不同于您最可能遇到的许多传统编程语言;然而,一旦你掌握了这种新的编程风格,这将是一次非常有益的体验!既然你提到你是第一次写Prolog,我将给出一些关于写Prolog的一般提示和技巧,然后讨论你的问题的一些提示,然后提供我认为是解决问题的方法


反复思考 您可以认为您编写的每个Prolog程序本质上都是递归的。i、 e.您可以为其提供一系列“基本情况”,其形式如下:
human(John)。
wildling(Ygritte)
在我看来,这些规则应该始终是您编写的第一条规则。试着把问题分解成最简单的情况,然后从那里开始工作。

另一方面,您还可以为它提供更复杂的规则,这些规则看起来像这样:
contains(X,[H | T]):-contains(X,T)
关键是编写这样的规则相当于在Python中编写递归函数。这条规则在查看列表中是否包含值时起了很大的作用,但若并没有“基本情况”,它是不完整的。一个完整的contains规则实际上是两个规则组合在一起:
contains(X,[X|)]。

包含(X[H | T]):-包含(X,T)。


这样做的最大好处是尝试并确定问题的简单情况,这些情况可以像递归函数中的基本情况一样,然后尝试确定您希望如何“递归”并实际处理手头的问题


模式匹配 Prolog的一大优点是它拥有的模式匹配系统。只要有可能,你就应该100%地利用这一点——当你试图处理列表时,这一点尤其有用。例如:
头部(X[X|T])。

调用时将计算为true:
head(1[1,2,3])
,因为规则中固有的是X的匹配。在列表的第一个元素上进行这种模式匹配非常重要,实际上是在Prolog中处理列表的关键方法。根据我的经验,列表顶部的模式匹配通常是我前面提到的“基本情况”之一


了解程序的流程 Prolog工作原理的另一个关键部分是它采用“自顶向下”的方法来读取代码。我的意思是,每次调用规则时(除了形式
king(James)。
的定义外),Prolog从第1行开始,一直持续到规则为true或文件结尾。因此,规则的顺序非常重要。我假设您知道可以通过逗号将规则组合在一起以表示逻辑AND,但更微妙的是,如果您将一个规则排列在另一个规则之上,它可以充当逻辑OR,因为它将在另一个规则之前进行计算,并且可能导致程序递归


具体例子 现在我已经把所有的一般建议都排除在外了,我将实际引用给定的问题。首先,我要写我的“基本情况”。如果给您两个第一个元素相同的列表,会发生什么
如果每个列表中的第一个元素不相同,则它们必须不同。因此,您必须查看第二个列表,以查看该元素是否包含在列表其余部分的任何位置。这会产生什么样的规则
也可能是第一个列表的第一个元素根本不包含在第二个列表中,在这种情况下,您必须在第一个列表中前进一次,然后从第二个列表重新开始。这会产生什么样的规则
最后,我想说您的方法是正确的,我在下面提供了自己的解决方案:

相似性([H|uu],[H|uu])。

相似性(H1 | T1],124; T2]:-相似性([H1 | T1],T2)。

相似性([uu124; T1],[H2|T2]):-相似性(T1[H2|T2])。

希望所有这些都能对你有所帮助