再帰ルーチン
sub recursive_exist{ #最重要の再帰ルーチン my ($flag, $selected, $key) = @_; #要素@{$selected}を選んだら残りは$flagでビットが立っている配列と # @{$key}にある要素しか考えなくていい、と呼び出し元から保証されている my (@new_keys); #実は要素の候補はもっと絞り込める。入れ物を用意して… for$k(@{$key}){ #要素の候補を全て審査し直す my $f = $flag & $bit{$k}; #新たに要素を選んだら、配列はもっとふるい落とされる next if (unpack "%".$bit_length."b*", $f) < 2; # $fの立っているビットを数える常套句らしい # 選んだ要素が含まれている配列の数が少なければふるい落とす push @new_keys, $k; #審査を合格した要素は、次の再帰の段階でも選んでよい #ここですぐさま再帰しない理由は、一般的には、@{$key}を@new_keysへと #絞り込んでおくと、効率が著しく良いからである } while(@new_keys){ #次の再帰… $k = shift @new_keys; my $f = $flag & $bit{$k}; if(@{$selected}){ #の前に、この再帰の段階での配列を表示しておかなくてはならない #ただし要素数が2に満たなければまだ表示しない print join ',', (@{$selected}, $k); #選んだ要素を列挙して… print "\n "; print join ',', (grep{$_}map{vec($f,$_,1) ? $names[$_] : ''}(0..$#names)); #それを含む配列を列挙する。 print "\n"; } &recursive_exist($f, [@{$selected}, $k], \@new_keys); #さらに要素を加えたら…? } }