List 序言:以意外顺序计算的规则

List 序言:以意外顺序计算的规则,list,prolog,rule,List,Prolog,Rule,我目前正在编写一个Prolog程序,以从列表中删除重复项 这是我的密码: makeset([First], [First]). % if only one item in list, the solution is itself. makeset([First, Second], [First, Second]) :- dif(First, Second). makeset([First, Second], [First]) :- First = Second. % if more

我目前正在编写一个Prolog程序,以从列表中删除重复项

这是我的密码:

makeset([First], [First]). % if only one item in list, the solution is itself.
makeset([First, Second], [First, Second]) :-
   dif(First, Second).
makeset([First, Second], [First]) :-
    First = Second.
% if more than two items in list
makeset([First | Tail], FinalList) :-
   member(First, Tail),
   makeset(Tail, FinalList).
makeset([First | Tail], FinalList) :-
   not(member(First, Tail)),
   makeset(Tail, [First |FinalList]).
但是,当我在一个包含两个以上项目的列表中尝试此操作时,它只返回false。我运行了一个跟踪,发现它一直在使用最后两条规则,即使在列表中只有两项。为什么会这样

查询示例:
makeset([3,2,4,5,1],X)。
返回false,但每次评估都使用最后一条规则

编辑: 我将规则更改为以下内容,但仍然无法正确评估,因此问题必须与最后一条规则有关

makeset([First], FinalList) :- 
 FinalList = [First]. % if only one item in list, the solution is itself.
makeset([First, Second], FinalList) :- 
 not(First = Second), FinalList = [First, Second].
makeset([First, Second], FinalList) :- 
 First = Second, FinalList = [First].
% if more than two items in list
makeset([First | Tail], FinalList) :- 
 member(First, Tail), makeset(Tail, FinalList).
makeset([First | Tail], FinalList) :- 
 not(member(First, Tail)), makeset(Tail, [First |FinalList]).

如何修复最后一条规则?

在最后一条规则中,将元素从第一个列表移动到第二个列表。 然后,您将阻止匹配顶级规则


注意:dif/2它是一个强大但复杂的谓词。你真的需要它的力量吗

在最后一条规则中,将元素从第一个列表移动到第二个列表。
makeset([First | Tail], [First | FinalList]) :- 
 not(member(First, Tail)), makeset(Tail, FinalList).
然后,您将阻止匹配顶级规则

注意:dif/2它是一个强大但复杂的谓词。你真的需要它的力量吗

makeset([First | Tail], [First | FinalList]) :- 
 not(member(First, Tail)), makeset(Tail, FinalList).
您不应该将
作为
makeset
输入的第一部分,这会阻止早期规则的匹配。只有在使用
makeset
谓词统一
FinalList
之后,才能将
First
添加到列表中

您的解决方案也不会处理输入列表为空的情况

您不应该将
作为
makeset
输入的第一部分,这会阻止早期规则的匹配。只有在使用
makeset
谓词统一
FinalList
之后,才能将
First
添加到列表中

您的解决方案也不能处理输入列表为空的情况。

净化您的代码! 首先。你似乎坚持这个世界纯洁的一面。当然,您使用的是
dif/2
!与其程序对应物相反,它丑陋的兄弟
(\=)/2
,这意味着此时不可统一,但可能以后,或者永远不会,不要问我,
dif/2
谓词有一个纯粹的声明意义。它意味着(句法或理论自由)不平等。这不仅会给你带来业力和放纵。不,它甚至可以帮助您调试程序。事实上,我们可以使用Prolog来帮助我们发现程序中的问题——只要您的代码足够纯净!首先,让我们净化你的代码,然后我们可以调试它

代码中唯一不正常的是
not(member(First,Tail))
。我将用
maplist(dif(First),Tail)
替换它。现在我们有一个纯程序。它失败了,就像以前一样。第一件事可能是减少列表的大小。你真的想做那件家务吗?这里有一个更简单的方法,只适用于纯Prolog程序。我会问:

让我看看所有可以想象的列表,它们的集合是什么

右,所有列表。一个也不会落在后面

问序言! 0..2
中的
I的所有答案现在似乎都很完美。它们包含了所有可以想象得到的列表。都是。请注意,在一个答案中再次出现
dif/2
,确保元素不同

对于
I=3
来说,事情变得更加复杂。一些意见:

  • 没有关于
    X=[\uu,\uu,\u]
    的答案。臭虫找到了!事实上,最小的错误发现

  • L=[\u a,\u a,\u a]

我们可以将第一个问题简化为一个目标:

| ?- L = [_,_,_], L = X, makeset(L, X).
no
应该有答案。我们现在可以应用另一种策略:

概括你的代码 显然,
makeset/2
的定义太专业化了。现在,我将尝试对其进行概括,以便更好地定位错误。为此,请在程序中添加以下内容:

:- op(950,fy, [*]).

*_.
通过这种方式,我们可以在目标前面添加
*
,以将其删除。我们也可以使用注释,但这是一种更干净的方法。所以我现在要做的是系统地添加
*
,然后看看目标是否仍然失败。此外,我将一些变量重命名为新名称(
\ux
),这相当于进一步的泛化。经过一番尝试,我最终得到了:

:- op(950,fy, [*]). *_. makeset([], []). makeset([First], [_xFirst]). makeset([First, Second], [_xFirst, _xSecond]) :- * dif(First, Second). makeset([First | Tail], FinalList) :- * member(First, Tail), makeset(Tail, FinalList). makeset([First | Tail], FinalList) :- * maplist(dif(First),Tail), makeset(Tail, [_xFirst |FinalList]). ?- L = [_,_,_], L = X, makeset(L, X). 有更聪明的方法来表达这个
成员
/
映射列表dif
二分法。但是我会让它保持这样…

净化你的代码! 首先。你似乎坚持这个世界纯洁的一面。当然,您使用的是
dif/2
!与其程序对应物相反,它丑陋的兄弟
(\=)/2
,这意味着此时不可统一,但可能以后,或者永远不会,不要问我,
dif/2
谓词有一个纯粹的声明意义。它意味着(句法或理论自由)不平等。这不仅会给你带来业力和放纵。不,它甚至可以帮助您调试程序。事实上,我们可以使用Prolog来帮助我们发现程序中的问题——只要您的代码足够纯净!首先,让我们净化你的代码,然后我们可以调试它

代码中唯一不正常的是
not(member(First,Tail))
。我将用
maplist(dif(First),Tail)
替换它。现在我们有一个纯程序。它失败了,就像以前一样。第一件事可能是减少列表的大小。你真的想做那件家务吗?这里有一个更简单的方法,只适用于纯Prolog程序。我会问:

让我看看所有可以想象的列表,它们的集合是什么

右,所有列表。一个也不会落在后面

问序言! 0..2
中的
I的所有答案现在似乎都很完美。它们包含了所有可以想象得到的列表。都是。请注意,在一个答案中再次出现
dif/2
,确保元素不同

对于
I=3
来说,事情变得更加复杂。一些意见:

  • 没有关于
    X=[[uu,],
    :- op(950,fy, [*]).
    *_.
    
    makeset([], []).
    makeset([First], [_xFirst]).
    makeset([First, Second], [_xFirst, _xSecond]) :-
       * dif(First, Second).
    makeset([First | Tail], FinalList) :-
       * member(First, Tail),
       makeset(Tail, FinalList).
    makeset([First | Tail], FinalList) :-
       * maplist(dif(First),Tail),
       makeset(Tail, [_xFirst |FinalList]).
    
    ?- L = [_,_,_], L = X, makeset(L, X).
    
    makeset([], []).
    makeset([First | Tail], FinalList) :-
       member(First, Tail),
       makeset(Tail, FinalList).
    makeset([First | Tail], [First|FinalList]) :-
       maplist(dif(First),Tail),
       makeset(Tail, FinalList).