my @all_nums = 0 .. 100; my @nums = grep { !($_ % 2) or !($_ % 5) } @all_nums; # and throw some special nums in column 3: gen( [ \@nums, \@nums, [4,5], \@nums, \@all_nums, ], 100, 0, sub { print "@_\n" } ); sub gen { my( $col_ranges, $max, $used, $found, @vec ) = @_; if ( @$col_ranges == 0 ) { $found->( @vec ) if $max == $used; return; } my @col_ranges = @$col_ranges; my $col_range = shift @col_ranges; gen( \@col_ranges, $max, $used+$_, $found, @vec, $_ ) for @$col_range; }