sub comb_iter { my $items = shift || []; # Think 1,2,3,4,5 my $group = shift || 2; # Think 2 @$items>=$group or die "Insufficient elements ".scalar(@$items). " to make groups of $group\n"; my @index=(0..$group-1); # Think 0,1 my @last=(@$items-$group..$#$items); # Think 3,4 my @ret; while ($index[0]<=$last[0]) { # Think first pass: 0 < 3 push @ret,[@$items[@index]]; # increment the last digit, and if we rollover carry it left unless (++$index[-1]<=$last[-1]) { # we've rolled over, we need to go left until # until the result after adding 1 is below the # respective last. my $pos=$#index; --$pos while ($pos and $index[$pos]+1>$last[$pos]); # increment the apropriate index, if we increment # $index[0] too high the loop exits because of the # while condition. my $v=++$index[$pos]; # and then move right assigning the values in sequential order $index[++$pos]=++$v while $pos<$#index; } } return \@ret; }