简体   繁体   English

计算prolog中列表的排列

[英]Counting permutations of a list in prolog

There is a question is in Art of prolog 2nd edition where you are supposed to define a predicate even_permutation(Xs,Ys) and similarly odd permutations which when you query for example even_permutation([1,2,3],[2,3,1]) and odd_permutation([1,2,3],[2,1,3]) are true.These predicates should be able to work on a random list and determine if a permutation of that list is in an odd or even position. 在prolog第2版的Art中有一个问题,你应该定义一个谓词even_permutation(Xs,Ys)和类似的奇数排列,当你查询例如even_permutation([1,2,3],[2,3, 1])和odd_permutation([1,2,3],[2,1,3])是真的。这些谓词应该能够在随机列表上工作,并确定该列表的排列是奇数还是偶数位置。 I have my predicate for pemutation as shown. 如图所示,我的断言是谓词。

permutation([],[]).
permutation(Xs,[Z|Zs]):-select(Z,Xs,Ys), permutation(Ys,Zs).
select(X,[X|Xs],Xs).
select(X,[Y|Ys],[Y|Zs]):- select(X,Ys,Zs).

I have an idea where i count the number of permutations of the list and group them into even and odd permutations then my query can determine whether a permutaion is odd or even but i have no idea how to implement it. 我有一个想法,我计算列表的排列数,并将它们分为偶数和奇数排列然后我的查询可以确定permutaion是奇数还是偶数但我不知道如何实现它。 If there is a better way to do it please tell me. 如果有更好的方法,请告诉我。

I know the original question was posted quite some time ago, but I was very recently working through some of the problems in The Art Of Prolog as well and thought over the even/odd permutation problem for a few days. 我知道最初的问题是在很久以前发布的,但我最近也在研究Prolog的Art一些问题并且考虑了偶数/奇数排列问题几天。 I didn't want to open a duplicate problem, so I'm posting my solution here. 我不想打开一个重复的问题,所以我在这里发布我的解决方案。

The problem in the book asks: 书中的问题是:

Write programs for even_permutation(Xs, Ys) and odd_permutation(Xs, Ys) that find Ys , the even and odd permutations, respectively, of a list Xs . 编写even_permutation(Xs, Ys)odd_permutation(Xs, Ys) ,它们分别找到列表Xs Ys ,偶数和奇数排列。 For example, even_permutation([1,2,3], [2,3,1]) and odd_permutation([1,2,3], [2,1,3]) are true. 例如, even_permutation([1,2,3], [2,3,1])odd_permutation([1,2,3], [2,1,3])都是正确的。

So it's asking for permutation generators, not just verifiers. 所以它要求排列生成器,而不仅仅是验证器。 @hardmath has provided a link to the correct definition of even or odd permutation. @hardmath提供了偶数或奇数排列的正确定义的链接。 The authors of the book gave two simple examples to illustrate. 本书的作者给出了两个简单的例子来说明。

For me, the key was figuring out a recursive definition for an even or odd permutation. 对我来说,关键在于找出偶数或奇数排列的递归定义。 For all permutations, the classical permutation generator in Prolog uses the following notion: 对于所有排列,Prolog中的经典置换生成器使用以下概念:

  • Every permutation of N+1 elements is a list representing a permutation of N of the elements with the (N+1)st element inserted into the list. N + 1个元素的每个排列是表示插入列表中的(N + 1)个元素的N个元素的排列的列表。

The predicate select or insert is used to do the insertion. 谓词selectinsert用于进行插入。

For even and odd permutations, I considered a similar idea: 对于偶数和奇数排列,我考虑了类似的想法:

  • Every even permutation of N+1 elements is either a list representing an even permutation of N of the elements with the (N+1)st element inserted at an odd position in the list, or a list representing an odd permutation of N of the elements with the (N+1)st element inserted at an even position in the list. N + 1个元素的每一个偶数排列或者是列表表示N的偶数排列与第(N + 1)在该列表中的奇数位置插入的元素,或较的N 奇数排列的列表中的元素的具有(N + 1)st元素的元素插入列表中的偶数位置。

  • Every odd permutation of N+1 elements is either a list representing an odd permutation of N of the elements with the (N+1)st element inserted at an odd position in the list, or a list representing an even permutation of N of the elements with the (N+1)st element inserted at an even position in the list. N + 1个元素的每个奇数排列是表示N个元素的奇数排列的列表,其中(N + 1)个元素插入列表中的奇数位置,或者列表表示N的偶数排列。具有(N + 1)st元素的元素插入列表中的偶数位置。

The rational is that the insertion of an element at an odd position represents an even number of swaps relative to the original list (the front of the list, being the first position, requires no swaps, so it's even). 理性的是,在奇数位置插入元素表示相对于原始列表的偶数交换(列表的前面,作为第一个位置,不需要交换,所以它是偶数)。 Similarly, the insertion of an element at an even position represents an odd number of swaps relative to the original list. 类似地,在偶数位置插入元素表示相对于原始列表的奇数个交换。

If I add to this the rule that the empty list is it's own even permutation, then I can define the following predicates as follows to generate the even and odd permutations: 如果我添加一个规则,即空列表是它自己的偶数排列,那么我可以如下定义以下谓词来生成偶数和奇数排列:

even_permutation( [], [] ).
even_permutation( [X|T], Perm ) :-
    even_permutation( T, Perm1 ),
    insert_odd( X, Perm1, Perm ).
even_permutation( [X|T], Perm ) :-
    odd_permutation( T, Perm1 ),
    insert_even( X, Perm1, Perm ).

odd_permutation( [X|T], Perm ) :-
    odd_permutation( T, Perm1 ),
    insert_odd( X, Perm1, Perm ).
odd_permutation( [X|T], Perm ) :-
    even_permutation( T, Perm1 ),
    insert_even( X, Perm1, Perm ).

insert_odd( X, InList, [X|InList] ).
insert_odd( X, [Y,Z|InList], [Y,Z|OutList] ) :-
    insert_odd( X, InList, OutList ).

insert_even( X, [Y|InList], [Y,X|InList] ).
insert_even( X, [Y,Z|InList], [Y,Z|OutList] ) :-
    insert_even( X, InList, OutList ).

Here's a high-level description of how to determine if a permutation is even or odd, in the usual sense of the terms . 以下是关于如何通过术语的通常意义确定排列是偶数还是奇数的高级描述。

Convert the permutation into a product of disjoint cycles. 将置换转换为不相交周期的乘积。 The parity of the permutation is the sum of parities of its factors (even times even or odd times odd is even, odd times even or even times odd is odd). 置换的奇偶性是其因子的奇偶性的总和(偶数偶数或奇数倍奇数是偶数,奇数倍偶数或偶数奇数是奇数)。 A cycle of odd length is an even permutation, and a cycle of even length is an odd permutation. 奇数长度的循环是偶数排列,偶数长度的循环是奇数排列。 For example, a cycle of length one is the identity permutation and thus (expressed as the empty product of transpositions) is an even permutation. 例如,长度为1的循环是身份置换,因此(表示为换位的空积)是偶数置换。

Finding the product of disjoint cycles representation can be done in your setup by picking an item from the first list, looking up where it gets mapped by the corresponding location in the second list, and repeating this lookup with the image of each succeeding item until the cycle returns to the item at the beginning of the first list. 通过从第一个列表中选择一个项目,查找第二个列表中相应位置的映射位置,并使用每个后续项目的图像重复此查找,直到找到不相交周期表示的产品。 cycle返回第一个列表开头的项目。 The list of successive images will be disjoint from the orbits of items not in the list, so consider them eliminated and begin finding the next disjoint cycle with the first item of the first list that is not yet eliminated. 连续图像的列表将与不在列表中的项目的轨道不相交,因此考虑它们被消除并开始使用尚未消除的第一列表的第一项找到下一个不相交的循环。 Eventually all the items in the first list will be eliminated, having been incorporated into one or another of the constructed cycles. 最终,第一个列表中的所有项目都将被删除,并已合并到一个或另一个构建的周期中。

Other approaches to determining the parity of a given permutation are described in the article linked above. 确定给定排列的奇偶性的其他方法在上面链接的文章中描述。 If you really wish to enumerate only even permutations (resp. only odd permutations), one approach is to modify the enumeration of all permutations in a way that returns only permutations of the same parity (cf. that section and the one following). 如果你真的希望仅列举偶数排列(仅仅是奇数排列),一种方法是修改所有排列的枚举,只返回相同奇偶校验的排列(参见该部分和后面的部分)。

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

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