我一直试图解决这个问题很长一段时间,我认为我尝试的逻辑是有缺陷的。
目标是用子列表的最后一个替换随后减少的数字子列表。
?- compare([1, 3, 7, 6, 5, 10, 9], Result).
Result = [1, 3, 5, 9] ;
false.
我尝试的是:
compare([A,B|T],X):-
%succ(B,A),
A is B+1,
append([],NextX,X),
compare([B|T],NextX).
remove([A,B|T],X):-
A=\=B+1,
compare([B|T],X).
我不确定如何为compare / 2编写基本情况,我认为我没有正确地将我的逻辑转换为代码。我在这里尝试的是比较A和B,如果它们是连续数字,则从列表中删除A. 非常感谢您的帮助。
答案 0 :(得分:2)
你快到了。首先介绍特殊情况:如果列表只包含一个元素,它就在列表中。
compare([X],[X]).
你的第二条规则只需要改变一下:
compare([A,B|T],X):- % A is not in the list if
A is B+1, % A = B+1
compare([B|T],X). % Note: X is the same as in head of rule
你的谓词remove / 2应该是compare / 2的第3条规则,涵盖了另一种情况:
compare([A,B|T],[A|X]):- % A is in the list
A=\=B+1, % if A is not B+1
compare([B|T],X).
现在查询有效:
?- compare([1, 3, 7, 6, 5, 10, 9], Result).
Result = [1,3,5,9] ?
yes
但是,只有第一个列表是可变的,才能使用此谓词。你不能反过来使用它:
?- compare([A,B,C], [1,2]).
ERROR at clause 2 of user:compare/2 !!
INSTANTIATION ERROR- X is A+B: expected bound value
另一方面,如果你使用库(clpfd)......
:- use_module(library(clpfd)).
compare([X],[X]).
compare([A,B|T],X):-
A #= B+1,
compare([B|T],X).
compare([A,B|T],[A|X]):-
A #\= B+1,
compare([B|T],X).
...以上查询也有效:
?- compare([A,B,C], [1,2]).
A = C = 2,
B = 1 ? ;
A = 1,
B = 3,
C = 2 ? ;
no