Perl Algorithm: Permute and List :: AllUtils (uniq)

use Modern::Perl; use Algorithm::Permute; use List::AllUtils qw/uniq/; find_perms(1151); sub find_perms { my ($value) = @_; my @others; my @digits = split(//, $value); my $perm = Algorithm::Permute->new( \@digits ); while (my @next = $perm->next()) { my $number = join('', @next); push @others, $number; } @others = sort uniq @others; # this one works correctly # @others = sort ( uniq( @others )); say "FOUND @others"; } Output: FOUND 1115 1115 1115 1115 1115 1115 1151 1151 1151 1151 1151 1151 1511 1511 1511 1511 1511 1511 5111 5111 5111 5111 5111 5111 

Hi,

After discovering that Algorithm :: Permute produces duplicates, most likely due to the number of β€œ 1s inβ€œ 1151 ”, I decided to use uniq . However, using sort uniq without parentheses does not produce the expected results. But sort(uniq(@x)) does. What gives?

+4
source share
3 answers

perldoc -f sort lists three syntaxes for the sort function:

 sort SUBNAME LIST sort BLOCK LIST sort LIST 

sort uniq @others follows the syntax of sort SUBNAME LIST sort. He expects uniq be a function that compares the global variables $a and $b , and returns <0 , 0 or >0 to indicate the relative ordering of $a and $b .

It looks like you expected and wanted the sort LIST syntax that you get when you say one of

 sort(uniq(@others)) sort(uniq @others) 
+6
source

Algorithm :: Cycles NextPermute does not create duplicates, so there is no need to waste memory and processor, getting rid of them.

 use Algorithm::Loops qw( NextPermute ); sub find_perms { my @rv; my @digits = sort split //, $_[0]; do { push @rv, join '', @digits; } while NextPermute(@digits); return @rv; } say for find_perms(1151); 

 1115 1151 1511 5111 
+5
source

While @mob answered your question , I would like to point out that I'm not sure if you want to go the sort uniq path. You still save items that you really don't want to store. In such cases, it is better to use a hash.

Also, when a piece of data is for a row, use a row . The result from find_perms(0345) may surprise you, but find_perms('0345') will not.

Finally, Algorithm::Permute::permute is very fast.

Given these considerations, I would rewrite your code as follows:

 use strict; use warnings; use Algorithm::Permute qw( permute ); my $uniq_perms = find_perms('115122345'); sub find_perms { my ($value) = @_; my @digits = split //, $value; my %uniq; permute { $uniq{join('', @digits)} = undef } @digits; return [ keys %uniq ]; } 
+4
source

All Articles