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

序言列表问题

  •  0
  • Chris  · 技术社区  · 16 年前

    当我结结巴巴地思考这个问题时,我正试图理解prolog中的列表:

    有一个谓词mergeandmap/2基本上应该做到这一点:

    mergeandmap([[a1,...,an],...,[z1,...,zm]],[x1...xn])
                %----------list 1------------ -list 2--
    

    清单2由字母组成(例如[a、b、c])。 (例如:[[0,0,1],[1,0,1],[0,1,1])

    prolog程序应根据列表1确定应打印列表2中的哪些元素以及打印时间。

    对于上述示例:

    ([[0,0,1],[1,0,1],[0,1,1]],[a,b,c])  Result:  b c abc
    

    另一个例子:

    ([[0,1,1],[1,0,1],[1,1,1]],[a,b,c])  Result:  bc ac abc
    ([[0,1],[1,0]],[a,b])  Result:  b a
    ([[0,1,1,1],[1,0,1,0],[1,1,1,0],[1,1,1,0]],[a,b,c,d])  Result:  bcd acd abcd a
    

    我想到了这个主意:

    ([[A,B,C],[D,E,F],[G,H,I]],[a,b,c])
    
    1. (1)结果的“映射”第二个列表:

      [ADG,BEH,CFI]+[abc,abc,abc]

    有人知道如何在prolog中实现这一点吗? 任何帮助都将不胜感激!

    2 回复  |  直到 16 年前
        1
  •  0
  •   KernelJ    16 年前

    这是您所说内容的一个实现,完全按照您的规范在prolog中完成。您的“Merge”实际上是一个名为transpose的函数(在矩阵的上下文中),它恰好位于一个SWI Prolog库中!

    1 ?- [user].
    |: mergeandmap(Bss,Ls) :- transpose(Bss,BssT), write('Result: '), maptostrings(BssT,Ls), write('\n').
    |: maptostrings([],_).
    |: maptostrings([Bs|Bss],Ls) :- write(' '), zipstringbits(Bs,Ls), maptostrings(Bss,Ls).
    |: zipstringbits([],_).
    |: zipstringbits([0|Bs],[_|Ls]) :- zipstringbits(Bs,Ls).
    |: zipstringbits([1|Bs],[L|Ls]) :- write(L), zipstringbits(Bs,Ls).
    |: :- use_module(library(clpfd)).
    %    library(error) compiled into error 0.01 sec, 10,056 bytes
    %   library(apply) compiled into apply 0.02 sec, 16,256 bytes
    %   library(lists) compiled into lists 0.00 sec, 13,404 bytes
    %   library(pairs) compiled into pairs 0.01 sec, 4,772 bytes
    %  library(clpfd) compiled into clpfd 0.32 sec, 367,328 bytes
    |: 
    % user://1 compiled 0.44 sec, 369,348 bytes
    true.
    
    2 ?- mergeandmap([[0,0,1],[1,0,1],[0,1,1]],[a,b,c]).
    Result:  b c abc
    true .
    
    3 ?- mergeandmap([[0,1,1],[1,0,1],[1,1,1]],[a,b,c]).
    Result:  bc ac abc
    true .
    
    4 ?- mergeandmap([[0,1],[1,0]],[a,b]).
    Result:  b a
    true .
    
    5 ?- mergeandmap([[0,1,1,1],[1,0,1,0],[1,1,1,0],[1,1,1,0]],[a,b,c,d]).
    Result:  bcd acd abcd a
    true .
    
    6 ?- mergeandmap([[0,1],[1,0],[1,0]],[a,b,c]).
    Result:  bc a
    true .
    
    7 ?- transpose([[A,B,C],[D,E,F],[G,H,I]],X).
    X = [[A, D, G], [B, E, H], [C, F, I]].
    

    1 ?- [user].
    |: transpose(Rs,Cs) :- emptylists(Rs),emptylists(Cs).
    |: transpose([[X|R]|Rs],[[X|C]|Cs]) :- headsandtails(Rs,C,NRs), headsandtails(Cs,R,NCs), transpose(NRs,NCs).
    |: headsandtails(Xss,[],[]) :- emptylists(Xss).
    |: headsandtails([[X|Xs]|Xss],[X|Hs],[Xs|Ts]) :- headsandtails(Xss,Hs,Ts).
    |: emptylists([]) :- !.
    |: emptylists([[]|L]) :- emptylists(L).
    |: 
    % user://1 compiled 0.07 sec, 1,208 bytes
    true.
    
    2 ?- transpose([[1,2,3,4],[5,6,7],[8,9],[10]],Result).
    Result = [[1, 5, 8, 10], [2, 6, 9], [3, 7], [4]] ;
    false.
    
    3 ?- transpose([[1,2,3,4],[5,6,7],[8,9,10,11],[10]],Result).
    false.
    
    4 ?- transpose([[1,2,3,4,5,7,8,3],[5,6,7],[8,9,10,11],[10]],Result).
    false.
    
    5 ?- transpose([[1,2,3,4,5,7,8,3],[5,6,7],[8,9,99],[10]],Result).
    Result = [[1, 5, 8, 10], [2, 6, 9], [3, 7, 99], [4], [5], [7], [8], [3]] ;
    false.
    

    基本上这是如何工作的,它检查转置的左上角元素和原始元素是否相同,检查其中一个元素的左上角行是否与另一个元素的左上角列匹配,反之亦然,然后迭代检查所有其他元素,直到无需检查为止。

    切割操作员!在EmptyList上,谓词阻止答案向右扩展,并使用更多的空列表,这意味着它可以在尝试转置没有空列表的内容时终止(它只是不断添加它们,并且总是找不到答案)。

    总而言之,对于一体式解决方案,以下是您所需的全部代码:

    mergeandmap(Bss,Ls) :- transpose(Bss,BssT), write('Result: '), maptostrings(BssT,Ls), write('\n').
    maptostrings([],_).
    maptostrings([Bs|Bss],Ls) :- write(' '), zipstringbits(Bs,Ls), maptostrings(Bss,Ls).
    zipstringbits([],_).
    zipstringbits([0|Bs],[_|Ls]) :- zipstringbits(Bs,Ls).
    zipstringbits([1|Bs],[L|Ls]) :- write(L), zipstringbits(Bs,Ls).
    transpose(Rs,Cs) :- emptylists(Rs),emptylists(Cs).
    transpose([[X|R]|Rs],[[X|C]|Cs]) :- headsandtails(Rs,C,NRs), headsandtails(Cs,R,NCs), transpose(NRs,NCs).
    headsandtails(Xss,[],[]) :- emptylists(Xss).
    headsandtails([[X|Xs]|Xss],[X|Hs],[Xs|Ts]) :- headsandtails(Xss,Hs,Ts).
    emptylists([]) :- !.
    emptylists([[]|L]) :- emptylists(L).
    
        2
  •  0
  •   Frank    16 年前

    由于每个列表都保证具有相同的长度,因此您可以轻松细分问题(类似于“分而治之”)。首先递归地遍历0/1列表,并为每个列表创建相应的输出(同样是递归的)。

    mergeandmap([], _).
    mergeandmap([X|Xs], Y) :- helper(X, Y), mergeandmap(Xs, Y).
    

    以类似的方式,您可以用3行代码编写helper谓词:基本大小写(空列表)、0元素和1元素。由于X和Y都具有相同的长度,因此每个递归谓词都会删除列表的head元素。我认为,这应该使人们大致了解如何实现这一结果。

    顺便说一下,你上面的第一个例子似乎是错误的。结果应该是c ac bc。

    推荐文章