2012-08-17 32 views
0

Perl新手,我试图定义一个字符子集,然后在文本文件中输出它们的所有可能组合(最多8个字符)。我真的不习惯'默认变量'或Perl的其他方面,所以我从伪代码开始,希望有人能够帮助我解释具体细节(我从例子中学到了很多东西)。Perl - 创建一个蛮力列表

#Define output file 
$filename=output.dat 
$standard_output->$filename 

#Define list 
$list[]=regex/a..z 0..9/ 

#Cycle through iterations 
foreach $letter1 in $list{ 
print $list[$letter] 
} 

foreach $letter1 in $list{ 
foreach $letter2 in $list{ 
    print $list[$letter1] $list[$letter2] 
} 
} 

... 

foreach letter1 in list{ 
foreach letter2 in list{ 
    foreach letter3 in list{ 
    foreach letter4 in list{ 
    foreach letter5 in list{ 
    foreach letter6 in list{ 
     foreach letter7 in list{ 
     foreach letter8 in list{ 
     print list[letter1] list[letter2] list[letter3] list[letter4] list[letter5] list[letter6] list[letter7] list[letter8] 
     } 
     }  
    } 
    } 
    } 
    } 
} 
} 

正如你可以清楚地看到的,我对此很新颖。有人能帮助我理解Perl吗?

+0

你的伪代码产生的所有可能的组合,这是比所有的排列多了不少。 – 2012-08-17 02:44:07

+0

你说得对,我用错了词。我正在寻找所有可能的组合。发布编辑。 – 2012-08-17 02:48:58

+1

请参阅'Algorithm :: Combinatorics'中的''combinations'](http://p3rl.org/Algorithm::Combinatorics#combinations-data-k-)([code example](http://stackoverflow.com/a/10300383)) – daxim 2012-08-17 09:26:50

回答

3

函数式编程*救援!下面的代码不会太高效,但更简洁。

我们将定义一个将数字和列表作为参数的函数。这个数字表示我们需要多少次递归,列表中包含来自外层的信件。

#!/usr/bin/perl 
use strict; use warnings; 
my @list = 'a' .. 'z'; # lowercase letters 
sub combinations { 
    my ($recursions, @letters) = @_; # unpack the arguments 
    if ($recursions == 0) { 
     print @letters, "\n"; # print the letters, append newline 
    } else { 
     # do a loop 
     $recursions--; # reduce level 
     for my $letter (@list) { 
     combinations($recursions, @letters, $letter); 
     } 
    } 
} 

我们可以使用combinations(8);来调用该子类以获得预期结果。

..是范围运算符并生成一个列表。它也适用于字母字符。你会想要'a' .. 'z', 0 .. 9

它的工作原理,虽然你可能想使用较小的@list进行测试。

这产生所有固定长度的字符串。为了让所有的字符串高达给定长度,只是做

combinations($length) foreach my $length (1 .. 8); 

(广度优先),或包括

print @list, "\n"; 

只是在else分枝的深度 - 在for -loop前第一。

脚注:

(*)没有,真的没有,但是这是一个接近。功能编程完全不需要任何循环。

+0

嗨,非常感谢您的帮助!我得到一个全局符号“$ length”,当我尝试将循环放入时,需要显式包名错误?我错过了明显的东西吗? – 2012-08-17 03:01:46

+0

啊,对不起,我忘记了我的 - 我的 - 固定:-) – amon 2012-08-17 03:03:02

4

Set::CrossProduct模块让一切变得简单,而且它确实它而不重新建立了新或内存破坏递归:

use v5.10; 

use Set::CrossProduct; 

my $min = 2; 
my $max = 4; 
my $set = [ qw(a b 1 2) ]; 

foreach my $length ($min .. $max) { 
    say "Getting combinations of length $length"; 

    my $cross = Set::CrossProduct->new(
     [ ($set) x $length ] 
     ); 

    while(my $tuple = $cross->get) { 
     say join '', @$tuple; 
     } 
    }