Prolog:如何使三个列表具有相同的长度(通过添加前导零)

时间:2010-06-05 20:52:02

标签: 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( [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] )

关于如何实现这一点的任何要点都会很棒。我来自功能背景,所以我很挣扎。有没有办法告诉列表的长度?我想我可以递归地做到这一点,但这看起来很痛苦。

2 个答案:

答案 0 :(得分:1)

长度(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).

只需传递列表和最终列表的大小。

?- compZeros([1], 4, L).
L = [0, 0, 0, 1] 

?- compZeros([1, 2, 3], 4, L).
L = [0, 1, 2, 3] 

?- compZeros([1, 2, 3, 4], 4, L).
L = [1, 2, 3, 4].

答案 1 :(得分:0)

另一种仅使用统一的变体。

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]

P.S。不要在反向变体中尝试这些谓词 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'