FAQ 4.51 How do I permute N elements of a list?

FAQ 4.51 How do I permute N elements of a list?

am 19.09.2007 03:03:02 von PerlFAQ Server

This is an excerpt from the latest version perlfaq4.pod, which
comes with the standard Perl distribution. These postings aim to
reduce the number of repeated questions as well as allow the community
to review and update the answers. The latest version of the complete
perlfaq is at http://faq.perl.org .

------------------------------------------------------------ --------

4.51: How do I permute N elements of a list?

Use the "List::Permutor" module on CPAN. If the list is actually an
array, try the "Algorithm::Permute" module (also on CPAN). It's written
in XS code and is very efficient.

use Algorithm::Permute;
my @array = 'a'..'d';
my $p_iterator = Algorithm::Permute->new ( \@array );
while (my @perm = $p_iterator->next) {
print "next permutation: (@perm)\n";
}

For even faster execution, you could do:

use Algorithm::Permute;
my @array = 'a'..'d';
Algorithm::Permute::permute {
print "next permutation: (@array)\n";
} @array;

Here's a little program that generates all permutations of all the words
on each line of input. The algorithm embodied in the "permute()"
function is discussed in Volume 4 (still unpublished) of Knuth's *The
Art of Computer Programming* and will work on any list:

#!/usr/bin/perl -n
# Fischer-Krause ordered permutation generator

sub permute (&@) {
my $code = shift;
my @idx = 0..$#_;
while ( $code->(@_[@idx]) ) {
my $p = $#idx;
--$p while $idx[$p-1] > $idx[$p];
my $q = $p or return;
push @idx, reverse splice @idx, $p;
++$q while $idx[$p-1] > $idx[$q];
@idx[$p-1,$q]=@idx[$q,$p-1];
}
}

permute {print"@_\n"} split;



------------------------------------------------------------ --------

The perlfaq-workers, a group of volunteers, maintain the perlfaq. They
are not necessarily experts in every domain where Perl might show up,
so please include as much information as possible and relevant in any
corrections. The perlfaq-workers also don't have access to every
operating system or platform, so please include relevant details for
corrections to examples that do not work on particular platforms.
Working code is greatly appreciated.

If you'd like to help maintain the perlfaq, see the details in
perlfaq.pod.

Re: FAQ 4.51 How do I permute N elements of a list?

am 19.09.2007 11:19:42 von Michele Dondi

On Tue, 18 Sep 2007 18:03:02 -0700, PerlFAQ Server
wrote:

> Use the "List::Permutor" module on CPAN. If the list is actually an
> array, try the "Algorithm::Permute" module (also on CPAN). It's written

There are also Algorithm::Loops's NextPermute() and NextPermuteNum()
which are pure Perl implementations of an algorithm giving the next
permutation of a list (an array, really, which is modified in place)
efficiently.

If there's some interest in this I may try to concoct a patch to the
faq entry.


Michele
--
{$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
(($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^ ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER 256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,

Re: FAQ 4.51 How do I permute N elements of a list?

am 19.09.2007 18:09:45 von brian d foy

In article <1kp1f3lektuk0tkb0mut0ftp572mr2sr91@4ax.com>, Michele Dondi
wrote:

> On Tue, 18 Sep 2007 18:03:02 -0700, PerlFAQ Server
> wrote:
>
> > Use the "List::Permutor" module on CPAN. If the list is actually an
> > array, try the "Algorithm::Permute" module (also on CPAN). It's written

> If there's some interest in this I may try to concoct a patch to the
> faq entry.

Yes, please do. You can post it here and I should find it.

Alternatively, you could also just patch the faq directly according to
the instructions in perlfaq. The latest version is always at
http://faq.perl.org , so ignore any installed perlfaq.pod that mentions
CVS instead of SVN :)

Re: FAQ 4.51 How do I permute N elements of a list?

am 28.09.2007 12:06:21 von Michele Dondi

On Wed, 19 Sep 2007 09:09:45 -0700, brian d foy
wrote:

>> If there's some interest in this I may try to concoct a patch to the
>> faq entry.
>
>Yes, please do. You can post it here and I should find it.

Here it is, HTH:

: --- perlfaq4.pod Tue Jan 03 08:01:16 2006
: +++ perlfaq4-new.pod Fri Sep 28 12:02:06 2007
: @@ -1552,6 +1552,19 @@
: Algorithm::Permute::permute {
: print "next permutation: (@array)\n";
: } @array;
: +
: +The Algorithm::Loops module also provides the C and
: +C functions which efficiently find all unique permutations
: +of an array, even if it contains duplicate values, modifying it in-place:
: +if its elements are in reverse-sorted order then the array is reversed,
: +making it sorted, and a false value is returned; otherwise the next
: +permutation is returned.
: +
: +C uses string order and C numeric order, so
: +one could enumerate all the permutations of C<0..9> like thus:
: +
: + my @list= 0..9;
: + do { print "@list\n" } while NextPermuteNum @list;
:
: Here's a little program that generates all permutations of
: all the words on each line of input. The algorithm embodied


Michele
--
{$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
(($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^ ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER 256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,

Re: FAQ 4.51 How do I permute N elements of a list?

am 28.09.2007 19:24:27 von brian d foy

In article , Michele Dondi
wrote:

> On Wed, 19 Sep 2007 09:09:45 -0700, brian d foy
> wrote:
>
> >> If there's some interest in this I may try to concoct a patch to the
> >> faq entry.
> >
> >Yes, please do. You can post it here and I should find it.
>
> Here it is, HTH:


Added, thanks, :)