所以我遇到了这个Prolog问题:
给定一个线性数字列表,删除连续值的所有序列。
E.g。
remove([1, 2, 4, 6, 7, 8, 10], L)
将生成L=[4, 10]
。
我设法编写了这段代码:
consecutive(N,P):-
N is P-1.
removeS([],[]).
removeS([H],[H]).
removeS([H1,H2],[]):-
consecutive(H1,H2).
removeS([H1,H2|T],[H1|L]):-
not(consecutive(H1,H2)),
removeS([H2|T],L).
removeS([H1,H2,H3|T],L):-
consecutive(H1,H2),
not(consecutive(H2,H3)),
removeS([H3|T],L).
removeS([H1,H2,H3|T],L):-
consecutive(H1,H2),
consecutive(H2,H3),
removeS([H3|T],L).
它几乎适用于某些情况:
removeS([1,2,3,4,5,2,3,4,5,6,7,9,11],R). --> R = [5, 9, 11];
Here only 9 and 11 should be displayed
removeS([3,2,1,2,3,4,5,2,3,4,5,6,7,9,11],R). --> R = [3, 2, 5, 9, 11];
Here only 3,2,9,11 should appear in R
在计算下一步时,需要考虑增加序列的最后一个数字。
我在这里做错了什么?
答案 0 :(得分:1)
在这个答案中,我们将Prolog lambdas与两个meta-predicate结合使用。
:- use_module(library(lambda)).
基于append/2
,split_if_adj/3
,tfilter/3
,(=)/3
和z_nonsucc_t/3
我们定义:
consecutives_removed(Xss, Zs) :-
split_if_adj(z_nonsucc_t, Xss, Yss),
tfilter(\[_|Xs]^(Xs=[]), Yss, Zss),
append(Zss, Zs).
示例查询(由OP给出):
?- consecutives_removed([1,2,4,6,7,8,10], Xs).
Xs = [4,10].
?- consecutives_removed([1,2,3,4,5,2,3,4,5,6,7,9,11], Xs).
Xs = [9,11].
?- consecutives_removed([3,2,1,2,3,4,5,2,3,4,5,6,7,9,11], Xs).
Xs = [3,2,9,11].
答案 1 :(得分:0)
你做的不那么普遍(结果,更复杂),而不是需要。
?- removeS([1,2,3],R).
R = [3] ;
false.
我已经引入了一个服务谓词,“吃掉”所有连续的,并简化了逻辑,当两个连续出现时,仅启动它,我有:
?- removeS([3,2,1,2,3,4,5,2,3,4,5,6,7,9,11],L).
L = [3, 2, 9, 11].
修改的
这是我的定义。切割可以删除,否则你可以做的替代,但恕我直言,这只会整个混乱。或者,简单地说,丢弃它并用一次/ 1包裹removeS / 2顶部调用。
removeS([],[]).
removeS([A,B|T],L):- succ(A,B), eat(A,[B|T],R), !, removeS(R, L).
removeS([A|B],[A|L]) :- removeS(B,L).
eat(A,[B|T],R) :- succ(A,B), eat(B,T,R).
eat(_,T,T).