Set of sets: ABCD ABCE AEF DFG ABFG arbitrary set: BG Internally, this is all stored a integers, which I'll write out here in binary: ABCDEFG 1111000 1110100 1000110 0001011 1100011 arbitrary set: 0100001 I'm going to keep using the letters in the rest of the post, though, they're easier to read. #### A: (ABCD, ABCE, AEF, ABFG) B: (ABCD, ABCE, ABFG) C: (ABCD, ABCE) D: (ABCD, DFG) E: (ABCE, AEF) F: (AEF, DFG, ABFG) G: (DFG, ABFG) Then, with our arbitrary set, BG, we just look at the sets in the B slot and the G slot. B: (ABCD, ABCE, ABFG) G: (DFG, ABFG) If there's a superset, it's gotta be in one of those two slots. The next trick is that we only look at the smaller of the two lists, to try and minimize our work as much as possible: G: (DFG, ABFG) So now we only need to check and see if BG is a subset of DFG or ABFG. That's 2 checks instead of 5. Progress. #### ABCDEFG 1111000 1110100 1000110 0001011 1100011 arbitrary set: 0100001 Now, I'll transpose the matrix, since I think it makes it easier to explain. SSSSS eeeee ttttt 12345 +----- A|11101 B|11001 C|11000 D|10010 E|01100 F|00111 G|00011 So instead of listing the sets horizontally, I list them vertically. Each horizontal row is an element. Internally, each of those horizontal numbers there is stored as a new integer. So instead of storing "1111000" for the set "ABCD", I store "11101" for the set of all sets taht contain "A". #### SSSSS eeeee ttttt 12345 +----- A|11101 B|11001 C|11000 D|10010 E|01100 F|00111 G|00011 Arbitrary set is BG. So take the B row and the G row. SSSSS eeeee ttttt 12345 +----- B|11001 G|00011 #### my %dispatch = (); sub and_maker { my $num_args = shift; return $dispatch{$num_args} if $dispatch{$num_args}; my $built = join '&', map {'$_[' . $_ . ']'} (0..$num_args - 1); return $dispatch{$num_args} = eval "sub { $built }"; } Call as: my $func = and_maker(3); my $results1 = $func->(1,2,3); # 3 args my $results2 = $func->(5,6,7); # 3 args my $func2 = and_maker(5); my $$results3 = $func2->(12,13,14,15,16); # 5 args