カンパニーレ(ネフ社)という積み木パズルについて、pythonを使って組み合わせを全パターン計算をしました。
ただの趣味で調べただけなので、実用的な内容ではありません。
手順
1.考察をして、フローチャートを作成
2.どのようにコーディングするか
3.コード
4.出力結果
1. 考察をして、フローチャートを作成
考察の部分は別の記事で紹介していますので、こちらをご覧ください。
考察によって、以下のフローチャートを得ることができました。

Fのまっさらな状態から、すべての色の矢印を1つずつ使って、Fに戻るパターンの組み合わせを求めればよいことが分かります。
2. どのようにコーディングするか
最近atcoderで勉強した、DFS(深さ優先探索),BFS(幅優先探索)を使えば簡単にできるのではないかと思ったのですが、
同じ色の矢印は1回しか使えないという制約があり、いい方法が思いつきませんでした。
今回は「濃青","青","濃緑","緑","黄緑","濃赤","薄赤","橙"」の8色をどの順番で使うかでチェックする方法にしました。
濃赤、緑は特定の場合に2種類の積み方があるため、その場合分けも必要になりました。
Excelへの書き込みは初めてやったので、とても簡単な内容ですが勉強になりました。
3. コード
from itertools import permutations
colorlist=["濃青","青","濃緑","緑","黄緑","濃赤","薄赤","橙"]#使用する積み木の色のリストです。
flowchart = [
[-1, 3, 1,-1,-1,-1,-1,-1],
[-1,-1, 0, 3, 2, 4, 1,-1],
[-1,-1,-1, 3, 1, 4, 2, 3],
[ 4,-1,-1,-1, 3, 1,-1,-1],
[-1, 0,-1, 1, 4,-1,-1, 2]
]#[i][j]について、iはA~Eの状態を0~4で、jはcolorlistの順、flowchart[i][j]は積み木を重ねた後の状態を0~4で表している
answerset = set()
def arrow(color:"色",point:"A~Eの状態",green,red): #point:A~Eにcolor:積み木の色を使ったときに状態を求める
if selectredgreen % 2 == 0 and color == "緑" and point == 4 :#緑①を使用しているかどうか
green = "緑①"
elif selectredgreen % 2 == 1 and color == "緑" and point == 4:
green = "緑②"
if selectredgreen <= 1 and color == "濃赤" and point == 3:
red = "赤①"
elif selectredgreen > 1 and color == "濃赤" and point == 3:
red = "赤②"
return flowchart[point][colorlist.index(color)],green,red
for selectredgreen in range(4):#濃赤①②と緑①②の場合分け
if selectredgreen % 2 == 0:
flowchart[4][3] = 1
else:
flowchart[4][3] = 2
if selectredgreen <= 1:
flowchart[3][5] = 1
else:
flowchart[3][5] = 2
for i in permutations(colorlist,8): #8色の色の順列
point = 3 #最初の状態 茶色を入れたのみなので状態D
flag = 0 #完成パターンであるかどうか
green = 0
red = 0
for j in range(8):
point,green,red = arrow(i[j],point,green,red)
if point == -1:
flag = 1
break
if flag == 0:
answerset.add((i,green,red))
import openpyxl
book = openpyxl.load_workbook('data.xlsx')# ブックを取得
sheet = book['Sheet1']# シートを取得
DarkBlue ='191970'# セルの背景色の設定
Blue ='0000ff'
DarkGreen ='006400'
Green ='228b22'
Greenyellow ='adff2f'
DarkRed ='8b0000'
Red ='ffa07a'
Orange ='ffa500'
fill = [
openpyxl.styles.PatternFill(patternType='solid',fgColor=DarkBlue , bgColor=DarkBlue ),
openpyxl.styles.PatternFill(patternType='solid',fgColor=Blue , bgColor=Blue ),
openpyxl.styles.PatternFill(patternType='solid',fgColor=DarkGreen , bgColor=DarkGreen ),
openpyxl.styles.PatternFill(patternType='solid',fgColor=Green , bgColor=Green ),
openpyxl.styles.PatternFill(patternType='solid',fgColor=Greenyellow, bgColor=Greenyellow),
openpyxl.styles.PatternFill(patternType='solid',fgColor=DarkRed , bgColor=DarkRed ),
openpyxl.styles.PatternFill(patternType='solid',fgColor=Red , bgColor=Red ),
openpyxl.styles.PatternFill(patternType='solid',fgColor=Orange , bgColor=Orange )
]
i = 1
for j in answerset:
for k in range(8):
sheet.cell(row=i, column=k+1).value = j[0][k]# セルへ書き込む
sheet.cell(row=i, column=k+1).fill = fill[colorlist.index(j[0][k])]
for l in range(1,3):
sheet.cell(row=i, column=l+8).value = j[l]
i += 1
book.save('data.xlsx')# 保存する
4. 出力結果
茶と黄を追加して、同じ色ごとに並べ替えて、セルの色も変更した状態です。