Perl算法:Permute和List :: AllUtils(uniq)

时间:2012-06-27 21:44:46

标签: perl

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

嗨,

在发现Algorithm::Permute正在产生重复之后,很可能是由于“1151”中的“1”数量,我决定使用uniq。但是,如果不使用括号使用sort uniq,则不会产生预期结果。但sort(uniq(@x))确实如此。是什么给了什么?

3 个答案:

答案 0 :(得分:6)

perldoc -f sort列出了sort函数的三种语法:

sort SUBNAME LIST
sort BLOCK LIST
sort LIST

sort uniq @others匹配排序的sort SUBNAME LIST语法。它期望uniq是一个比较全局变量$a$b的函数,并返回<00>0来表示$a$b的相对顺序。

看起来你期待并想要sort LIST语法,这就是当你说出一个

时得到的
sort(uniq(@others))
sort(uniq @others)

答案 1 :(得分:5)

Algorithm::LoopsNextPermute不会产生重复,因此不需要花费内存和CPU来消除它们。

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

答案 2 :(得分:4)

虽然@mob answered the question you asked,但我想指出我不确定你是否想要sort uniq方式。您仍在存储您不想存储的元素。在这种情况下,最好使用哈希。

另外,请when a piece of data is meant to be a string, use a stringfind_perms(0345)的输出可能会让您大吃一惊,但find_perms('0345')不会。

最后Algorithm::Permute::permute非常快。

考虑到这些因素,我会将您的代码重写为:

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 ];
}