Xem perlfaq4: "How do I permute N elements of a list?"
Sử dụng Danh mục :: Permutor mô-đun trên CPAN. Nếu danh sách thực sự là một mảng, hãy thử thuật toán :: Permute module (cũng trên CPAN). Nó được viết trong mã XS và rất hiệu quả:
use Algorithm::Permute;
my @array = 'a'..'d';
my $p_iterator = Algorithm::Permute->new (\@array);
while (my @perm = $p_iterator->next) {
print "next permutation: (@perm)\n";
}
Đối với thực hiện nhanh hơn, bạn có thể làm:
use Algorithm::Permute;
my @array = 'a'..'d';
Algorithm::Permute::permute {
print "next permutation: (@array)\n";
} @array;
Dưới đây là một chương trình nhỏ mà tạo ra tất cả các hoán vị của tất cả các từ trên mỗi dòng đầu vào . Thuật toán thể hiện trong các hoán vị() chức năng được thảo luận trong Tập 4 (vẫn chưa được công bố) của The Art of Computer Programming Knuth và sẽ làm việc trên danh sách bất kỳ:
#!/usr/bin/perl -n
# Fischer-Krause ordered permutation generator
sub permute (&@) {
my $code = shift;
my @idx = 0..$#_;
while ($code->(@_[@idx])) {
my $p = $#idx;
--$p while $idx[$p-1] > $idx[$p];
my $q = $p or return;
push @idx, reverse splice @idx, $p;
++$q while $idx[$p-1] > $idx[$q];
@idx[$p-1,$q][email protected][$q,$p-1];
}
}
permute { print "@_\n" } split;
Các Thuật toán :: Module Loops cũng cung cấp NextPermute và Hàm NextPermuteNum tìm kiếm tất cả các hoán vị duy nhất của mảng, ngay cả khi nó chứa giá trị trùng lặp, sửa đổi tại chỗ: nếu các phần tử của nó theo thứ tự sắp xếp ngược thì mảng được đảo ngược, sắp xếp, và trả về false; nếu không thì hoán vị tiếp theo sẽ được trả về.
NextPermute sử dụng theo thứ tự chuỗi và NextPermuteNum trật tự số, vì vậy bạn có thể liệt kê tất cả các hoán vị của 0..9 như thế này:
use Algorithm::Loops qw(NextPermuteNum);
my @list= 0..9;
do { print "@list\n" } while NextPermuteNum @list;
Nguồn
2009-03-12 09:47:26
Bài viết là một bài đọc thú vị. Cảm ơn! –