Reputation: 3100
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 out that Algorithm::Permute is producing duplicates, most likely due to the amount of '1's in "1151" i decided to use uniq
. However using sort uniq
without the parenthesis doesn't produce expected results. But sort(uniq(@x))
does. What gives?
Upvotes: 4
Views: 191
Reputation: 385829
Algorithm::Loops's NextPermute
doesn't produce duplicates, so there's no need to spend memory and CPU 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
Upvotes: 5
Reputation: 118128
While @mob answered the question you asked, I would like to point out I am not sure if you want to go the sort uniq
way. You are still storing elements you don't really want to store. In such cases, it is best to use a hash.
Also, please, when a piece of data is meant to be a string, use a string. The output from find_perms(0345)
may surprise you, but find_perms('0345')
won't.
Finally Algorithm::Permute::permute
is very fast.
With those considerations in mind, I would re-write your code as:
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 ];
}
Upvotes: 4
Reputation: 118605
perldoc -f sort
lists three syntaxes for the sort
function:
sort SUBNAME LIST
sort BLOCK LIST
sort LIST
sort uniq @others
matches the sort SUBNAME LIST
syntax of sort. It expects uniq
to 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 were expecting and wanting the sort LIST
syntax, which is what you get when you say one of
sort(uniq(@others))
sort(uniq @others)
Upvotes: 6