Haskell ソリューションを再度プラグインします (レイジー リストは組み込みであるため、簡単に操作できます)。
combinations 0 _ = [[]]
combinations k [] = []
combinations k (x:xs) = map (x:) (combinations (k-1) xs) ++ combinations k xs
最初の 2 つのケースは、2項係数のプロパティから、より具体的には次のとおりn choose 0 = 1
です。すべてn
を含むn=0
(これが最初に case を処理する理由です0 choose 0
)。もう一つは0 choose k = 0
. 3 番目の方程式は、組み合わせの再帰的な定義を正確に変換したものです。
残念ながら、それを無限リストに適用すると、簡単な解決策が返されます。
> take 10 $ combinations 3 [1..]
[[1,2,3],[1,2,4],[1,2,5],[1,2,6],[1,2,7],[1,2,8],[1,2,9],[1,2,10],[1,2,11],[1,2,12]]
編集: では、有限数のステップで各組み合わせを実際に見ていきたいと思います。上記のバージョンでは、1 で始まる組み合わせのみを生成する左側の式のみを使用していることは明らか++
です。この問題は、各引数の先頭を交互に選択してリストを作成する興味深いリスト zip 関数を定義することで回避できます。リスト (2 番目の引数で厳格でないことが重要です):
merge [] ys = ys
merge (x:xs) ys = x:merge ys xs
の代わりに使用します++
。
combinations k (x:xs) = map (x:) (combinations (k-1) xs) `merge` combinations k xs
どれどれ:
> let comb_10_3 = combinations 3 [1..10]
> let comb_inf_3 = combinations 3 [1..]
> take 10 comb_inf_3
[[1,2,3],[2,3,4],[1,3,4],[3,4,5],[1,2,4],[2,4,5],[1,4,5],[4,5,6],[1,2,5],[2,3,5]]
> comb_10_3 `intersect` comb_inf_3 == comb_10_3
True
> last $ combinations 3 [1..10]
[6,8,10]
> elemIndex [6,8,10] $ combinations 3 [1..]
Just 351
すべての10 choose 3
組み合わせがあります!