1.はじめに
こんにちは。yutomanです。情シスの仕事を自動化したいという下心からpythonの勉強を始めた初学者です。
『退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング』(著・Al Sweigart,訳・相川 愛三,オライリージャパン,2017)を買ったは良いのですが理解するまでに七転八倒しましたので、せっかくならばこの七転八倒泥まみれの様子をお見せして、同じ空の下にいるどこかの初学者の一助になりたく、この記事を書きます。
2.転びながら解いていく
1.問題文を読む。
問題はまずはじめにリスト"grid"を読者に与えます。
"0"で模様を描いているようですが、どうやら横向きのハート型のようです。
問題文には
上記のgridの値を受け取り、次のような絵として表示するコードを書きなさい。
とあります。その直後に通常のハート型の絵が描かれていますので
このハート型を90度右に回転させるプログラムを書くことがこの問題の目的だとわかります。
2.とりあえず問題文で与えられたリストを書く。
まずは何はともあれ、材料となるリストを記載しておきます。
grid = [['.', '.', '.', '.', '.', '.', ],
['.', '0', '0', '.', '.', '.', ],
['0', '0', '0', '0', '.', '.', ],
['0', '0', '0', '0', '0', '.', ],
['.', '0', '0', '0', '0', '0', ],
['0', '0', '0', '0', '0', '.', ],
['0', '0', '0', '0', '.', '.', ],
['.', '0', '0', '.', '.', '.', ],
['.', '.', '.', '.', '.', '.', ]]
3.90度右に回転させる方法を考える。
さて、この絵を右に回転させると言ったって、一体どうしたら良いのでしょう。
考えてみると、スマホの画面に映った写真を回転させる時、写真は実際に回転しているのでしょうか?
いえ、違いますね。画像を構成する細かい点々が並び直されてあたかも右回転したように見えるだけです。
その発想を今回の問題にも適用させると、
プロセスは何でも良いから結果としてハートの形が右回転した形に変わっていれば良いということです。
したがって、リスト"grid"に並んでいる値(0と.)を取得して右回転したかのような形に並び直してしまえば良いのです。
4.1列目を取得する。
リスト"grid"はご丁寧にも"列"と"行"がわかりやすいように記載されています。
"列"とは表でいう"縦の並び"、"行"とは表でいう"横の並び"です。これが大きなヒントになっています。
つまりハートが右回転したように見えるには、
リスト"grid"の列が、行に並び変わっていれば良いのです。
と言う訳で、まずは左から1列目の値をすべて取得して、上から1行目に並べ直します。
リスト"grid"に注目しましょう。リストの中に、さらにリストがある構造をしています。
リストの中にリストがある場合、第1インデックスでどのリストか指定して、第2インデックスでそのリストの中の値を示すのでしたね。例えば"grid[0][0]"は、リスト0個目の0番目の値を指すわけです。これを繰り返して、左から1列目の値を取得し表示します。
print(grid[0][0]) #リスト0個目の0番目の値を表示
print(grid[1][0]) #リスト1個目の0番目の値を表示
print(grid[2][0]) #リスト2個目の0番目の値を表示
print(grid[3][0]) #リスト3個目の0番目の値を表示
print(grid[4][0]) #リスト4個目の0番目の値を表示
print(grid[5][0]) #リスト5個目の0番目の値を表示
print(grid[6][0]) #リスト6個目の0番目の値を表示
print(grid[7][0]) #リスト7個目の0番目の値を表示
print(grid[8][0]) #リスト8個目の0番目の値を表示
これを実行すると…
.
.
0
0
.
0
0
.
.
まぁそりゃそうだ。
これではただ1列目を取得して、また1列目に並び直しただけです。あまり意味がありません。
そこで、関数print()の呼び出し時に自動的に改行をさせないためのおまじない「end = ''」を第2引数に入れましょう。
print(grid[0][0], end = '')#0個目の0番目の値を標示
print(grid[1][0], end = '')#1個目の0番目の値を標示
print(grid[2][0], end = '')#2個目の0番目の値を標示
print(grid[3][0], end = '')#3個目の0番目の値を標示
print(grid[4][0], end = '')#4個目の0番目の値を標示
print(grid[5][0], end = '')#5個目の0番目の値を標示
print(grid[6][0], end = '')#6個目の0番目の値を標示
print(grid[7][0], end = '')#7個目の0番目の値を標示
print(grid[8][0], end = '')#8個目の0番目の値を標示
これを実行すると
..00.00..
おお!!1行目にきちんと並びました。
これをリスト"grid"の2列目、3列目…と繰り返していけば良いのです。
ん…?「繰り返し」…。そう!for文の出番ですね!
5.for文で繰り返し処理を行う。
リスト"grid"は6列ありますから、6回「4.1列目を取得する。」と同じ処理を繰り返す必要があります。
ただし、「4.1列目を取得する。」ではprint()関数を9回も書きました。最高にめんどくさいので、これも繰り返し処理をしましょう。
そもそも9回print()関数を書いたのは、リスト"gird"の要素が9つあるからでした。for文を使うとたった2行にまとめることができます。
for i in range(9):
print(grid[i][0], end = '')
ただし、
これは1~9個の要素の中の0番目の値、すなわち1列目の値を取得して1行目に並べているだけです。
そうなっている理由は「print(grid[i][0], end = '')」と2個目のインデックスを[0]と固定している為です。
つまりこの2個目のインデックスも繰り返し処理の中で変化していく必要があります。
2個目のインデックスは、「今何列目の値を取得しているか」を示しています。
したがって、繰り返しが始まった時は1で、繰り返しが終わる時は最終列、すなわち6になっている必要があります。
for j in range(6):
for i in range(9):
print(grid[i][j], end = '')
とします。
6.形を整える。
一見、先程の繰り返し処理で完璧にできたかに思えますが、
実はこのまま実行すると以下のように表示されます。
..00.00...0000000..0000000...00000.....000.......0....
うまく繰り返しはできているのですが
そのまま横一列に並んでしまうのです。
これを避けるには
列ごとの処理が終わったタイミングで改行させれば良いのです。
具体的には1つ目のfor文の中で、「print('')」と空白文字を記載するすることで、強制的に改行させます。
for j in range(6):
for i in range(len(grid)):
print(grid[i][j], end = '')
print('')
7.完成
grid = [['.', '.', '.', '.', '.', '.', ],
['.', '0', '0', '.', '.', '.', ],
['0', '0', '0', '0', '.', '.', ],
['0', '0', '0', '0', '0', '.', ],
['.', '0', '0', '0', '0', '0', ],
['0', '0', '0', '0', '0', '.', ],
['0', '0', '0', '0', '.', '.', ],
['.', '0', '0', '.', '.', '.', ],
['.', '.', '.', '.', '.', '.', ]]
for j in range(6):
for i in range(9):
print(grid[i][j], end = '')
print('')
..00.00..
.0000000.
.0000000.
..00000..
...000...
....0....
きちんと右回転(したかのように)できました!
今後も他の演習プロジェクトについて七転八倒解説を書いていきたいと思います!!
yutoman
3.参考
以下参考にさせていただきました。とても助かりました。
①『退屈なことはPythonにやらせよう』第4章演習プロジェクト 文字絵グリッド
②『退屈なことはPythonにやらせよう』4章 演習プロジェクト