Prolog 序言:如何使三个列表的长度相同(通过添加前导零)
我正在写一个Prolog程序来解决一个问题。该问题以三个列表作为输入:Prolog 序言:如何使三个列表的长度相同(通过添加前导零),prolog,Prolog,我正在写一个Prolog程序来解决一个问题。该问题以三个列表作为输入: solve( [L|Lr] , [R|Rr] , [S|Sr] ) :- 不幸的是,列表的长度必须相等,程序才能工作 因此,这些工作: ?- solve( [A, B, C, D] , [1, 3, 5, 6], [E, F, G, H]). ?- solve( [1] , [2], [3]). 但这些并不是: ?- solve( [A, B, C, D], [1], [B, I, T] ). ?- solve( [
solve( [L|Lr] , [R|Rr] , [S|Sr] ) :-
不幸的是,列表的长度必须相等,程序才能工作
因此,这些工作:
?- solve( [A, B, C, D] , [1, 3, 5, 6], [E, F, G, H]).
?- solve( [1] , [2], [3]).
但这些并不是:
?- solve( [A, B, C, D], [1], [B, I, T] ).
?- solve( [A], [1, 2], [4, 5]).
我想做的是写一个谓词(?)用前导零填充较小的列表。因此:
solve( [A, B, C, D], [1], [B, I, T] )
将成为:
solve( [A, B, C, D], [0, 0, 0, 1], [0, B, I, T] )
关于如何实现这一点的任何观点都将非常棒。我来自功能性背景,所以我很努力。有没有办法说出一张清单的长度?我想我可以反复这么做,但这似乎很痛苦 长度(List,length)谓词用于获取列表的长度。我做了一个小程序,将前导零放入一个列表中
addZeros(L, 0, L).
addZeros(L, 1, [0|L]).
addZeros(L, N, [0|FL]) :-
N2 is N - 1,
addZeros(L, N2, FL).
compZeros(_, 0, []).
compZeros(L, N, FL) :-
length(L, S),
S < N,
N2 is N - S,
addZeros(L, N2, FL).
compZeros(L, _, L).
另一个仅使用统一的变体
padZerosPrep(L, [], L).
padZerosPrep(L, [_|T], [0|R]):- padZerosPrep(L, T, R).
padZerosWalk([], [], La, Lb, La, Lb).
padZerosWalk([], [_|_], La, Lb, La, Lb).
padZerosWalk([_|_], [], La, Lb, La, Lb).
padZerosWalk([_|La0], [_|Lb0], [_|La1], [_|Lb1], La, Lb):-
padZerosWalk(La0, Lb0, La1, Lb1, La, Lb).
padZeros(La0, Lb0, La, Lb):-
padZerosPrep(La0, Lb0, La1),
padZerosPrep(Lb0, La0, Lb1),
padZerosWalk(La0, Lb0, La1, Lb1, La, Lb).
只需传递两个列表,并记住第二对列表将具有相同的长度:
?- padZeros([1,2,3],[4,5,6],A,B).
A = [1, 2, 3],
B = [4, 5, 6]
?- padZeros([1,2,3],[4,5],A,B).
A = [1, 2, 3],
B = [0, 4, 5]
?- padZeros([2,3],[4,5,6],A,B).
A = [0, 2, 3],
B = [4, 5, 6]
?- La=[A,B,C,D], Lb = [1], Lc=[B,I,T], padZeros(La, Lb, La1, Lb1), padZeros(La1, Lc, La2, Lc2), padZeros(Lb1, Lc, Lb2, Lc2).
La = [A, B, C, D],
Lb = [1],
Lc = [B, I, T],
La1 = [A, B, C, D],
Lb1 = [0, 0, 0, 1],
La2 = [A, B, C, D],
Lc2 = [0, B, I, T],
Lb2 = [0, 0, 0, 1]
?- Lc=[A,B,C,D], Lb = [1], La=[B,I,T], padZeros(La, Lb, La1, Lb1), padZeros(La1, Lc, La2, Lc2), padZeros(Lb1, Lc, Lb2, Lc2).
Lc = [A, B, C, D],
Lb = [1],
La = [B, I, T],
La1 = [B, I, T],
Lb1 = [0, 0, 1],
La2 = [0, B, I, T],
Lc2 = [A, B, C, D],
Lb2 = [0, 0, 0, 1]
注意,不要用反向变体尝试这些谓词。Haskell中的相同变体:
padZeros :: (Num a, Num b) => [a] -> [b] -> ([a], [b])
padZeros a b = walk (zip a b) pa pb where
pa = map (const 0) b ++ a
pb = map (const 0) a ++ b
walk [] a' b' = (a', b')
walk (_:xs) (_:a') (_:b') = walk xs a' b'
太棒了,谢谢你,ed,我当时很难理解这一点。然而,我认为你的第二个基本情况下添加零是多余的。
padZeros :: (Num a, Num b) => [a] -> [b] -> ([a], [b])
padZeros a b = walk (zip a b) pa pb where
pa = map (const 0) b ++ a
pb = map (const 0) a ++ b
walk [] a' b' = (a', b')
walk (_:xs) (_:a') (_:b') = walk xs a' b'