😊

立方体の6面色塗りの総数をJulia で解決!

2022/05/21に公開

はじめに

2022年度は中学3年生と高校2年生の授業を担当しています。

高校2年生は演習の授業で,『立方体の色塗り』の問題を取り上げました。演習なので,生徒はiPadなど使って発表します。

立方体の問題

立方体の問題の解答

6色

上面を塗る色を定めておいて,残り5色の中の1色で底面を塗り,次に側面を塗る。側面の塗り方は円順列の数である。

\therefore{}_{5} {\rm C}_1\times (4-1)\, ! =\boldsymbol{ 30}\text{\bf (通り)}

3色

3色の選び方は{}_{6} {\rm C}_3通り。同じ色で対面を塗る方法は1通り。

\therefore{}_{6} {\rm C}_3\times 1=\boldsymbol{ 20}\text{\bf (通り)}

4色

4色の選び方は{}_{6} {\rm C}_4通り。その中の2色を選んで2対の面を塗る。次に, 残りの1対の面の1面ずつを残り2色で塗る。このとき,2色を逆に塗っても塗り分け方としては同じである。

\therefore{}_{6} {\rm C}_4\times {}_{4} {\rm C}_2=\boldsymbol{ 90}\text{\bf (通り)}

生徒の発表が終わって

少し時間があったので,『発表バッチリですね。この3色・4色の問題で隣り合う面は同色でも良いとしたら何通りだろう? 例えば,立方体の6つの面を赤で2面,青で2面,黄で2面塗ることにする。塗り方は全部で何通りになるかな?』

と生徒に振ったものの,『ちょっと大変だぞ・・・』という予感。生徒にはポリドロンというおもちゃを渡して,立体を作ってもらいました。

https://www.tokyo-shoseki.co.jp/polydron/

Twitterへ

Twitterへ投げたところ,@ysmemoirsさんなどが反応してくれました。

https://twitter.com/dannchu/status/1527204070712152065

https://twitter.com/ysmemoirs/status/1527205046844239873

https://twitter.com/ysmemoirs/status/1527207094180405248

https://twitter.com/ysmemoirs/status/1527208026339282944

考察1

@ysmemoirsさんも書いているように,赤2青2黄2を1列に並べると

\dfrac{6!}{2!2!2!}=90(通り)

となります。なので,多くても90通りとなります。

また,6色を1列に並べると6!=720通りあるのですが,解答にもあるように立方体の6つの面に塗ると30通りです。ということは

\dfrac{720}{30}=24(パターン)

1列に並べた時に24パターンを1つと数えているわけです。

今回,1列に並べて90通りなので,

\dfrac{90}{24}=3.75(パターン)

となり,少なくとも4通りはあることがわかりました。

https://twitter.com/dannchu/status/1527542890251300864

考察2

『そんなにいっぱいはないだろう』という感じで,とりあえず,どんなパターンがあるか作りながら感げてみました。

https://twitter.com/dannchu/status/1527544328998240256

  • 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\times 1+24\times 2+12\times 3=6+48+36=90

となります。答えは 6通り となりました。

Juliaでコード作成

コード作成の方針

『立方体の色塗り』は高校の教材でよく出てきるのですが,今回考えた『隣り合うところに同色を塗ってもよい』という条件がついた問題はあまりありません。やっぱり難しいからです。答えが出せたとしても,『他にないのか?』と考えると,上述のように,1列に並べて分類するしかありません。(
本当はちゃんと理論があると思います。)

立方体の色塗りの場合,最大でも24パターンを1通りとすることがわかっているので,これらをちゃんと調べて,除いていくコードを考えました。

24パターンを巡回してく

そこで,この『24パターンをどう記述するか?』となるのですが,24パターンはわかっているので,それらを書いてしまうこともできたのですが,ちょっとミスすると,後でチェックするのが大変そうだったので,24パターンを順々に定めていく方法を考えました。

3つの操作の組み合わせ

これは,恐らく色々あるのだろうな?と思ったのですが,とりあえず,以下の3つの操作を組み合わせることにしました。操作は6\times6の行列を使うことにしました。

A 右回り

1 2 3 4 5 6
1 2 6 5 3 4
A=\begin{pmatrix} 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 \\ \end{pmatrix}

B 左回り

1 2 3 4 5 6
1 2 5 6 4 3
B=\begin{pmatrix} 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 \\ \end{pmatrix}=A^{-1}

C 左倒し

1 2 3 4 5 6
3 4 2 1 5 6
C=\begin{pmatrix} 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 \\ \end{pmatrix}

これらの行列によって

AAACBBBCAAACBBBCAAACBBBC

の順で操作することによって,24パターンの配置を順々に調べることができます。

下の展開図を参考にしました。

コード可

juliaでコーディングです。パッケージはCombinatorics.jlLinearAlgebra.jlです。

cubeperm
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へ埋め込まれたところはまだちゃんと表示れていないようです。まあ,こっちは\KaTeXだしね。

https://github.com/shimizudan/20220519cube222/blob/master/519.ipynb

Discussion