Merge 序言列表问题

Merge 序言列表问题,merge,map,list,prolog,Merge,Map,List,Prolog,当我结结巴巴地思考这个问题时,我正试图理解prolog中的列表: 有一个谓词mergeandmap/2基本上应该做到这一点: mergeandmap([[a1,...,an],...,[z1,...,zm]],[x1...xn]) %----------list 1------------ -list 2-- 清单2由字母组成(例如[a、b、c])。 列表1由多个列表组成,其大小(列表2)元素包含1和0 (例如:[[0,0,1],[1,0,1],[0,1,1]) pro

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

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

mergeandmap([[a1,...,an],...,[z1,...,zm]],[x1...xn])
            %----------list 1------------ -list 2--
清单2由字母组成(例如[a、b、c])。 列表1由多个列表组成,其大小(列表2)元素包含1和0 (例如:[[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])
  • “合并”列表到新列表中:通过将所有第一个子元素、所有第二个子元素、所有第三个子元素等放在一起…->[ADG、BEH、CFI]
  • (1)结果的“映射”第二个列表:

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

  • ->大写字母的值决定结果中是否包含小写字母

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

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

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


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

    这是您所说内容的一个实现,完全按照您的规范在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]].
    
    编写自己的转置函数要复杂一些,因为我决定自己尝试一下。过了一会儿,我终于找到了一个非常简洁的解决方案,通过设计,它能够接受列表列表,即使它们不是矩形的!(遗憾的是,它仍然没有在mergeandmap中使用所需的灵活性)。代码如下:

    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).
    

    第四个例子也错了,应该是:bcd ac abc abcNo,Joel和Frank,你们都错了。如果列表的第n个元素为1,则第n个字母位于第n个字符串中。即。mergeandmap([[0,1],[1,0],[1,0],[a,b,c])='bc a'因此应该阅读第一个示例,a在第三个字符串中,b在第一个和第三个字符串中,c在第二个和第三个字符串中。Chris明确指出:“列表1由多个列表组成,其大小(列表2)元素包含1和0(例如:[[0,0,1],[1,0,1],[0,1],[0,1])”我建议克里斯澄清他想做什么@KernelJ:你的例子中的0/1大小为2的列表和一个大小为3的字符列表显然不符合上面的说法。事实上,这个特定的句子是一个错误。然而,问题的其余部分与我的解释和意图是一致的。它应该是“列表1由大小(列表2)列表组成,每个列表在{0,1}中有n个元素”。
    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).