我想做的是从特定成员开始反转列表的内容。例如 [1,2,3,4,5,6,7],假设我想在 4 处翻转,那么它必须变成 [1,2,3,7,6,5,4]。我写了一个返回 [4,5,6,7] 的“cut”谓词,然后我使用 append/reverse 来制作最终列表。如果我将谓词直接写入 TKeclipse,结果正是我想要的。当我试图将它们统一在一个“翻转”谓词中时,eclipse 会随意地回答“否”,我不明白为什么。
cut([H|T], H, [H|T]).
cut([H|T], X, RightSublist):-
X \= H,
cut(T, X, RightSublist).
flip(state1, N, state2):-
cut(state1, N, RightSublist),
append(LeftSublist, RightSublist, state1),
reverse(RightSublist, ReversedRightSublist),
append(LeftSublist, ReversedRightSublist, state2).
这是一种更有效的方法,因为遍历列表一次,而不是使用
append
:
flip_at_elem(Elem, Lst, Flip) :-
flip_at_elem_(Lst, Elem, Flip, After, Rem),
reverse(After, Rem).
flip_at_elem_([H|T], Elem, Flip, After, Rem) :-
( H = Elem
-> After = [H|T],
Flip = Rem
; Flip = [H|Flip0],
flip_at_elem_(T, Elem, Flip0, After, Rem)
).
swi-prolog 中的结果:
?- time(flip_at_elem(4, [1,2,3,4,5,6,7], F)).
% 11 inferences, 0.000 CPU in 0.000 seconds (80% CPU, 1133086 Lips)
F = [1, 2, 3, 7, 6, 5, 4].
我可能会做这样的事情:
flip_at(Xs,E,Ys) :- partition(Xs,Ys,E,RemX,RemY) , reverse(RemX,RemY) .
partition( [X|Xs] , Ys , X , [X|Xs] , Ys ) .
partition( [X|Xs] , [X|Ys] , E , RemX , RemY ) :- partition(Xs,Ys,E,RemX,RemY) .
结果(SWI Prolog):
?- time( flip_at( [a,b,c,d,e,f,g], d, Flipped ) ) .
10 inferences, 0.000 CPU in 0.000 seconds (103% CPU, 37321 Lips)
Flipped = [a, b, c, g, f, e, d]
此外,如果您要使用
append/3
,您所要做的就是:
我们可以很容易地划分列表:
partition( [] , _ , [] , [] ) . % empty list or element not found
partition( [X|Xs] , X , [] , [X|Xs] ) . % found the element, it and the remainder of the source list comprise the right half
partition( [X|Xs] , E , [X|Ys] , Zs ) :- % otherwise, add the head to the left half, if...
X \= E, - it's not the element we're looking for, and
partition(Xs,E,Ys,Zs). - recurse down
一旦你有了......
flip( Xs , N , Ys ) :-
partition(Xs,N,Ls,Rs),
reverse(Rs,R0),
append(Ls,R0,Ys) .