my %seen; for each combination @c: #however you do this with Math::Combinatorics my $wanted = 1; CHECK: for my $i (0..$#c) { for my $j ($i+1..$#c) { if ($seen{$c[$i],$c[$j]} || $seen{$c[$j],$c[$i]}) { $wanted = 0; last CHECK; } } next unless $wanted; # emit combination here # go through pairs again to mark them as seen for my $i (0..$#c) { for my $j ($i+1..$#c) { $seen{$c[$i],$c[$j]} = 1; $seen{$c[$j],$c[$i]} = 1; } } }