我正在尝试使用NestedLoops函数在Perl中构造一个排列程序.这是我的代码:
use strict; use warnings; use Algorithm::Loops qw(NestedLoops); my @a = 'a'..'o'; my $length = 5; my $start = 0; my $depth = 2; NestedLoops([ [0..$length],( sub { $start = 0 if $start == $depth; $start++; [$start * $length..$start * $length + $length - 1] }) x $depth,],\&permute,); sub permute { my @ind = @_; foreach my $i (@ind) { print $a[$i]; } print "\n"; }
所以我有一个数组,字母’a’到’o'(大小为15).我将数组视为有3行,所以我对数组的想象是这样的:
abcde fghij klmno
然后每个循环对应于每一行……我想构建如下的排列:
afk afl afm afn afo agk // fails here... I end up getting agg ...
它适用于前5个值(最低循环的整个运行),但是第二次运行失败,因为$start的最后一行的值被重置为0 ……这是一个问题,因为它会破坏一切.
所以我想知道的是,如何根据级别保持$start持久性的值…所以我要求的基本上是常量.我的循环真的应该是这样的:
for my $a (0..5) { # 0 at this level and never change for my $b (5..10) { # $start should be 5 at this level and never change for my $c (10..15) { # $start should be 10 at this level and never change permute($a,$b,$c); } } }
现在,因为我将有一个可变长度的for循环,我不能硬编码每个起始值,所以我正在寻找一种方法来初始创建这些起始值,然后在循环重置时保留它们.
我意识到这是一个令人困惑的问题,所以请提出问题,我将帮助澄清.
解决方法
你正在努力做到这一点.
部分问题是 NestedLoops的文档没有详细介绍如何使用第一个参数中的子例程引用.
部分问题是 NestedLoops的文档没有详细介绍如何使用第一个参数中的子例程引用.
对于以下示例,假设这是在它们上面的某处写的.
use strict; use warnings; use Algorithm::Loops qw'NestedLoops';
真的最简单的方法来调用NestedLoops来获得你想要的东西是这样的:
NestedLoops( [ ['a'..'e'],['f'..'j'],['k'..'o'],\&permute ); sub permute { print @_,"\n"; }
如果你真的希望动态生成NestedLoops的参数,我建议使用List::MoreUtils part.
use List::MoreUtils qw'part'; my @a = 'a'..'o'; my $length = 5; my $index; NestedLoops( [ part { $index++ / $length } @a ],"\n"; }
如果由于某种原因你想要将带有索引的NestedLoops调用到数组中,那么使用part仍然很容易.
use List::MoreUtils qw'part'; my @a = 'a'..'o'; my $length = 5; NestedLoops( [ part { $_ / $length } 0..@a-1 ],\&permute ); sub permute { print map { $a[$_] } @_; print "\n"; }
你遇到的主要问题是你给NestedLoops的两个子程序引用是修改相同的变量,它们都被多次调用.
解决此问题的最佳方法是依赖于调用子例程时的最后一个值. (从实现来看,这似乎更接近于它的使用方式.)
my @a = 'a'..'o'; my $length = 5; my $depth = 3; NestedLoops( [ [0..$length-1],(sub{ return unless @_; my $last = pop; my $part = int( $last / $length ) + 1; # current partition my $start = $part * $length; # start of this partition my $end = $start + $length; [$start..$end-1] # list of variables in this partition }) x ($depth-1) ],\&permute ); sub permute { print map { $a[$_] } @_; print "\n"; }