用perl生成一个数组的所有n!
排列的最佳(优雅、简单、高效)方法是什么?
例如,如果我有一个数组@arr = (0, 1, 2)
,我想输出所有排列:
0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0
它应该是一个返回迭代器的函数(延迟求值,因为n!
可能变得非常大),所以可以这样调用它:
my @arr = (0, 1, 2);
my $iter = getPermIter(@arr);
while (my @perm = $iter->next() ){
print "@perm\n";
}
7条答案
按热度按时间knsnq2tg1#
我建议您使用List::Permutor:
4nkexdtk2#
从perlfaq4开始:"如何排列列表中的N个元素?":
使用CPAN上的List::Permutor模块,如果列表实际上是一个数组,尝试Algorithm::Permute模块(也在CPAN上),它是用XS代码编写的,非常高效:
要获得更快的执行速度,您可以执行以下操作:
下面是一个小程序,它可以生成每一行输入中所有单词的所有排列,包含在permute()函数中的算法在Knuth的《计算机编程的艺术》(The Art of Computer Programming)第4卷(尚未出版)中有讨论,它适用于任何列表:
Algorithm::Loops模块还提供了NextPermute和NextPermuteNum函数,这些函数可以有效地查找数组的所有唯一排列,即使它包含重复值,也可以就地修改它:如果数组元素的顺序是反排序的,则数组被反转,使其排序,并返回false;否则返回下一个置换。
NextPermute使用字符串顺序和NextPermuteNum数字顺序,因此您可以像这样枚举0..9的所有排列:
6tdlim6h3#
您可以使用Algorithm::Permute,也许Iterating Over Permutations(The Perl Journal,1998年秋季)对您来说是一本有趣的读物。
fcg9iug34#
试试这个
输出:这将给出所有可能的数字组合。您可以添加逻辑来过滤掉不需要的组合。
5lhxktic5#
我建议研究一种按字典顺序生成排列的算法,这就是我最近解决Problem 24的方法,当数组中的项目数量变大时,以后存储和排序排列的代价会变得很高。
看起来Manni建议的
List::Permutor
生成了数字排序的排列,这就是我使用Perl时所采用的方法,让我们看看结果如何。hjqgdpho6#
看一下Iterator::Array::Jagged。
ujv3wf0j7#
一个纯Perl的答案,如果你想得到比CPAN模块允许的更好的结果:
印刷品:
为了解释一下这段编写得很密集的代码:
$_
是map
中列表的每个元素的值。@$_
将该值视为数组引用。@_
是函数的参数数组,$#_
是该数组中的最高索引。list_with_x_first
中的最后一个表达式(它首先接受一个索引$i
,然后是其他参数的列表)返回其他参数,但首先返回第$i
个参数,然后返回前面的参数,最后返回后面的参数。要捕获调用
permutate
的结果:my @results = permutate(@input_list);