Merge 序言列表问题
当我结结巴巴地思考这个问题时,我正试图理解prolog中的列表: 有一个谓词mergeandmap/2基本上应该做到这一点: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
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])
任何帮助都将不胜感激 由于每个列表都保证具有相同的长度,因此您可以轻松细分问题(类似于“分而治之”)。首先递归地遍历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).