[英]Prolog creating lists
我正在尝试在 Prolog 中编写一个程序,该程序将接收三个列表(所有列表的长度都相同)并返回一个列表列表。
我要返回的列表列表是一个三元组,其中包含来自传入的三个列表的元素。三元组的第一个元素来自传入的第一个列表,三元组的第二个元素来自第二个列表,三元组的第三个元素来自传入的第三个列表。
我想要发生的是函数返回的三元组列表,以返回您可以从传入的三个列表中创建的每个可能的组合。
到目前为止,我有一些代码可以获取三个列表的第一个元素并从中生成一个三元组,然后获取所有列表的第二个元素并从中生成一个三元组,依此类推。 这是下面。
listCombos( [], [], [], []).
listCombos( [A|AREST], [B|BREST], [C|CREST], [[A,B,C]|SOLUTION]) :-
listCombos( AREST, BREST, CREST, SOLUTION).
我获取每个组合的策略是获取第一个列表的第一个元素和第二个列表中的第一个元素,然后遍历第三个列表中的每个元素。 完成后,我将移动第一个列表中的第一个元素和第二个列表中的第二个元素,并将它们与第三个列表中的每个元素进行匹配。 然后在我浏览完第二个列表后移动到第一个列表。 如果需要对此进行更多说明,请告诉我。
我是 Prolog 的新手,所以我不明白如何将我打算做的事情变成代码。 我已经尝试了一些东西,但没有成功,并且得到了一些我不明白的错误代码,所以很难判断我是否朝着正确的方向前进(如果需要,我可以发布一些我的尝试)。 如果有人知道我应该朝哪个方向前进,或者对我需要做的事情有一些解释,那将不胜感激。
非常感谢。
了解一点 Prolog 最明显的解决方案是这样的:
listCombos(Xs, Ys, Zs, Result) :-
findall([X,Y,Z],
(member(X, Xs), member(Y, Ys), member(Z, Zs)),
Result).
建议概括您正在寻找的构造,接受要组合的列表列表,遵循此答案中的架构:
combine(Ls,Rs) :- maplist(member,Rs,Ls).
listCombos(A,B,C, SOLUTION) :- findall(R,combine([A,B,C],R),SOLUTION).
我们首先可以解决一个相关的问题:给定一个“头”列表Hs
和一个“尾”列表Ts
,构造一个列表中Hs
所有头H
和Ts
中所有尾T
所有列表。 我们可以用一个谓词来做到这一点:
merge_all([], _, []).
merge_all([H|Hs], Ts, All) :-
merge_single(Ts, H, All, D),
merge_all(Hs, Ts, D).
merge_single([], _, D, D).
merge_single([T|Ts], H, [[H|T]|Rest], D) :-
merge_single(Ts, H, Rest, D).
例如:
?- merge_all([a, b], [[1, 4], [2, 5]], R).
R = [[a, 1, 4], [a, 2, 5], [b, 1, 4], [b, 2, 5]].
现在我们可以使用它来制作所有带有Cs
和“空集”的叉积,例如,如果Cs = [a, b, c]
,则:
?- merge_all([a, b, c], [[]], RC).
RC = [[a], [b], [c]].
鉴于我们有这个结果,我们可以用这个结果做Bs
的叉积。 例如,如果Bs = [1, 4]
,那么我们得到:
?- merge_all([a, b, c], [[]], RC), merge_all([1, 4], RC, RB).
RC = [[a], [b], [c]],
RB = [[1, a], [1, b], [1, c], [4, a], [4, b], [4, c]].
上面生成三组的叉积应该很简单,我把它留作练习。
Daniel Lyons 的方法很好,因为它允许我们轻松控制列表列表的叉积中的组合顺序,同时保持组合中元素的顺序相同,当然:
cross( [], [[]] ).
cross( [XS | T], R ):-
cross( T, TC),
findall( [X | Y], ( % or:
member( Y, TC), % member( X, XS)
member( X, XS) % member( Y, TC),
),
R).
它表现出良好的模块化和关注点分离:呈现顺序与生成顺序和选择顺序无关。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.