Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PyconJP2018 09_18 小栗潤一 Pythonで「お絵描きパズル」を解いてみた
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
J-Ogu
September 18, 2018
Programming
3k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PyconJP2018 09_18 小栗潤一 Pythonで「お絵描きパズル」を解いてみた
発表で使用した資料をアップします。
J-Ogu
September 18, 2018
More Decks by J-Ogu
See All by J-Ogu
ビジネスPythonを学ぶ会_2020_11_09_Ogu
ogu
0
440
JBUG広島&JBUG岡山 #共同開催 2020_06_21 LT資料
ogu
1
490
すごい広島 With Python 発表資料_2020_0129
ogu
0
410
Pycon JP 2018 python_お絵描きパズルのロジックまとめ.pdf
ogu
1
1k
Other Decks in Programming
See All in Programming
技術記事、AIに書かせるか、自分で書くか? 〜それでも私が自分の手で書く理由〜 / #QiitaConference
jnchito
2
1.3k
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
630
エージェンティックRAGにAWSで入門しよう!
har1101
8
1.3k
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
210
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
320
RTSPクライアントを自作してみた話
simotin13
0
510
A2UI という光を覗いてみる
satohjohn
1
110
Webフレームワークの ベンチマークについて
yusukebe
0
150
プロパティの順序で型推論が壊れる!? TypeScript6.0の修正からContext-Sensitivityの仕組みを追う
bicstone
2
1.3k
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
0
170
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
140
セキュリティの専門家じゃなくてもできる。「セキュリティ意識」をアップデートして サプライチェーン攻撃への耐性を高めよう。
tk3fftk
5
660
Featured
See All Featured
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
200
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
How to Ace a Technical Interview
jacobian
281
24k
BBQ
matthewcrist
89
10k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
160
The Invisible Side of Design
smashingmag
302
52k
Building Flexible Design Systems
yeseniaperezcruz
330
40k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
840
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
The SEO Collaboration Effect
kristinabergwall1
1
480
Transcript
Pythonで 「お絵描きパズル」 を 解いてみた PyCon JP 2018 09_18 小栗 潤一
自己紹介
小栗 潤一 ・ 広島在住 ・ 大学時代は福岡で デザインの勉強 ・ 広島のチラシ制作会社勤務 3年間デザイナーとして働き
9年間社内業務改善のプログラマー 自己紹介
自己紹介 私とPythonについて ・ 勉強を初めて約2年 ・ 広島のもくもく会 「すごい広島」 「すごい広島 with Python」
今日の議題
Python初心者の私が約3ヶ月かけて ロジックを考えPythonのコードにした話^^ そのコードを使って 某懸賞雑誌一冊分 120問に挑戦しました どこまで解けたのかお楽しみに!!
今日の議題 ・お絵描きパズルのルール ・パズルを解くのにPythonを使用した利点 ・ロジックを考え、 コードにする話 ・Jupyter Notebookを使用したデモ ・120問中どこまで解けたのか? ・まとめ
お絵描きパズル とは
お絵描きパズルとは 数字をヒントに マスを塗っていき 現れたイラストを 答えるゲーム 1990年代に 流行
お絵描きパズルとは お絵かきロジック (世界文化社) ピクロス (任天堂) ののぐらむ イラストロジック 名称が違うだけで 同じルール
お絵描きパズルとは 用語の説明 白のマス ・ 処理が未確定の空白のマス ・ □□□で表現 ・ 配列内では[0, 0,
0] 黒のマス ・ 塗りが確定した塗りつぶしたマス ・ ▪▪▪で表現 ・ 配列内では[1, 1, 1] 塗り指示 ・ 問題の左・上辺にあるヒントの数字 ×のマス ・ 塗られないことが確定したマス ・ □□□で表現 ・ 配列内では[-1, -1, -1] ×××
「お絵描きパズルを解いてみた」 初心者が考えた Pythonの利点
「お絵描きパズルを解いてみた」 Pythonの利点 Pandas、 Numpyなどの便利なライブラリ [0,0,0,0,0,0,0,0,0,0] [10] [0,0,0,0,0,0,0,0,0,0] [3,2,2] DataFrame Numpyの配列計算
Series
それを踏まえて もう一度ご覧ください
「お絵描きパズルを解いてみた」 Pythonの利点 Pandas、 Numpyなどの便利なライブラリ [1, 1, 1, 1, 1, 1,
1, 1, 1, 1] [10] [1, 1, 1,-1, 1, 1,-1,-1, 1, 1] [3,2,2] DataFrame Numpyの配列計算 Series
「お絵描きパズルを解いてみた」 Pythonの利点 Jupyter Notebookを使った開発 ・ デモ環境 Jupyter Notebook ipywidgets RISE
(拡張機能)
Jupyter Notebookを使って 問題を解かせてみましょう or デバッグ環境の紹介
・Pandas,Numpyを使って 簡単な配列計算で解けそう ・ 動きのあるデバック環境が 簡単に作れる 私の考えたPythonを使う利点
お絵描きパズルのルール ロジックの話
お絵描きロジックの基本的なルール ・数字と同じマスを塗りつぶす ・数字が複数ある場合は必ず1マス以上空ける 3 2,3 2,2 3 3
アルゴリズム (ロジック) を考えてみましょう
ロジックを考える まずは手動で解いてみる 普段何気なく問題を解く際に 頭の中で行なっている アルゴリズムを書き出してみる
まずは問題を解いてみよう 処理1 確定マスの塗りつぶし 処理5 端から確定マスを見つける 処理2 端が確定した際の処理 処理6 指示の最大数と同じ連続した塗り 処理3
届かないマスの確定処理 処理7 端から指示 +1のマスが塗られていたら 処理9 端から 「1」 と 「2」 の連続した塗り指示の確定処理 処理4 「×」 のマスで分割して処理1〜3を実行 処理8 端から 「1」 の連続した塗り指示の確定処理 処理10 連続された塗りから対象の指示数字を特定する ロジックを書き出してみる
ロジックの構造と全体の流れ # 変数の指定 n_list = np.array([0, 0, 0, 0, 0,
0, 0, 0, 0, 0]) n_vals = [3,3] # 関数の指定 def nuri_syori(n_list, n_vals): ck_n_list = copy.copy(n_list) ck_n_list[0] = 2 while not np.allclose(n_list, ck_n_list) and 0 in n_list: ck_n_list = copy.copy(n_list) for i in range(2): # リストの反転 if i == 1: n_list = n_list[::-1] n_vals = n_vals[::-1] # 処理1〜10 logic_shori_1 () 〜 logic_shori_10 () # リストの反転(戻す処理) if i == 1: n_list = n_list[::-1] n_vals = n_vals[::-1]
ロジックで 某懸賞雑誌 120問に挑戦します どこまで解けたのでしょうか^^ ロジックの解説から始めましょう
6,2 処理1 確定マスの塗りつぶし 解き方
処理1 確定マスの塗りつぶし 解き方 6,2 6,2 6,2 6,2 左から詰めて6の配置 右から詰めて6の配置 左詰め時の一番右のマスから
右詰め時の一番左マスまでは確定 6,2 6,2 6,2 左から詰めて2の配置 右から詰めて2の配置 左詰め時の一番右のマスから 右詰め時の一番左マスまでは確定
解き方 n_list = np.array([0, 0, 0, 0, 0, 0, 0,
0, 0, 0]) n_vals = [6,2] # 隙間の数を埋める処理リファクト後の処理 for n,val in enumerate(n_vals): af = sum(n_vals[n:]) + len(n_vals[n:]) - 1 bf = sum(n_vals[:n+1]) + len(n_vals[:n+1]) - 1 if not list(n_list[-af:bf]):continue n_list[-af:bf] = 1 ## n_list = [0,1,1,1,1,1,0,0,1,0] 左から詰めて6の配置 6,2 右から詰めて6の配置 6,2 左詰め時の一番右のマスから 右詰め時の一番左マスまでは確定 6,2
処理2 端が確定した際の処理 解き方 3,2 3,2 × 3,2 最初は確定できるマスはありません 行 ・
列を進める際に確定マスができた 塗りマスと直後の 「×」 確定ができる
解き方 n_list = np.array([1, 0, 0, 0, 0, 0, 0,
0, 0, 0]) n_vals = [3,2] # 前方から処理 if n_list[0] == 1.0: n_list[0:n_vals[0]] = 1 n_list[n_vals[0]:n_vals[0]+1] = -1 # 後方から処理 if n_list[-1] == 1.0: n_list[-n_vals[-1]:len(n_list)] = 1 n_list[-n_vals[-1] -1:-n_vals[-1]] = -1 ## n_list = [1,1,1,-1,0,0,0,0,0,0] 3,2 × 3,2 行・列を進める際に確定マスができた 塗りマスと直後の 「×」 確定ができる
処理3 届かないマスの確定処理 解き方 3 3 × × × × ×
3 3 左右に3マス届く可能性のマス 届かないマスは塗られる可能性がないことが確定
解き方 n_list = np.array([0, 0, 0, 1, 0, 0, 0,
0, 0, 0]) n_vals = [3] # 指示が一つ以上あるものは処理中断 if not len(n_vals) == 1: return n_list leftNumm = int(np.where(n_list == 1)[0][0])+int(n_vals[0]) if leftNumm < len(n_list): n_list[leftNumm:len(n_list)] = -1 # 反転してもう一度 n_list = n_list[::-1] leftNumm = int(np.where(n_list == 1)[0][0])+int(n_vals[0]) if leftNumm < len(n_list): n_list[leftNumm:len(n_list)] = -1 # 反転してもとに戻す n_list = n_list[::-1] ## n_list = [-1,0,0,1,0,0,-1,-1,-1,-1] 3 × × × × × 3 3 左右に3マス届く可能性のマス 届かないマスは塗られる 可能性がないことが確定
処理1・2・3は最初に 実装したロジック 難易度★★☆☆☆ 28問中約8割の問題が 解けるようになった^^v
ロジックの言語化 Try & Err の繰り返し 処理1 確定マスの塗りつぶし 処理5 端から確定マスを見つける 処理2
端が確定した際の処理 処理6 指示の最大数と同じ連続した塗り 処理3 届かないマスの確定処理 処理7 端から指示 +1のマスが塗られていたら 処理9 端から 「1」 と 「2」 の連続した塗り指示の確定処理 処理4 「×」 のマスで分割して処理1〜3を実行 処理8 端から 「1」 の連続した塗り指示の確定処理 処理10 連続された塗りから対象の指示数字を特定する
ロジックの言語化 Try & Err の繰り返し 処理1 確定マスの塗りつぶし 処理5 端から確定マスを見つける 処理2
端が確定した際の処理 処理6 指示の最大数と同じ連続した塗り 処理3 届かないマスの確定処理 処理7 端から指示 +1のマスが塗られていたら 処理9 端から 「1」 と 「2」 の連続した塗り指示の確定処理 処理4 「×」 のマスで分割して処理1〜3を実行 処理8 端から 「1」 の連続した塗り指示の確定処理 処理10 連続された塗りから対象の指示数字を特定する 一部のロジックは Wikipediaに載ってる為、 本日は解説しません
まずは問題を解いてみよう 全てのロジックを まとめた資料 興味のある方は こちらから http://bit.ly/2PEDues
ロジックの言語化 Try & Err の繰り返し 処理1 確定マスの塗りつぶし 処理5 端から確定マスを見つける 処理2
端が確定した際の処理 処理6 指示の最大数と同じ連続した塗り 処理3 届かないマスの確定処理 処理7 端から指示 +1のマスが塗られていたら 処理9 端から 「1」 と 「2」 の連続した塗り指示の確定処理 処理4 「×」 のマスで分割して処理1〜3を実行 処理8 端から 「1」 の連続した塗り指示の確定処理 処理10 連続された塗りから対象の指示数字を特定する
wikiに載ってない オリジナルロジック の解説
処理7 端から指示 +1のマスが塗られていたら 5,1 × 5,1 5,1 × 5,1 左端から
「5」 を塗ったと仮定すると 「5」 の塗りの可能性は 左端のマスは塗られないことが確定
処理8 端から 「1」 の連続した塗り指示の確定処理 1,1,1,2 × × × × 1,1,1,2
× × × 1,1,1,2 仮に 「1」 が左から詰めて塗られていたら この範囲にある塗りは必ず 「1」 になる ここまではWikipediaに載ってるロジック
処理9 端から 「1」 と 「2」 の連続した塗り指示の確定処理 1,2,1,1 × 1,2,1,1 ×
1,2,1,1 × × × × 1,2,1,1 処理8は 「1の連続した」 という条件があった 「1と2の連続した」 という条件に変える この範囲にある[▪,□,▪]の[□]は×が確定
ロジックの言語化 難易度★★★★☆まで解ける(一部を除いて) 処理1 確定マスの塗りつぶし 処理5 端から確定マスを見つける 処理2 端が確定した際の処理 処理6 指示の最大数と同じ連続した塗り
処理3 届かないマスの確定処理 処理7 端から指示 +1のマスが塗られていたら 処理9 端から 「1」 と 「2」 の連続した塗り指示の確定処理 処理4 「×」 のマスで分割して処理1〜3を実行 処理8 端から 「1」 の連続した塗り指示の確定処理 処理10 連続された塗りから対象の指示数字を特定する どれ一つとして難しい 処理は行なっていません PandasのDataFrameを Seriesで取得して Numpyのndarrayに変換して 配列計算しているだけ
それでも解けない問題
・確定するマスがなくなる ・仮説処理で進めるしかない それでも解けない問題がでてくる
それでも解けない問題がでてくる 総当たり処理 ・確定するマスがなくなる ・仮説処理で進めるしかない
どれくらいの計算量になるのか? それでも解けない問題がでてくる × × × × × × 30 2,2,1,3,2,1,1
2,2,1,3,2,1,1 30 13 13**8= 815,730,721 ??????
それでも解けない問題がでてくる 総当たり処理 ・確定するマスがなくなる ・仮説処理で進めるしかない 計算量の少ない仮説
ではどう進める?
上下左右のうち 計算量の少ない1辺の 仮説を立てるだけ
仮説処理 1辺だけの総当たり処理 itertoolsを使って 4辺のパターン数を計算 1行目 :4パターン 15行目 :11パターン 1列目 :19パターン
20列目 :120パターン
仮説処理 1行目:4パターン そのまま最後まで解ける 確定マスがなくなる (さらなる仮説処理へ) 矛盾が発生 一番計算処理が少ない 辺から進める
仮説処理 0個 1個 複数 ありえない 確定パターン パターンを 記憶して 別の辺を進める 確定マスがなくなる
パターン数が重要
仮説処理 2つ目の辺も 複数残った場合は 1つ目と2つ目の パターンを 総当たりチェック 必ず確定パターンが見つかる 1つ目の辺の残った パターンを記憶して 2つ目の辺を仮説処理
仮説処理を 追加することで 懸賞雑誌に載っている 問題がほぼ全て解けた 難易度★★★★★
懸賞雑誌一冊分 120問中カラーロジックを除く 116問全て解けた ^^
本日デモに使用した 問題もPythonで自作 イラストから問題作成 作成した問題を解く
まとめ
まとめ ・Pythonには便利なライブラリが豊富にあり 「お絵描きパズル」 のような配列計算で答えが 出せるゲームと相性が良い ・ ロジックを考えるのは難しいが コード自体はDataFrameをSeriesで取得して Numpyのndarrayで計算している簡単なコード 「お絵描きパズル」
「数独」 とも相性がいい ぜひ自分でトライしてみてください ^ ^ v