在prolog第2版的Art中有一个问题,你应该定义一个谓词even_permutation(Xs,Ys)和类似的奇数排列,当你查询例如even_permutation([1,2,3],[2]这些谓词应该能够在一个随机列表上工作,并确定该列表的排列是否存在于一个随机列表中,并且确定该列表的排列是否存在于一个随机列表中。奇数或偶数位置。如图所示,我有断言的谓词。
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).
我有一个想法,我计算列表的排列数,并将它们分组为偶数和奇数排列,然后我的查询可以确定permutaion是奇数还是偶数但我不知道如何实现它。如果有更好的方法,请告诉我。
答案 0 :(得分:3)
我知道最初的问题是在很久以前发布的,但我最近也在解决 Prolog的艺术中的一些问题并且考虑了偶数/奇数排列问题几天。我不想打开一个重复的问题,所以我在这里发布我的解决方案。
书中的问题是:
分别编写
even_permutation(Xs, Ys)
和odd_permutation(Xs, Ys)
找到Ys
,偶数和奇数排列的程序, 列表Xs
。例如,even_permutation([1,2,3], [2,3,1])
和odd_permutation([1,2,3], [2,1,3])
是真的。
所以它要求排列生成器,而不仅仅是验证器。 @hardmath提供了偶数或奇数排列的正确定义的链接。本书的作者给出了两个简单的例子来说明。
对我来说,关键在于找出偶数或奇数排列的递归定义。对于所有排列,Prolog中的经典置换生成器使用以下概念:
谓词select
或insert
用于插入。
对于偶数和奇数排列,我考虑了类似的想法:
N + 1个元素的每个偶数排列是表示具有(N + 1)个st元素的N个元素的偶数排列的列表在列表中的奇数位置插入,或者表示在中插入了(N + 1)st元素的N个元素的奇数排列的列表甚至列表中的位置。
N + 1个元素的每个奇数排列是表示具有(N + 1)个st元素的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 ).
答案 1 :(得分:2)
以下是如何确定排列是偶数还是奇数in the usual sense of the terms的高级描述。
将置换转换为不相交周期的乘积。置换的奇偶性是其因子的奇偶性的总和(偶数偶数或奇数倍奇数是偶数,奇数倍偶数或偶数奇数是奇数)。奇数长度的循环是偶数排列,偶数长度的循环是奇数排列。例如,长度为1的周期是身份置换,因此(表示为换位的空积)是偶数置换。
通过从第一个列表中选择一个项目,查找第二个列表中相应位置的映射位置,并使用每个成功的图像重复此查找,可以在设置中查找不相交周期表示的乘积。 item直到循环返回到第一个列表开头的项目。连续图像的列表将与不在列表中的项目的轨道不相交,因此考虑它们被消除并开始使用尚未消除的第一列表的第一项找到下一个不相交的循环。最终,第一个清单中的所有项目都将被删除,并已合并到一个或另一个构建的周期中。
确定给定排列的奇偶性的其他方法在上面链接的文章中描述。如果你真的只希望枚举偶数排列(仅仅是奇数排列),一种方法是修改the enumeration of all permutations,只返回相同奇偶校验的排列(参见该部分和后面的部分)。 / p>