use warnings; use strict; use Data::Dumper; # nCk - combinatoric n Choose k (binomial coefficients) sub nck (&&$@) { my $end_cond = shift(); my $nextk_cond = shift(); my $k = shift(); return () unless defined($k); # start recursive grouping when end condition is fulfilled return [] if $end_cond->($k); # keep looking for a partner my @groups; while (@_) { # nextk condition can force early exit by returning undef my $pick = shift(); push @groups, map { unshift(@{ $_ }, $pick); $_ } &nck($end_cond, $nextk_cond, $nextk_cond->($k, $pick), @_); } return @groups; } # standard 5 choose 3 my @grouping = nck sub { $_[0] <= 0 }, sub { $_[0] - 1 }, 3, qw(a b c d e); # conditions set to figure out $1.51 exactly my @stamps = (.02, .03, .04, .05, .1, .26, .27, .42, .8, .84, .87, 5); my @packing = nck sub { $_[0] >= 1.51 }, sub { my $nextk = $_[0] + $_[1]; $nextk <= 1.51 ? $nextk : undef }, 0, @stamps; print Dumper(\@grouping, \@packing); __DATA__ $VAR1 = [ [ 'a', 'b', 'c' ], [ 'a', 'b', 'd' ], [ 'a', 'b', 'e' ], [ 'a', 'c', 'd' ], [ 'a', 'c', 'e' ], [ 'a', 'd', 'e' ], [ 'b', 'c', 'd' ], [ 'b', 'c', 'e' ], [ 'b', 'd', 'e' ], [ 'c', 'd', 'e' ] ]; $VAR2 = [ [ '0.02', '0.03', '0.04', '0.05', '0.26', '0.27', '0.84' ], [ '0.02', '0.04', '0.05', '0.26', '0.27', '0.87' ], [ '0.02', '0.27', '0.42', '0.8' ], [ '0.03', '0.04', '0.05', '0.1', '0.42', '0.87' ], [ '0.03', '0.05', '0.1', '0.26', '0.27', '0.8' ], [ '0.03', '0.26', '0.42', '0.8' ], [ '0.04', '0.1', '0.26', '0.27', '0.84' ] ];