Q - 2.02.多重ループ 解説 /

実行時間制限: 0 msec / メモリ制限: 0 KiB

前のページ | 次のページ

キーポイント

  • ループ構文の中にさらにループ構文があるものを多重ループと呼ぶ
  • 多重ループを一度に抜けたい場合は、フラグ変数を用意してそれぞれのループを抜けるようにする必要がある

多重ループ

1.08 節で扱った while 文や 1.09 節で扱った for 文などのループは、さらにその中にループを書くことができます。

for i in range(3):
    for j in range(3):
        print(i, j)
実行結果
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2

このように、ループの内側にループがあるようなものを二重ループと呼びます。
二重だけでなく、当然三重ループや四重ループなどもあります。それらをまとめて多重ループと呼びます。

for i in range(2):
    for j in range(2):
        for k in range(2):
            print(i, j, k)
実行結果
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

二重ループを使って次の例題を解いてみましょう。


例題

要素数 3 の 2 つの数列 A, B に同じ要素が含まれているかどうかを判定してください。

入力の形式
A_1 A_2 A_3
B_1 B_2 B_3
入力例
1 3 2
4 5 3
出力例
YES

次のプログラムをベースに説明していきます。

# スペース区切りの整数をリストとして受け取る
A = list(map(int, input().split()))

# スペース区切りの整数をリストとして受け取る
B = list(map(int, input().split()))

# 答えを保持する変数
answer = False

# ここにプログラムを追記

if answer:
    print("YES")
else:
    print("NO")

AB の要素の組み合わせを全て見て、一致しているものがあるかを調べる」という方針で解くことにしましょう。

まず、ループを使わないで書いてみます。

# スペース区切りの整数をリストとして受け取る
A = list(map(int, input().split()))

# スペース区切りの整数をリストとして受け取る
B = list(map(int, input().split()))

# 答えを保持する変数
answer = False

if (A[0] == B[0] or A[0] == B[1] or A[0] == B[2] or
    A[1] == B[0] or A[1] == B[1] or A[1] == B[2] or
    A[2] == B[0] or A[2] == B[1] or A[2] == B[2]):
    answer = True

if answer:
    print("YES")
else:
    print("NO")

A に着目してパターン化すると次のような形式になっていることがわかります。

A[i] == B[0] or A[i] == B[1] or A[i] == B[2]

これをループ化してみます。

# スペース区切りの整数をリストとして受け取る
A = list(map(int, input().split()))

# スペース区切りの整数をリストとして受け取る
B = list(map(int, input().split()))

# 答えを保持する変数
answer = False

for i in range(3):
    if A[i] == B[0] or A[i] == B[1] or A[i] == B[2]:
        answer = True

if answer:
    print("YES")
else:
    print("NO")

次は B に着目してパターン化します。

A[i] == B[j]

最終的なプログラムは次のようになります。

# スペース区切りの整数をリストとして受け取る
A = list(map(int, input().split()))

# スペース区切りの整数をリストとして受け取る
B = list(map(int, input().split()))

# 答えを保持する変数
answer = False

for i in range(3):
    for j in range(3):
        if A[i] == B[j]:
            answer = True

if answer:
    print("YES")
else:
    print("NO")

多重ループの break/continue

for 文や while 文には break や continue という命令がありました。多重ループはループ文の中にループ文を入れたものなので、通常の for 文と同様に break/continue 命令を使うことができます。
多重ループで break 命令を使うと 1 段階ループを抜けることができます。内側のループの中で break すると内側のループを抜けることができますが、この break によって外側のループを抜けることはできません。

例えば、「i と j が両方 1 になったらループを抜ける」という処理を以下のようなコードで書いた場合、実行結果は意図したものにはなりません。

for i in range(3):
    for j in range(3):
        print(i, j)
        if i == 1 and j == 1:
            print("i と j が両方 1 なので終了(?)")
            break
実行結果
0 0
0 1
0 2
1 0
1 1
i と j が両方 1 なので終了(?)
2 0
2 1
2 2

多重ループを抜ける方法はいくつかありますが、そのうちのひとつとして「ループを抜けるかどうかを管理する変数(フラグ変数)を用意し、フラグ変数の値に応じてループを抜けるかどうか分岐する」という方法があります。

「i と j が両方 1 になったらループを抜ける」という処理を、フラグ変数を持つ方法で書くと以下のようになります。

# 外側のループを抜ける条件を満たしているかどうか(フラグ変数)
finished = False

for i in range(3):
    for j in range(3):
        print(i, j)
        if i == 1 and j == 1:
            print("i と j が両方 1 なので終了。")
            finished = True

        if finished:
            break

    if finished:
        break
実行結果
0 0
0 1
0 2
1 0
1 1
i と j が両方 1 なので終了。

また、フラグ変数を持つ方法以外に、多重ループの部分を関数化し return を用いて抜ける方法もあります。

def func():
    for i in range(3):
        for j in range(3):
            print(i, j)
            if i == 1 and j == 1:
                print("i と j が両方 1 なので終了。")
                return


func()
実行結果
0 0
0 1
0 2
1 0
1 1
i と j が両方 1 なので終了。

問題

リンク先の問題を解いてください。