我正在尝试用Prolog编写一个程序,该程序将包含三个列表(所有长度均相同)并返回一个列表列表。
我要返回的列表列表是一个三元组,其中包含要传入的三个列表中的元素。三元组的第一个元素来自传入的第一个列表,三元组的第二个元素来自于第二个列表,三元组的第三个元素来自传入的第三个列表。
我想要发生的是函数返回的三元组列表,以返回您可以从传入的三个列表中得出的每个单一可能组合。
截至目前,我有一些代码将三个列表的第一个元素取出,并从中取出三倍,然后将所有列表的第二个元素取出,并从其中取出三倍,依此类推。在下面。
listCombos( [], [], [], []).
listCombos( [A|AREST], [B|BREST], [C|CREST], [[A,B,C]|SOLUTION]) :-
listCombos( AREST, BREST, CREST, SOLUTION).
我获取每个组合的策略是获取第一个列表的第一个元素和第二个列表的第一个元素,然后遍历第三个列表的每个元素。完成此操作后,我将继续移动第一个列表中的第一个元素和第二个列表中的第二个元素,并将它们与第三个列表中的每个元素进行匹配。然后,在我浏览完第二个列表之后,移至第一个列表。让我知道是否需要对此进一步澄清。
我是Prolog的新手,所以我不明白如何将我打算做的事情变成代码。我已经尝试了一些方法,但是没有成功,并且得到了一些我不理解的错误代码,因此很难判断我是否朝着正确的方向前进(如果需要,我可以发表一些尝试)。如果有人对我应该前进的方向有所了解,或者对我需要做的事情有所解释,将不胜感激。
非常感谢您。
答案 0 :(得分:3)
了解一点Prolog,最明显的解决方案是这样的:
listCombos(Xs, Ys, Zs, Result) :-
findall([X,Y,Z],
(member(X, Xs), member(Y, Ys), member(Z, Zs)),
Result).
答案 1 :(得分:1)
我们首先可以解决一个相关的问题:给定一个“头” Hs
的列表和一个“尾巴” Ts
的列表,在{{ 1}},以及列表中H
中的所有尾巴Hs
。我们可以使用谓词来做到这一点:
T
例如:
Ts
现在我们可以使用它来制作带有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
使用上面的方法生成三组叉积应该很简单,我将其保留为练习。
答案 2 :(得分:1)
建议根据this answer中的模式,概括您要寻找的结构,接受要组合的列表的列表:
combine(Ls,Rs) :- maplist(member,Rs,Ls).
listCombos(A,B,C, SOLUTION) :- findall(R,combine([A,B,C],R),SOLUTION).
答案 3 :(得分:0)
The approach by Daniel Lyons的好处在于,它使我们可以轻松控制列表 list 的叉积中组合的顺序,同时保持组合中元素的顺序。一样,当然:
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).
它具有良好的模块化和关注点分离:表示顺序与生成顺序和选择顺序无关。