Haskellで組合せ
順列ができれば、組合せもできます。
リストから、m 個だけ取り出す組合せ。
組合せでは、順列のうち、並べ替えても同じにならないものだけを取り出します。
つまり、いったん順列を考えて、そのうち最初のm個だけ取り出す。
さらに、ここから並べ替えて同じになるものを取り除けばいいわけですね。
ところで、並べ替えて同じになるかどうか調べるのだったら、昇順(小さいものからの順番)に並べておいて、同じでないものだけを残せばいい。
ということで、次のようにすれば、順列から組合せができますね。
combination m as = unique [x | x <- map (take m) (permutation as), ascendingOrder x] where unique xs = unique' [] xs where unique' ys [] = ys unique' ys (x:xs) | x `elem` ys = unique' ys xs | otherwise = unique' (ys ++ [x]) xs ascendingOrder [] = True ascendingOrder [x] = True ascendingOrder (x:xs) | x <= minimum xs = ascendingOrder xs | otherwise = False
実行してみる。1から4までのリストで3つ取り出す組合せは?
Main> combination 3 [1..4] [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
1から5まででは?
Main> combination 3 [1..5] [[1,2,3],[1,2,4],[1,2,5],[1,3,4],[1,3,5],[1,4,5],[2,3,4],[2,3,5],[2,4,5],[3,4,5] ]
1から6は?
Main> combination 3 [1..6] [[1,2,3],[1,2,4],[1,2,5],[1,2,6],[1,3,4],[1,3,5],[1,3,6],[1,4,5],[1,4,6],[1,5,6] ,[2,3,4],[2,3,5],[2,3,6],[2,4,5],[2,4,6],[2,5,6],[3,4,5],[3,4,6],[3,5,6],[4,5,6] ] Main>
でもねえ。
リストが[1..7]になるとすぐには答えが返ってこなくなって、[1..8]ならなんとか計算結果が得られますけど、リストがそれ以上長くなると、あっけなくエラーになりました。
ERROR - Garbage collection fails to reclaim sufficient space
おやおや。