简体   繁体   English

Prolog 创建列表

[英]Prolog creating lists

I'm trying to write a program in Prolog that will take in three lists (all of which are the same length) and return a list of lists.我正在尝试在 Prolog 中编写一个程序,该程序将接收三个列表(所有列表的长度都相同)并返回一个列表列表。

The list of lists that I am returning is a triple that contains elements from the three lists that are being passed in. The first element of the triple is from the first list passed in, the second element of the triple is from the second list, and the third element of the triple is from the third list passed in.我要返回的列表列表是一个三元组,其中包含来自传入的三个列表的元素。三元组的第一个元素来自传入的第一个列表,三元组的第二个元素来自第二个列表,三元组的第三个元素来自传入的第三个列表。

What I want to have happen is the list of triples that the function is returning to return every single possible combination that you could make from the three lists being passed in.我想要发生的是函数返回的三元组列表,以返回您可以从传入的三个列表中创建的每个可能的组合

As of now I have some code that takes the first elements of the three lists and makes a triple out of them, then takes the second element of all the lists and makes a triple out of them, and so on.到目前为止,我有一些代码可以获取三个列表的第一个元素并从中生成一个三元组,然后获取所有列表的第二个元素并从中生成一个三元组,依此类推。 Here it is below.这是下面。

   listCombos( [], [], [], []).
   listCombos( [A|AREST], [B|BREST], [C|CREST], [[A,B,C]|SOLUTION]) :-
       listCombos( AREST, BREST, CREST, SOLUTION).

My strategy for getting every combo is taking the first element of the first list and the first element in the second list and then going through each elements in the third list.我获取每个组合的策略是获取第一个列表的第一个元素和第二个列表中的第一个元素,然后遍历第三个列表中的每个元素。 Once I have done that I will move on the the first element in the first list and the second element in the second list and match those up with each element in the third list.完成后,我将移动第一个列表中的第一个元素和第二个列表中的第二个元素,并将它们与第三个列表中的每个元素进行匹配。 Then after I have went through the second list move onto the first list.然后在我浏览完第二个列表后移动到第一个列表。 Let me know if more clarification on this is needed.如果需要对此进行更多说明,请告诉我。

I'm new to Prolog so I don't understand how to turn what I'm planning to do into code.我是 Prolog 的新手,所以我不明白如何将我打算做的事情变成代码。 I've tried a few things but haven't been successful and have gotten some error codes I don't understand so it's hard to tell if I'm going in the right direction (I can post some of my attempts if needed).我已经尝试了一些东西,但没有成功,并且得到了一些我不明白的错误代码,所以很难判断我是否朝着正确的方向前进(如果需要,我可以发布一些我的尝试)。 If anyone has some idea of what direction I should go in or some explanation on what I need to do that would be appreciated.如果有人知道我应该朝哪个方向前进,或者对我需要做的事情有一些解释,那将不胜感激。

Thank you very much.非常感谢。

Knowing a little Prolog the most obvious solution is something like this:了解一点 Prolog 最明显的解决方案是这样的:

listCombos(Xs, Ys, Zs, Result) :-
    findall([X,Y,Z], 
            (member(X, Xs), member(Y, Ys), member(Z, Zs)),
            Result).

It's advisable to generalize the construct you're looking for, accepting a list of lists to be combined, following the schema from this answer :建议概括您正在寻找的构造,接受要组合的列表列表,遵循此答案中的架构:

combine(Ls,Rs) :- maplist(member,Rs,Ls).

listCombos(A,B,C, SOLUTION) :- findall(R,combine([A,B,C],R),SOLUTION).

We first can solve a related problem: given a list of "heads" Hs and a list of "tails" Ts , construct all lists for all heads H in Hs , and all tails T in Ts in a list.我们首先可以解决一个相关的问题:给定一个“头”列表Hs和一个“尾”列表Ts ,构造一个列表中Hs所有头HTs中所有尾T所有列表。 We can do this with a predicate:我们可以用一个谓词来做到这一点:

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

For example:例如:

?- merge_all([a, b], [[1, 4], [2, 5]], R).
R = [[a, 1, 4], [a, 2, 5], [b, 1, 4], [b, 2, 5]].

Now we can use this for example to make all cross products with Cs and the "empty set", for example if Cs = [a, b, c] , then:现在我们可以使用它来制作所有带有Cs和“空集”的叉积,例如,如果Cs = [a, b, c] ,则:

?- merge_all([a, b, c], [[]], RC).
RC = [[a], [b], [c]].

Given we have this result, we can make the cross product of Bs with this result.鉴于我们有这个结果,我们可以用这个结果做Bs的叉积。 For example if Bs = [1, 4] , then we obtain:例如,如果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]].

With the above generating the cross product of three sets should be straightforward, I leave this as an exercise.上面生成三组的叉积应该很简单,我把它留作练习。

The approach by Daniel Lyons is good in that it allows us to easily control the order of combinations in the cross-product of a list of lists, while keeping the order of elements in the combinations the same, of course: 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).

It exhibits good modularity and separation of concerns: the order of presentation is independent of the order of generation and the order of selection.它表现出良好的模块化和关注点分离:呈现顺序与生成顺序和选择顺序无关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM