Math prolog中列表的计数置换

Math prolog中列表的计数置换,math,prolog,Math,Prolog,prolog第二版的艺术中有一个问题,你应该定义一个谓词偶数置换(Xs,Ys)和类似的奇数置换,当你查询偶数置换([1,2,3],[2,3,1])和奇数置换([1,2,3],[2,1,3])这些谓词应该能够处理随机列表,并确定该列表的排列是否处于奇数或偶数位置。我有我的pemutate谓词,如图所示 permutation([],[]). permutation(Xs,[Z|Zs]):-select(Z,Xs,Ys), permutation(Ys,Zs). select(X,[X|Xs],Xs

prolog第二版的艺术中有一个问题,你应该定义一个谓词偶数置换(Xs,Ys)和类似的奇数置换,当你查询偶数置换([1,2,3],[2,3,1])和奇数置换([1,2,3],[2,1,3])这些谓词应该能够处理随机列表,并确定该列表的排列是否处于奇数或偶数位置。我有我的pemutate谓词,如图所示

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

我有一个想法,我计算列表中排列的数量,并将它们分组为偶数和奇数排列,然后我的查询可以确定排列是奇数还是偶数,但我不知道如何实现它。如果有更好的方法,请告诉我

下面是如何确定排列是偶数还是奇数的高级描述

将置换转换为不相交循环的乘积。排列的奇偶性是其因子的奇偶性之和(偶数倍偶数或奇数倍奇数为偶数,奇数倍偶数或偶数倍奇数为奇数)。奇数长度的循环是偶数置换,偶数长度的循环是奇数置换。例如,长度为1的循环是身份置换,因此(表示为换位的空积)是偶数置换

在设置中,可以通过从第一个列表中选取一个项目,查找第二个列表中相应位置映射的项目,并使用每个后续项目的图像重复此查找,直到周期返回到第一个列表开头的项目,来查找不相交周期的乘积表示。连续图像的列表将与不在列表中的项目的轨道相分离,因此考虑它们被消除,并开始寻找未被消除的第一列表的第一项的下一个不相交的循环。最终,第一个列表中的所有项目将被删除,并被纳入一个或另一个已构建的循环中


确定给定置换奇偶性的其他方法在上面链接的文章中描述。如果您真的希望只枚举偶数置换(或仅枚举奇数置换),一种方法是以只返回相同奇偶校验的置换的方式进行修改(参见该部分和下面的一部分)。

我知道原来的问题是很久以前发布的,但我最近也在研究序言艺术中的一些问题,并思考了几天奇偶排列问题。我不想打开一个重复的问题,所以我在这里发布我的解决方案

书中的问题是:

偶数置换(Xs,Ys)
奇数置换(Xs,
Ys)
分别查找奇偶排列的, 列表的Xs。例如,
偶数置换([1,2,3],[2,3,1])
奇数置换([1,2,3],[2,1,3])
为真

所以它要求的是置换生成器,而不仅仅是验证器@hardmath提供了一个链接,指向偶数或奇数排列的正确定义。这本书的作者举了两个简单的例子加以说明

对我来说,关键是找出偶数或奇数排列的递归定义。对于所有置换,Prolog中的经典置换生成器使用以下概念:

  • N+1个元素的每个排列是一个列表,表示N个元素的排列,其中(N+1)个元素插入到列表中
谓词
select
insert
用于执行插入操作

对于奇偶排列,我考虑了一个类似的想法:

  • N+1个元素的每个偶数置换是表示N个元素的偶数置换的列表,其中(N+1)个元素插入到列表中的奇数位置,或者是表示N个元素的奇数置换的列表,其中(N+1)个元素插入到列表中的偶数位置

  • N+1个元素的每个奇数置换是表示N个元素的奇数置换的列表,其中(N+1)个元素插入到列表中的奇数位置,或者是表示N个元素的偶数置换的列表,其中(N+1)个元素插入到列表中的偶数位置

合理的做法是,在奇数位置插入元素表示相对于原始列表的交换数为偶数(列表的前面是第一个位置,不需要交换,所以是偶数)。类似地,在偶数位置插入元素表示相对于原始列表的奇数交换

如果我将空列表是它自己的偶数排列的规则添加到这一规则中,那么我可以定义以下谓词来生成偶数和奇数排列:

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

嗨,瓦斯瓦·塞缪尔。你的主题是指计数排列,但我认为你误解了偶数和奇数排列之间的区别。它们(通常)不是根据排列的枚举来定义的,而是根据将排列表示为排列的乘积所需的换位次数(交换两项)来定义的。这总是可以做到的,确实不止一种方式,但相同的排列总是会有偶数或奇数个换位“因子”。@false hehe从技术上讲,因为我说“超过”2年,我被涵盖,但我会调整。谢谢。:)顺便问一下,你是怎么发现的?在很长一段时间后添加另一个答案并不会使其达到堆的顶部。如果按活动排序,答案会增加。“超过2年”的确是一个单调的表达:-)。