This solution uses a simple recursive permutation algorithm and a callback function to process the permutations.
# Name : permute
# Parameters : $array_ref
# $start_idx
# $callback_ref
# @callback_params
# Description : Generate permutations of the elements of the array referenced
# by $array_ref, permuting only the elements with index
# $start_idx and above.
# Call the subroutine referenced by $callback for each
# permutation. The first parameter is a reference to an
# array containing the permutation. The remaining parameters
# (if any) come from the @callback_params to this subroutine.
# If the callback function returns FALSE, stop generating
# permutations.
sub permute
{
my ( $array_ref, $start_idx, $callback_ref, @callback_params ) = @_;
if ( $start_idx == $#{$array_ref} )
{
# No elements need to be permuted, so we've got a permutation
return $callback_ref->( $array_ref, @callback_params );
}
for ( my $i = $start_idx; $i <= $#{$array_ref}; $i++ )
{
my $continue_permuting
= permute( [ @{$array_ref}[ 0 .. ($start_idx - 1),
$i,
$start_idx .. ($i - 1),
($i+1) .. $#{$array_ref} ] ],
$start_idx + 1,
$callback_ref,
@callback_params );
if (! $continue_permuting )
{ return 0; }
}
return 1;
}
# Name : handle_permutation
# Parameters : $array_ref
# $last_elem
# $num_found_perms_ref
# Description : $array_ref is a reference to an array that contains
# a permutation of elements.
# If the last element of the array is $last_elem, output the
# permutation and increment the count of found permutations
# referenced by $num_found_perms_ref.
# If 10 of the wanted permutations have been found, return
# FALSE to stop generating permutations Otherwise return TRUE.
sub handle_permutation
{
my ( $array_ref, $last_elem, $num_found_perms_ref ) = @_;
if ( $array_ref->[-1] eq $last_elem )
{
print '[ ';
print join ', ', @{$array_ref};
print " ]\n";
return ( ++${$num_found_perms_ref} < 10 );
}
return 1;
}
# Print the first 10 permutations of 'a b c d e f' ending with 'a'
my $num_found_perms = 0;
permute( [ qw{ a b c d e f } ], 0,
\&handle_permutation, 'a', \$num_found_perms );
Instead of using a callback function you could also implement the permutation generation using an iterator. See What is the Perl version of a Python iterator? for ways of doing that.
Another option would be to use a thread or coroutine to generate the permutations and pass them on to the main program. See Can a Perl subroutine return data but keep processing? and Perl, how to fetch data from urls in parallel? for a useful overview of available technologies for doing this kind of processing.