🍕
Juliaで順列と組み合わせを列挙する
プログラムを書いていたらfor文がだんだんと増えていって, 結局は再帰構文に行きつくことに気付いたのではないだろうか. 少しばかり難しいので, 調べた結果をまとめる. 以下では, 全て異なるものを選ぶ場合を考え, 全パターンを列挙するプログラムを考える.
全てを選ぶパターン |
|
|
---|---|---|
順列 | ||
円順列 | ||
数珠順列 | ||
組み合わせ | 1 |
順列
Rosetta Codeで紹介されている順列の列挙のプログラムは
順列の列挙
# https://rosettacode.org/wiki/Permutations#Julia
perms(l) = isempty(l) ? [l] : [[x; y] for x in l for y in perms(setdiff(l, x))]
for perm in perms([1,2,3])
println(perm)
end
出力
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
だが, 少しばかり圧縮されすぎていて何をしているのかわからない. 「ある要素を選んで, 残りの要素からまた選ぶ」という, 多少の無駄はあるが直感的な実装を以下に示す. 上記のRosseta Codeの出力と同じである.
順列の列挙
function permutations(choices)
permutations = Vector[]
function permutation(choices; chosen=Int64[])
if isempty(choices)
push!(permutations, chosen)
else
for x in choices
permutation(setdiff(choices, [x]), chosen=union(chosen, [x]))
end
end
end
permutation(choices)
return permutations
end
for perm in permutations([1,2,3])
println(perm)
end
出力
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
上記は与えられたリストの全ての要素を並べるパターン. isempty(choices)
からlength(chosen) == k
に変えればよい.
順列の列挙(一部のみ選ぶ)
function permutations(choices, k)
permutations = Vector[]
function permutation(choices; chosen=Int64[])
if length(chosen) == k
push!(permutations, chosen)
else
for x in choices
permutation(setdiff(choices, [x]), chosen=union(chosen, [x]))
end
end
end
permutation(choices)
return permutations
end
for perm in permutations([1,2,3], 2)
println(perm)
end
出力
[1, 2]
[1, 3]
[2, 1]
[2, 3]
[3, 1]
[3, 2]
円順列
誰かコメントにください.(個人的には順列だけで十分だったのでひとまず公開しました. ユルシテ)
数珠順列
誰かコメントにください.(個人的には順列だけで十分だったのでひとまず公開しました. ユルシテ)
組み合わせ
ライブラリ
# using Pkg
# Pkg.add("Combinatorics")
using Combinatorics
組み合わせの列挙
# using Combinatorics
for comb in combinations([1,2,3,4,5], 3)
println(comb)
end
出力
[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]
この記事の元になったノートは下記のリンクにある.
清水団さんが円順列と数珠順列も含めて, さらに同じものを含む場合にも対応した記事を書いてくださいました. 上位互換です.
Discussion
円順列と数珠順列のリスト作成のコード作りました!
せっかくなので,同じものを含んでいる場合でも求まるようにしました!
ありがとうございます!!