试图解决 Prolog 中的煎饼问题,无法统一谓词

问题描述 投票:0回答:2

我想做的是从特定成员开始反转列表的内容。例如 [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).
prolog predicate
2个回答
0
投票

这是一种更有效的方法,因为遍历列表一次,而不是使用

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].

0
投票

我可能会做这样的事情:

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
,您所要做的就是:

  1. 将源列表分成左右两半。
  2. 反转右半边
  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) .
© www.soinside.com 2019 - 2024. All rights reserved.