2012-08-17 56 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; 
     } 
    }