我必须获得两个整数列表(两个纵坐标)之间的列表差异。 我白了这个:
difference(L,[],L) :- !.
difference([],_,[]) :- !.
difference([],[],W).
difference([H|T1],[D|T2],T3) :- difference(T1,[D|T2],[H|T3]).
difference([H|T1],[H|T2],T3) :- difference(T1,T2,T3).
但为什么我不能得到我的列表差异? 如果我这样写:
difference([],[],W):- write(X).
和这个例子:
| ?- difference([1,4,4],[1,4],R).
[4|_27]
它是正确的!
注意如果我有重复的号码我必须显示它!
答案 0 :(得分:1)
我觉得你的代码很奇怪。例如,你的第三个条款:什么是W
?好像你的意思是说:
difference([],[],_).
第二个问题:在第四个条款中,没有什么能阻止H和D成为具有相同绑定的自变量。我怀疑你的意思是这样的:
difference([H|T1],[D|T2],T3) :- H \= D, difference(T1,[D|T2],[H|T3]).
修复这些事情似乎可以修复谓词以给出一个合理的答案:
| ?- difference([1,4,4], [1,4], R).
R = [4]
我认为你的前几个条款试图处理不同类型的基本情况,是吗? E.g:
difference(L, [], L) % handles the case where the second list is exhausted
difference([], _, []) % handles the case where the first list is exhausted
difference([], [], W) % handles the case where the lists are exhausted at the same time
这个问题的一个问题是L = []是一个合法的绑定,所以第一个和第三个子句意思相同。您可以安全地删除第三个,因为它会匹配并在第一个上产生相同的答案。第二个子句更有趣,因为它似乎说无论我们到目前为止做了什么工作,如果第一个列表为空,结果为空。我发现这种可能性有点刺耳 - 你有可能真的想要这两个基本案例吗? :
difference([], L, L).
difference(L, [], L).
我仍然不相信,但在我更好地了解你想要实现的目标之前,我可能无法提供更多帮助。例如,difference([1, 4], [1, 4, 4], R)
会发生什么?我假设您可能需要R = [4]
,但您的代码会生成R = []
。
另外,我发现它不太可能
difference([],[],W):- write(X).
将是一个有用的调试策略,因为Prolog将为X生成一个新的变量绑定,因为它没有任何内容可供引用。
我对所有更改的最终版本如下所示:
difference(L, [], L) :- !.
difference([], L, L) :- !.
difference([H|T1], [D|T2], T3) :- D \= H, difference(T1, [D|T2], [H|T3]).
difference([H|T1], [H|T2], T3) :- difference(T1, T2, T3).
修改:这是否符合您的要求?
not_in1(X, Left, Right) :- member(X, Left), \+ member(X, Right).
not_in(X, Left, Right) :- not_in1(X, Left, Right).
not_in(X, Left, Right) :- not_in1(X, Right, Left).
differences(Left, Right, Differences) :-
findall(X, not_in(X, Left, Right), Differences).
?- differences([1,2,3,4], [1,3,5], X).
X = [2,4,5]
如果是这样,我会尝试让原始代码生成匹配的答案。
编辑2 :好的,所以上面的解决方案的问题是它是O(N ^ 2)。在最坏的情况下(两个完全不同的列表),它必须将列表1中的每个项目与列表2中的每个项目进行比较。它没有利用这两个列表都是有序的事实(我相信这是'纵坐标'的意思)。
结果看起来更像您的原始代码,但您的原始代码没有利用订购商品的事实。这就是为什么第四和第五种情况令人困惑的原因:你应该重复其中一个列表或另一个列表,具体取决于哪个数字更大。更正后的代码如下所示:
differences([], Result, Result).
differences(Result, [], Result).
differences([H|Ls], [H|Rs], Result) :- differences(Ls, Rs, Result).
differences([L|Ls], [R|Rs], [L|Result]) :-
L < R,
differences(Ls, [R|Rs], Result).
differences([L|Ls], [R|Rs], [R|Result]) :-
L > R,
differences([L|Ls], Rs, Result).
你可以看到这产生与O(N ^ 2)方法相同的结果:
?- differences([1,2,3,4], [1,3,5], X).
X = [2,4,5]
你是对的,你确实需要两个基本案例。这是任何一个列表的剩余部分成为结果的一部分。据推测,这些值将是最大值(示例中为[5]
)。
现在我有三个归纳案例:一个针对<
,一个针对>
,一个针对=
。相等的情况很直观:在两个列表上重复,丢弃两个列表的头部。下一个案例基本上说如果左头小于右头,则将其添加到结果中并重复左侧尾部。在这种情况下,权利没有变化。另一种情况是这种情况的镜像。
希望这有帮助!