立方体の6面色塗りの総数をJulia で解決!
はじめに
2022年度は中学3年生と高校2年生の授業を担当しています。
高校2年生は演習の授業で,『立方体の色塗り』の問題を取り上げました。演習なので,生徒はiPadなど使って発表します。
立方体の問題
立方体の問題の解答
6色
上面を塗る色を定めておいて,残り5色の中の1色で底面を塗り,次に側面を塗る。側面の塗り方は円順列の数である。
3色
3色の選び方は
4色
4色の選び方は
生徒の発表が終わって
少し時間があったので,『発表バッチリですね。この3色・4色の問題で隣り合う面は同色でも良いとしたら何通りだろう? 例えば,立方体の6つの面を赤で2面,青で2面,黄で2面塗ることにする。塗り方は全部で何通りになるかな?』
と生徒に振ったものの,『ちょっと大変だぞ・・・』という予感。生徒にはポリドロンというおもちゃを渡して,立体を作ってもらいました。
Twitterへ
Twitterへ投げたところ,@ysmemoirs
さんなどが反応してくれました。
考察1
@ysmemoirs
さんも書いているように,赤2青2黄2を1列に並べると
となります。なので,多くても90通りとなります。
また,6色を1列に並べると
1列に並べた時に24パターンを1つと数えているわけです。
今回,1列に並べて90通りなので,
となり,少なくとも4通りはあることがわかりました。
考察2
『そんなにいっぱいはないだろう』という感じで,とりあえず,どんなパターンがあるか作りながら感げてみました。
- 3色とも対面(同色隣り合わない)の場合。これは元の問題と同じ設定で,1通りしかありません。
- 3色とも隣り合う場合。このようなものが作れることはわかりました。なんとなくですが『1通りなのかなあ?』という感じです。
- 2色は隣り合い、1色は対面の場合。これも作れることがわかりました。対面の1色の選び方は3通りあるので,『3通りなのかなあ?』という感じです。
まあ,少なくとも5通りあることはわかりました。
考察3(ここからが問題!)
この後は今ひとつ対称性の仕組みがわかりません。
『やはり,90通りを1列に並べてみて,同じになるパターンを考えるしかない!』
という考えに至り,全部書いて調べることにしました。
調べてみることは大切ですね。先程の考察の中の 『3色とも隣り合う場合』は2通りあるということがわかりました! 実際に作ってみると,確かに同じにはなりません。また,『2色は隣り合い、1色は対面の場合』はそれぞれが1通りの合計3通りで予想は正しかったです。
- 3色とも対面(同色隣り合わない)の場合は6パターンを1通りとする。
- 3色とも隣り合う場合は24パターンを1通りとする。
- 2色は隣り合い、1色は対面の場合は12パターンを1通りとする。
ということがわかりました。
となります。答えは 6通り となりました。
Juliaでコード作成
コード作成の方針
『立方体の色塗り』は高校の教材でよく出てきるのですが,今回考えた『隣り合うところに同色を塗ってもよい』という条件がついた問題はあまりありません。やっぱり難しいからです。答えが出せたとしても,『他にないのか?』と考えると,上述のように,1列に並べて分類するしかありません。(
本当はちゃんと理論があると思います。)
立方体の色塗りの場合,最大でも24パターンを1通りとすることがわかっているので,これらをちゃんと調べて,除いていくコードを考えました。
24パターンを巡回してく
そこで,この『24パターンをどう記述するか?』となるのですが,24パターンはわかっているので,それらを書いてしまうこともできたのですが,ちょっとミスすると,後でチェックするのが大変そうだったので,24パターンを順々に定めていく方法を考えました。
3つの操作の組み合わせ
これは,恐らく色々あるのだろうな?と思ったのですが,とりあえず,以下の3つの操作を組み合わせることにしました。操作は
上 | 下 | 右 | 左 | 前 | 後 |
---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 |
1 | 2 | 6 | 5 | 3 | 4 |
上 | 下 | 右 | 左 | 前 | 後 |
---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 |
1 | 2 | 5 | 6 | 4 | 3 |
上 | 下 | 右 | 左 | 前 | 後 |
---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 |
3 | 4 | 2 | 1 | 5 | 6 |
これらの行列によって
の順で操作することによって,24パターンの配置を順々に調べることができます。
下の展開図を参考にしました。
コード可
juliaでコーディングです。パッケージはCombinatorics.jl
とLinearAlgebra.jl
です。
using Combinatorics,LinearAlgebra
# 立方体の色塗り。
function cubeperm(seq)
a = sort!(seq)
p = union(permutations(a))
n = length(p)
d = []
A = [1 0 0 0 0 0
0 1 0 0 0 0
0 0 0 0 0 1
0 0 0 0 1 0
0 0 1 0 0 0
0 0 0 1 0 0]
B = [1 0 0 0 0 0
0 1 0 0 0 0
0 0 0 0 1 0
0 0 0 0 0 1
0 0 0 1 0 0
0 0 1 0 0 0]
C = [0 0 1 0 0 0
0 0 0 1 0 0
0 1 0 0 0 0
1 0 0 0 0 0
0 0 0 0 1 0
0 0 0 0 0 1]
for i = 1:n-1, j = i+1: n
p₁ = p[j]
if p[i] == p₁
push!(d, j)
end
p₂ = A * p₁
if p[i] == p₂
push!(d, j)
end
p₃ = A * p₂
if p[i] == p₃
push!(d, j)
end
p₄ = A * p₃
if p[i] == p₄
push!(d, j)
end
p₅ = C * p₄
if p[i] == p₅
push!(d, j)
end
p₆ = B * p₅
if p[i] == p₆
push!(d, j)
end
p₇ = B * p₆
if p[i] == p₇
push!(d, j)
end
p₈ = B * p₇
if p[i] == p₈
push!(d, j)
end
p₉ = C * p₈
if p[i] == p₉
push!(d, j)
end
p₁₀ = A * p₉
if p[i] == p₁₀
push!(d, j)
end
p₁₁ = A * p₁₀
if p[i] == p₁₁
push!(d, j)
end
p₁₂ = A * p₁₁
if p[i] == p₁₂
push!(d, j)
end
p₁₃ = C * p₁₂
if p[i] == p₁₃
push!(d, j)
end
p₁₄ = B * p₁₃
if p[i] == p₁₄
push!(d, j)
end
p₁₅ = B * p₁₄
if p[i] == p₁₅
push!(d, j)
end
p₁₆ = B * p₁₅
if p[i] == p₁₆
push!(d, j)
end
p₁₇ = C * p₁₆
if p[i] == p₁₇
push!(d, j)
end
p₁₈ = A * p₁₇
if p[i] == p₁₈
push!(d, j)
end
p₁₉ = A * p₁₈
if p[i] == p₁₉
push!(d, j)
end
p₂₀ = A * p₁₉
if p[i] == p₂₀
push!(d, j)
end
p₂₁ = C * p₂₀
if p[i] == p₂₁
push!(d, j)
end
p₂₂ = B * p₂₁
if p[i] == p₂₂
push!(d, j)
end
p₂₃ = B * p₂₂
if p[i] == p₂₃
push!(d, j)
end
p₂₄ = B * p₂₃
if p[i] == p₂₄
push!(d, j)
end
end
deleteat!(p, sort!(union!(d)))
end
チェック
赤2青2黄2色の場合のチェックです。
seq = [1, 1, 2, 2, 3, 3]
cubeperm(seq)
6-element Vector{Vector{Int64}}:
[1, 1, 2, 2, 3, 3]
[1, 1, 2, 3, 2, 3]
[1, 2, 1, 2, 3, 3]
[1, 2, 1, 3, 2, 3]
[1, 2, 1, 3, 3, 2]
[1, 3, 1, 3, 2, 2]
赤2青2黄1黒1色の場合のチェックです。
seq = [1, 1, 2, 2, 3, 4]
cubeperm(seq)
8-element Vector{Vector{Int64}}:
[1, 1, 2, 2, 3, 4]
[1, 1, 2, 3, 2, 4]
[1, 2, 1, 2, 3, 4]
[1, 2, 1, 3, 2, 4]
[1, 2, 1, 3, 4, 2]
[1, 2, 1, 4, 2, 3]
[1, 2, 1, 4, 3, 2]
[1, 3, 1, 4, 2, 2]
赤1青3黄1黒1色の場合のチェックです。
seq = [1, 2, 2, 2, 3, 4]
cubeperm(seq)
5-element Vector{Vector{Int64}}:
[1, 2, 2, 2, 3, 4]
[1, 2, 2, 3, 2, 4]
[1, 2, 2, 3, 4, 2]
[1, 3, 2, 2, 2, 4]
[1, 4, 2, 2, 2, 3]
バッチリです!(もう少し,24パターンを調べるプロセスを工夫したいです。)
GitHubが数式対応!
今回のものはGitHubに公開してます。最近GitHubは数式対応(こちらはMathJax)したようでみなさん騒いでいます!.ipynb
ファイルなのでZennへ埋め込まれたところはまだちゃんと表示れていないようです。まあ,こっちは
Discussion