代码之家  ›  专栏  ›  技术社区  ›  sixtyfootersdude

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

  •  0
  • sixtyfootersdude  · 技术社区  · 15 年前

    我正在写一个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 回复  |  直到 11 年前
        1
  •  1
  •   Ed.    15 年前

    length(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].
    
        2
  •  0
  •   ony    15 年前

    另一个只有统一的变体。

    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'
    
    推荐文章