【问题标题】:Finding all the matching elements in 2 lists in prolog在 prolog 的 2 个列表中查找所有匹配元素
【发布时间】:2017-09-09 16:26:30
【问题描述】:

我必须编写一个 Prolog 程序来查找 2 个单独列表之间的所有匹配元素。在实践中,它必须看起来像这样:

?- intersect([a,c,a,b], [d,b,a,b], X).

X = [a,b]

到目前为止,我所拥有的是:

intersect([], Y, Z).
intersect([H| T1], Y, [H| T2]) :-
   member(H, Y),
   remove_all(H, T1, P),
   intersect(T1, Y, T2).
intersect([H| T1], Y, T2) :-
   intersect(T1, Y, T2).

(我必须在之前的练习中创建一个 remove_all 函数。这会从列表中删除与您给出的匹配的所有元素)

这可行,除了一件事,我的答案是这样的:

X = [a, b|_17660]

我是 Prolog 的新手,对它了解不多。为什么最后有一个“|_17660”,我将如何更改我的代码来修复它? 如果有人可以帮助我,将不胜感激。

【问题讨论】:

  • intersect([a,b,c,d,e,f], [a,b,x,y,d,e,f,m], X). 的结果是什么?
  • 你的remove_all/3在哪里?你认为它是正确的,...

标签: list prolog


【解决方案1】:

首先,您收到了三个关于“单例变量”的明确警告。这是一个非常明确的暗示,表明出了点问题。通常,Prolog 程序员会先解决这个问题。当然,还有其他方法。

所以你的问题是你得到X = [a, b|_17660] 作为答案。这是什么意思? _176660 只是一个必须普遍量化的变量名。换句话说,你得到的答案是:

所有以[a, b|_] 开头的X 都是一个解决方案。像[a, b] 是有意的,但也像[a, b|non_list] 这样丑陋的。甚至是像[a, b, c]这样的误导甚至不正确的。

要了解这个问题的根源,让我们关注一个隐含的地面查询,例如:

?- intersect([a,c,a,b], [d,b,a,b], [a,b|non_list]).
ERROR: Undefined procedure: remove_all/3

啊,你没有显示remove_all/3 的定义。在传统的编程语言中,我们现在必须停下来。但是在 Prolog 中,我们仍然可以继续。无需查看该定义。我将改为使用不再包含remove_all/3specialization。所以从某种意义上说,这只是你程序的一部分,但我们仍然可以从中得出结论。这是我使用的:

相交([],Y,Z):- Z = non_listintersect([H|T1], Y, [H|T2]) :- false, 成员(H, Y), remove_all(H, T1, P), 相交(T1,Y,T2)。 intersect([H|T1], Y, T2) :- T2 = non_list, 相交(T1,Y,T2)。

这个程序几乎是你的。除了我添加了额外的目标。在另一种语言中,这是不可能的。但是在 Prolog 中,我们可以利用(纯的、单调的)Prolog 程序的一个非常好的特性:您可以随机添加额外的目标,并且仍然可以预测结果是什么:新程序描述了您的目标的 子集原程序做到了。当然,我有一些怀疑,所以我的添加是有一定指导意义的。但是你可以总是对你的错误程序做同样的事情!

仍然不相信?现在使用该新程序查看您实际描述的内容:

?- intersect(Xs, Ys, Zs).
   Xs = [],
   Zs = non_list ...

?- intersect([], any, non_list).
   true.

显然,这不是您想要的。要了解它的来源,我们可以让您的程序更加专业化:

相交([],Y,Z):- Z = non_listintersect([H|T1], Y, [H|T2]) :- false, 成员(H, Y), remove_all(H, T1, P), 相交(T1,Y,T2)intersect([H|T1], Y, T2) :- false, 相交(T1,Y,T2)

现在应该很明显,事实必须是专门的,否则这些荒谬的解决方案是可能的。这是一个这样的专业:

相交([],_Y,Z):- Z = []。 intersect([H|T1], Y, [H|T2]) :- false, 成员(H, Y), remove_all(H, T1, P), 相交(T1,Y,T2)。 相交([H| T1],Y,T2):- 相交(T1,Y,T2)。

事实是:空列表和任何东西的交集就是空列表。让我们保持这种状态,即使 Y = non_list 现在也是可能的。

您的规则仍然被删除,因为我没有看到您的定义。不要紧!我会继续在剩下的程序中发现问题。目前,我不知道在哪里寻找问题。但是我可以通过询问 最一般的查询 来让 Prolog 为我执行此操作,该查询的内容类似于

Prolog,告诉我你能描述的所有解决方案。

(记住这个技巧,你可以随时问这个问题——根本不知道谓词是关于什么的。)

?- intersect(Xs, Ys, Zs).
   Xs = Zs, Zs = []
;  Xs = [_99922],
   Zs = [] ...

第一个答案是完美的,但第二个答案不是。请注意Ys 不会出现在任何地方,因此答案适用于所有Ys。甚至:

?- intersect([a], [a], []).
   true.

这个问题和你的规则直接相关,没有任何条件...

请参阅this 以获得干净的解决方案。

【讨论】:

    猜你喜欢
    • 2013-12-06
    • 1970-01-01
    • 2016-07-18
    • 2011-08-17
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    相关资源
    最近更新 更多