math - 计算序言中列表的排列

标签 math prolog

Art of prolog 2nd edition 中有一个问题,您应该在其中定义谓词 even_permutation(Xs,Ys) 和类似的奇数排列,当您查询 even_permutation([1,2,3],[2 ,3,1]) 和 odd_permutation([1,2,3],[2,1,3]) 是真的。这些谓词应该能够在随机列表上工作并确定该列表的排列是否在奇数或偶数位置。如图所示,我有我的置换谓词。

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

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

最佳答案

我知道原来的问题是很久以前发布的,但我最近也在研究 The Art Of Prolog 中的一些问题,并考虑了偶数/奇数排列问题几天。我不想打开重复的问题,所以我在此处发布了我的解决方案。

书上的问题是:

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. For example, even_permutation([1,2,3], [2,3,1]) and odd_permutation([1,2,3], [2,1,3]) are true.

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

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

  • N+1 个元素的每个排列都是一个列表,表示 N 个元素的排列,第 (N+1) 个元素插入到列表中。

谓词 selectinsert 用于执行插入操作。

对于偶数和奇数排列,我考虑过类似的想法:

  • N+1 个元素的每个 even 排列要么是表示 N 个元素与第 (N+1) 个元素的even 排列的列表插入列表中的 奇数 位置,或表示 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 ).

关于math - 计算序言中列表的排列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5571558/

相关文章:

c++ - 将数学表达式传递给函数

machine-learning - 华纳(AVE 套件): eliminate "connected" terms from frequent patterns

prolog - prolog 中的向量加法

prolog - 查找图中节点之间的路径及其长度

C统计分析程序有数学错误

algorithm - 统一选择元素分布到箱子中

math - 矩形——一道数学题

python - 为什么生成随机数时迭代次数很重要?

prolog - DCG 输出单个变量而不是列表中的整个子句

prolog - Prolog中的动态联合查找算法