如何尽可能地向左移动元素?序言

Ree*_*han 4 prolog

假设我有一个包含 4 个元素 [0,4,0,2] 的列表(可以是任何排列)。列表中的每个元素都会向左移动。如果元素邻居为零,则它可以轻松向左移动。如果邻居是非零数,则它不能向左移动。(例如:[8,0,2,3] 会变成 [8,2,3,0],而 [0,4,0,2] 会变成 [4,2,0,0])

这是我目前的尝试:

shift_left([],_):-!.
shift_left([H1,H2|T],S):-
    H1=0,
    append(S,[H2|T],L1),
    write(L1),
    shift_left([H2|T],_).
shift_left([H1|T],_):-
    H1\=0,
    shift_left(T,[H1]).
Run Code Online (Sandbox Code Playgroud)

看了 CapelliC 的回答后,我的第二次尝试。它工作得很好。

shift_left([],[]).
shift_left([H|T],S):-
    shift_left(T,Q),
    H=0,
    append(Q,[0],S).
shift_left([H|T],S):-
    shift_left(T,Q),
    H\=0,
    S=[H|Q].
Run Code Online (Sandbox Code Playgroud)

Cap*_*liC 6

这是一个更简单的解决方案 - 从某种意义上说,它的技术性较低 - wrt Willem 的回答,并使用 append/3 作为您的原始代码

shift_left([],[]).
shift_left([H|T],S):-
    shift_left(T,Q),
    (   H=0
    ->  append(Q,[0],S)
    ;   S=[H|Q]
    ).
Run Code Online (Sandbox Code Playgroud)

测试

?- maplist(shift_left,[[8,0,2,3],[0,4,0,2]],Ss).
Ss = [[8, 2, 3, 0], [4, 2, 0, 0]].
Run Code Online (Sandbox Code Playgroud)


Wil*_*sem 5

我们可以枚举列表,每次看到零时,我们可以将它推送到元素列表中,以便稍后到达列表末尾时发出:

shift_left(L, R) :-
    shift_left(L, [], R).

shift_left([], Zs, Zs).
shift_left([H|T], Zs, [H|R]) :-
    dif(H, 0),
    shift_left(T, Zs, R).
shift_left([0|T], Zs, R) :-
    shift_left(T, [0|Zs], R).
Run Code Online (Sandbox Code Playgroud)

这给我们:

?- shift_left([8,0,2,3], R).
R = [8, 2, 3, 0] ;
false.

?- shift_left([0,4,0,2], R).
R = [4, 2, 0, 0] ;
false.
Run Code Online (Sandbox Code Playgroud)