入れ子ループ
縦と横の 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 のように分けます。
行の入れ物を、どこで空に戻すか
表を 1 本の文字列にするときは、2 段構えで作ります。まず内側のループで 1 行分 を組み立て、それを外側のループで 表全体 に足していきます。
このとき肝心なのが、行の入れ物を空に戻す位置です。外側のループの中、内側のループの前 に置きます。ここが外側より前にあると、1 行目の中身が残ったまま 2 行目が足され、全部の行がつながって 1 行になります。
区切りを手前に足すやり方は、enumerate と zip のときと同じです。違うのは、行の中では半角スペース、行と行のあいだでは改行、と使う文字が 2 種類あることだけです。
入れ子ループが思ったとおりに動かないときは、内側だけを取り出して 1 行分が正しく作れるかを先に確かめます。切り分けてから組み立て直すほうが、まとめて直すより速いです。
回数は掛け算で増える
外側が 3 周、内側が毎周 3 回なら、いちばん内側の処理は 3 * 3 で 9 回動きます。外側が 100 で内側が 100 なら 1 万回です。入れ子ループでは、回数が足し算ではなく掛け算で増えます。
break と continue は、いちばん内側のループ 1 つ にしか効きません。内側で break しても、外側は次の周に進みます。外側まで一気に抜けたいときは、抜けたことを表す変数を用意して外側でも判定するか、処理を関数に切り出して return で抜けます。
やってみよう
関数 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 の1つだけにする
- for を入れ子にして、外側で行、内側で列を作る
- 同じ行の数は半角スペース1つで区切り、行と行は \n で区切る
- 末尾に改行を付けない。n が 0 のときは空文字を返す
入出力例
multiplication_table(3) → "1 2 3
2 4 6
3 6 9"
multiplication_table(2) → "1 2
2 4"
multiplication_table(1) → "1"
multiplication_table(9) → "1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81"
multiplication_table(0) → ""