List Prolog创建列表
我正试图用Prolog编写一个程序,它将接收三个列表(所有列表的长度都相同)并返回一个列表列表 我返回的列表列表是一个三元组,其中包含传入的三个列表中的元素。三元组的第一个元素来自传入的第一个列表,三元组的第二个元素来自第二个列表,三元组的第三个元素来自传入的第三个列表 我想得到的是函数返回的三元组列表,它返回从传入的三个列表中生成的每一个可能的组合 到目前为止,我有一些代码,它获取三个列表的第一个元素并将其转换为三元组,然后获取所有列表的第二个元素并将其转换为三元组,依此类推。在下面List Prolog创建列表,list,prolog,cartesian-product,List,Prolog,Cartesian Product,我正试图用Prolog编写一个程序,它将接收三个列表(所有列表的长度都相同)并返回一个列表列表 我返回的列表列表是一个三元组,其中包含传入的三个列表中的元素。三元组的第一个元素来自传入的第一个列表,三元组的第二个元素来自第二个列表,三元组的第三个元素来自传入的第三个列表 我想得到的是函数返回的三元组列表,它返回从传入的三个列表中生成的每一个可能的组合 到目前为止,我有一些代码,它获取三个列表的第一个元素并将其转换为三元组,然后获取所有列表的第二个元素并将其转换为三元组,依此类推。在下面 l
listCombos( [], [], [], []).
listCombos( [A|AREST], [B|BREST], [C|CREST], [[A,B,C]|SOLUTION]) :-
listCombos( AREST, BREST, CREST, SOLUTION).
我获取每个组合的策略是获取第一个列表中的第一个元素和第二个列表中的第一个元素,然后遍历第三个列表中的每个元素。完成后,我将在第一个列表中的第一个元素和第二个列表中的第二个元素上移动,并将它们与第三个列表中的每个元素匹配。然后,在我看完第二个列表后,转到第一个列表。如果需要更多的澄清,请告诉我
我不熟悉Prolog,所以我不知道如何将我计划要做的事情转化为代码。我尝试了一些事情,但没有成功,并且得到了一些我不理解的错误代码,因此很难判断我是否朝着正确的方向前进(如果需要,我可以发布一些尝试)。如果有人对我应该走的方向有一些想法,或者对我需要做的事情有一些解释,我将不胜感激
非常感谢。了解一点序言最明显的解决方案如下:
listCombos(Xs, Ys, Zs, Result) :-
findall([X,Y,Z],
(member(X, Xs), member(Y, Ys), member(Z, Zs)),
Result).
了解一点序言,最明显的解决方案如下:
listCombos(Xs, Ys, Zs, Result) :-
findall([X,Y,Z],
(member(X, Xs), member(Y, Ys), member(Z, Zs)),
Result).
我们首先可以解决一个相关的问题:给定一个“头”
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]].
根据上面的内容,生成三个集合的叉积应该很简单,我把它留作练习。我们首先可以解决一个相关的问题:给定一个“heads”
Hs
列表和一个“tails”Ts
,在Hs
中为所有headsH
构建所有列表,以及列表中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]].
鉴于上述生成三个集合的叉积应该很简单,我将此作为一个练习。建议概括您正在寻找的构造,接受要组合的列表列表,遵循以下模式:
建议概括您正在寻找的构造,接受要组合的列表列表,遵循以下模式: 它的优点在于,它允许我们轻松控制列表叉积中的组合顺序,同时保持组合中元素的顺序不变,当然:
cross([],[[]])。
十字([XS | T],R):-
交叉(T,TC),
findall([X | Y],(%)或:
成员(Y,TC),%成员(X,XS)
成员(X,XS)%成员(Y,TC),
),
R) 。
它表现出良好的模块化和关注点分离:表示顺序独立于生成顺序和选择顺序。很好,它允许我们轻松控制列表交叉乘积中的组合顺序,同时保持组合中元素的顺序相同,当然:
cross([],[[]])。
十字([XS | T],R):-
交叉(T,TC),
findall([X | Y],(%)或:
成员(Y,TC),%成员(X,XS)
成员(X,XS)%成员(Y,TC),
),
R) 。
它表现出良好的模块化和关注点分离:表示顺序独立于生成顺序和选择顺序。哦,你想要笛卡尔积吗?你一直在问同样的问题。这是不对的。你应该回答你已经提出的问题,要求澄清,说出不清楚的地方。相反,你消失了,重新问同样的问题。这不是它应该如何工作的。可能是重复的哦,你想要一个笛卡尔积吗?你一直在问同样的问题。这是不对的。你应该回答你已经提出的问题,要求澄清,说出不清楚的地方。相反,你消失了,重新问同样的问题。这不是它应该如何工作的。纯解的可能复制在Prolog中非常困难,不是吗。好吧,递归是可以管理的,但在向前的迭代(或自顶向下)风格中很难做到。@WillNess我太累了,不知道怎么做,否则我会把它添加到我的ans中