假设我有一个包含 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)
这是一个更简单的解决方案 - 从某种意义上说,它的技术性较低 - 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)
我们可以枚举列表,每次看到零时,我们可以将它推送到元素列表中,以便稍后到达列表末尾时发出:
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)