List 序言:以意外顺序计算的规则
我目前正在编写一个Prolog程序,以从列表中删除重复项 这是我的密码: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
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).