入れ子ループ
縦と横の 2 方向に動きたい
ここまでのループは、1 本の列を上から下へなぞるものでした。ところが表を作りたいとなると、縦と横の 2 方向に動く必要があります。
そこで使うのが 入れ子ループ です。ループの中に、もう 1 つループを書きます。外側の for が 1 周する あいだに、内側の for が最後まで回りきります。
Python
for i in range(1, 4):
for j in range(1, 4):
print(i, j)9 行が表示されます。並びは 1 1、1 2、1 3、2 1 と続き、最後が 3 3 です。i が 1 つ進むあいだに j が 3 回まわっていることが読み取れます。
外側と内側で同じ変数名を使ってはいけません。内側でも i を使うと外側の i が上書きされ、進み方が壊れます。外側は i、内側は j のように分けます。
行の入れ物を、どこで空に戻すか
表の見た目まで手で作るなら、2 段構えになります。今回の演習ではこの整形を補助関数に任せます。まず内側のループで 1 行分 を組み立て、それを外側のループで 表全体 に足していきます。
このとき肝心なのが、行の入れ物を空に戻す位置です。外側のループの中、内側のループの前 に置きます。ここが外側より前にあると、1 行目の中身が残ったまま 2 行目が足され、全部の行がつながって 1 行になります。
区切りを手前に足すやり方は、enumerate と zip のときと同じです。違うのは、行の中では半角スペース、行と行のあいだでは改行、と使う文字が 2 種類あることだけです。
入れ子ループが思ったとおりに動かないときは、内側だけを取り出して 1 行分が正しく作れるかを先に確かめます。切り分けてから組み立て直すほうが、まとめて直すより速いです。
回数は掛け算で増える
外側が 3 周、内側が毎周 3 回なら、いちばん内側の処理は 3 * 3 で 9 回動きます。外側が 100 で内側が 100 なら 1 万回です。入れ子ループでは、回数が足し算ではなく掛け算で増えます。
break と continue は、いちばん内側のループ 1 つ にしか効きません。内側で break しても、外側は次の周に進みます。外側まで一気に抜けたいときは、抜けたことを表す変数を用意して外側でも判定するか、処理を関数に切り出して return で抜けます。
演習では計算と見た目を分ける
Python
pairs = []
for color in ["赤", "青"]:
for shape in ["丸", "四角"]:
pairs.append(color + shape)
print(pairs)["赤丸", "赤四角", "青丸", "青四角"] になります。外側の値一つに対して、内側の値を全部使います。演習でも一つのリストに順に結果をためます。表の空白と改行は _format_table が付けるので、二重ループと掛け算を自分で書いてください。
やってみよう
関数 multiplication_table(n) を実装してください。引数 n は表の大きさ (int) です。
1 から n までの縦横の掛け算をした表を、1 本の文字列として return します。同じ行の中の数は半角スペース 1 つで区切り、行と行は改行 \n で区切ります。末尾に改行は付けません。
multiplication_table(3) なら "1 2 3\n2 4 6\n3 6 9" です。n が 0 のときは空文字 "" を返します。multiplication_table(9) が本物の九九の表になることも確かめてみてください。
要件
- 関数名は multiplication_table で、引数は n の一つ
- 外側と内側の for で、それぞれ一から n まで動かす
- 内側で行の数と列の数を掛け、values に順に追加する
- 表への整形は _format_table(values, n) に任せる。n が 0 のときは空文字を返す