http://qs321.pair.com?node_id=1213494


in reply to Re: combinations of multiple variables which can assume multiple values
in thread combinations of multiple variables which can assume multiple values

As an exercise related to this problem (not solving the whole problem), I wanted to find an algorithm for 'variations_with_repetitions', (algorithms not being my strong suit), and was able to find a solution. I wouldn't say it is pretty, but it works :-)

It doen't have an iterative solution. Instead it returns all the tuples.

#!/usr/bin/perl use strict; use warnings; my $n = 3; my @a = "a".."b"; my @b = vw_rep(\@a, $n); # variations with repetition (Algorithm::Comb +inatorics) use Data::Dump; dd \@b; sub vw_rep { my ($ref, $n) = @_; my @c; for my $k (0 .. $n-1) { my $L = 0; for (1 .. @$ref**$k) { for my $i (0 .. $#$ref) { for (1 .. @$ref**($n-1 - $k)) { push @{ $c[$L++] }, $ref->[$i]; } } } } return @c; } __END__ C:\Old_Data\perlp>perl var_w_rep.pl [ ["a", "a", "a"], ["a", "a", "b"], ["a", "b", "a"], ["a", "b", "b"], ["b", "a", "a"], ["b", "a", "b"], ["b", "b", "a"], ["b", "b", "b"], ]
Update: A better approach using choroba's solution in an iterative fashion could be:
#!/usr/bin/perl use warnings; use strict; # Pm node 1211055 my $n = 3; my @b = qw( a b ); my $iter = variations_rep_iter(\@b, $n); while (my $tuple = $iter->()) { print "@$tuple\n"; } sub variations_rep_iter { my ($bases, $n) = @_; my @indices = (0) x $n; my $first = 1; my $iter = sub { if ($first) { $first = 0; return [ @$bases[ @indices ] ]; } my $r = $#indices; while ($r >= 0) { if (++$indices[$r] > $#$bases) { $indices[$r--] = 0; } else { last } } return if $r < 0; return [ @$bases[ @indices ] ]; }; return $iter; }