IT1-CODE-POCKET

二重ループと2次元配列の読み方

第3問の後半、発展レベルで必ず出てくるのが表の形をしたデータです。 成績表、席の配置、曜日ごとの記録など、題材はさまざまですが、 読み方の型は1つしかありません。ここでその型を固めます。

BASIC

内側が先に最後まで回る

二重ループでは、内側の繰り返しが最後まで回りきってから、外側が1つ進みます。 外側と内側が交互に動くわけではありません。ここを取り違えると、順番を問う問題で必ず外します。

i を 1 から 3 まで 1 ずつ増やしながら繰り返す:
|j を 1 から 2 まで 1 ずつ増やしながら繰り返す:
⎿⎿ 表示する(i, j)

表示される順番は次のとおりです。

(1,1) (1,2)   ← i=1 のまま j だけが動く
(2,1) (2,2)   ← i が2になり、また j が1から
(3,1) (3,2)

外側の変数はゆっくり、内側の変数は速く動くと覚えてください。 時計の針でいえば、外側が時針、内側が分針です。

2次元配列は「行」と「列」

2次元配列は、配列の中に配列が入った形です。Table[r][c]r が行(縦の位置)、c が列(横の位置)を表します。行が先です。

Table = [
  [3, 1, 4],
  [2, 5, 0],
  [1, 2, 6]
]
c=0c=1c=2
r=0314
r=1250
r=2126

行も列も0から数えますTable[1][2] は 「2行目の3列目」つまり 0 です。 要素数(Table) は行の数(3)、要素数(Table[r]) は その行の列の数(3)を表します。

表記のゆれに注意:問題によっては Table[1, 2] のように カンマ区切りで書かれることがあります。意味は同じで[行, 列]の順です。 どちらの書き方でも、先に来るのが行だと覚えてください。

EXERCISE 1

例題1:値の位置を選ぶ

値 6 を取り出して x に代入するには、[ ア ]に何を入れればよいですか。

Table = [
    [1, 2, 3],
    [4, 5, 6]
]
x = Table[ ア ]
表示する(x)

選択肢:① [0, 2] ② [1, 2] ③ [2, 1] ④ [1, 3]

答えと解説を見る

答え:② [1, 2]

6 の位置を表で確かめます。

c=0c=1c=2
r=0123
r=1456

6 は2行目・3列目にあります。添字は0から始まるので、 行は 1、列は 2 となり Table[1, 2] です。

  • ① [0, 2] … 1行目3列目なので 3
  • ③ [2, 1] … 行と列を逆にした間違い。3行目は存在しないためエラー
  • ④ [1, 3] … 列を「3番目だから3」と数えた間違い。4列目は存在しない

③ と ④ が、もっとも多い2大ミスです。 「行が先」と「0から数える」の2つを同時に意識してください。

EXERCISE 2

例題2:二重ループの合計

次のプログラムを実行したとき、表示される値を選びなさい。

total = 0

i を 1 から 3 まで 1 ずつ増やしながら繰り返す:
|j を 1 から 2 まで 1 ずつ増やしながら繰り返す:
⎿⎿ total = total + i × j

表示する(total)

選択肢:① 6 ② 12 ③ 18 ④ 24

答えと解説を見る

答え:③ 18

6回の繰り返しそれぞれで i × j を足します。 内側の j が先に動くことを意識して、順番どおりに表を作ります。

iji × jtotal
11111
21223
32125
42249
531312
632618

合計は 1+2+2+4+3+6 = 18 です。 ① の6は「回数」を答えてしまった場合、② の12は5回目までで止めた場合に選びます。

表を6行きちんと書けば必ず合います。 暗算しようとすると、i と j のどちらが動いているか分からなくなります。

EXERCISE 3

例題3:列ごとに合計する

各列の合計を ColSum に入れます。空欄 [ ア ] に入る式として正しいものを選びなさい。

Table = [
  [3, 1, 4],
  [2, 5, 0],
  [1, 2, 6]
]
ColSum = [0, 0, 0]

r を 0 から 要素数(Table) - 1 まで 1 ずつ増やしながら繰り返す:
|c を 0 から 要素数(Table[r]) - 1 まで 1 ずつ増やしながら繰り返す:
⎿⎿ ColSum[c] = ColSum[c] + [ ア ]

表示する(ColSum)

選択肢:① Table[r][c] ② Table[c][r] ③ Table[r] ④ ColSum[c]

答えと解説を見る

答え:① Table[r][c]

ColSum[c] は「c列目の合計」を入れる場所です。 そこに足すべきなのは、いま見ている r 行 c 列の値、つまり Table[r][c] です。

足す先が [c] だから、足す値も [c] を含む——この対応で確認できます。 r が変わるたびに同じ ColSum[c] に積み上がっていくため、列ごとの合計になります。

rColSum[0]ColSum[1]ColSum[2]
開始000
0行目後314
1行目後564
2行目後6810

② Table[c][r] は行と列を逆にした間違いで、 表が正方形(3×3)だとエラーにならず、違う答えが出てしまうのがやっかいなところです。 この場合 ColSum は [6, 8, 10] ではなく [8, 8, 8] になります。

行と列の対応を確かめる方法:外側の変数(r)が要素数(Table)で回っていれば r は行、 内側(c)が 要素数(Table[r]) で回っていれば c は列です。 繰り返しの範囲を見れば、どちらが行か分かります。

PATTERN

行ごと集計と列ごと集計の書き分け

表の問題は、結局この2つのどちらかです。合計を入れる変数をどこで初期化するかが違います。

行ごとの合計 列ごとの合計
合計を入れる変数 total(1つ) ColSum(列の数だけの配列)
初期化の位置 外側ループの中(行が変わるたび0に戻す) ループの前(1回だけ)
足す先 total ColSum[c]

「total = 0」がループの中にあるか外にあるか——これが読み分けの決め手です。 中にあれば行ごとにリセットされるので行単位の集計、 外にあれば最後まで積み上がるので全体または列単位の集計です。 穴埋めで初期化の位置が問われることもあります。

best = 0
r を 0 から 要素数(Table) - 1 まで 1 ずつ増やしながら繰り返す:
|total = 0                          ← 行が変わるたびに0へ
|c を 0 から 要素数(Table[r]) - 1 まで 1 ずつ増やしながら繰り返す:
|⎿ total = total + Table[r][c]
|もし total > best ならば:
⎿⎿ best = total

表示する(best)

これは「行ごとの合計を求め、その最大を探す」という頻出パターンです。 total = 0 が内側ループの直前にあることを確認してください。 ここが外に出ていると、全部の行が足し合わさってしまいます。

EXERCISE 4

例題4:条件に合うマスを数える

次のプログラムで、count = count + 1 は何回実行されますか。

Score = [
  [2, 0, 1],
  [0, 3, 2],
  [4, 1, 0]
]
count = 0

r を 0 から 要素数(Score) - 1 まで 1 ずつ増やしながら繰り返す:
|c を 0 から 要素数(Score[r]) - 1 まで 1 ずつ増やしながら繰り返す:
||もし Score[r][c] >= 2 ならば:
⎿⎿⎿ count = count + 1

表示する(count)

選択肢:① 3回 ② 4回 ③ 5回 ④ 9回

答えと解説を見る

答え:② 4回

二重ループに条件分岐が加わった形です。 ここで問われているのは「二重ループが何回まわるか」ではなく、 「その中で条件が成り立つのが何回か」という点に注意してください。

二重ループ自体は 3 × 3 = 9回まわります。 そのうち >= 2 を満たすマスだけを数えます。 表に○をつけていくのが最も確実です。

c=0c=1c=2
r=02 ○0 ×1 ×
r=10 ×3 ○2 ○
r=24 ○1 ×0 ×

○は 2・3・2・4 の4個です。 >= 2 なので2ちょうども含む点を見落とさないでください。

  • ① 3回> 2 と読み違えた場合です。 3 と 4 だけになり、2 が2つ抜け落ちます。等号を含むかどうかは毎回確認してください
  • ④ 9回 … 条件分岐を無視して、二重ループの回数をそのまま答えた場合です
この問題は3つの読み取りを同時に要求しています。 ①二重ループの回数(9回)、②条件の向きと等号(>=)、 ③数えているのがマスの個数であって合計ではないこと。 表に○×を書き込む1手間を惜しまなければ、確実に取れる問題です。

EXERCISE 5

例題5:集計してから、その最大値を求める

次のプログラムを実行したとき、表示される best の値として正しいものを選びなさい。

Table = [
  [3, 1, 4],
  [2, 5, 0],
  [1, 2, 6]
]
ColSum = [0, 0, 0]

r を 0 から 要素数(Table) - 1 まで 1 ずつ増やしながら繰り返す:
|c を 0 から 要素数(Table[r]) - 1 まで 1 ずつ増やしながら繰り返す:
⎿⎿ ColSum[c] = ColSum[c] + Table[r][c]

best = 0
i を 0 から 要素数(ColSum) - 1 まで 1 ずつ増やしながら繰り返す:
|もし ColSum[i] > best ならば:
⎿⎿ best = ColSum[i]

表示する(best)

選択肢:① 6 ② 8 ③ 10 ④ 21

答えと解説を見る

答え:③ 10

繰り返しが2つに分かれているのがポイントです。 長く見えますが、前半と後半をまったく別のプログラムとして順に処理すれば難しくありません。

  1. 前半(二重ループ) … 列ごとの合計を ColSum に作る
  2. 後半(1重ループ) … できあがった ColSum の中から最大値を探す

まず前半です。ColSum[c]添字が c だけなので、 同じ列の値が1か所に集まっていきます

c=0c=1c=2
r=0314
r=1250
r=2126
ColSum6810

ColSum は [6, 8, 10] になります。 後半はこの3つから最大値を探すだけなので、10 が答えです。

  • ① 6 … ColSum[0] です。最大値を探す後半を読まずに止まった場合です
  • ② 8 … 真ん中の列の合計です
  • ④ 21 … 表の全部を足した値です。ColSum[c]total と読み違えると、この値になります
「集計してから、その結果をさらに処理する」二段構えは第3問の定番です。 長いプログラムを見たら、まず繰り返しの区切りで前半・後半に分けること。 そして前半が終わった時点での配列の中身を必ず書き出すこと。 この2つを守れば、後半は最大値を探す処理の基本形に戻ります。

CODE

3つの表記での書き方の違い

Table = [[3, 1, 4], [2, 5, 0], [1, 2, 6]]
ColSum = [0, 0, 0]

r を 0 から 要素数(Table) - 1 まで 1 ずつ増やしながら繰り返す:
|c を 0 から 要素数(Table[r]) - 1 まで 1 ずつ増やしながら繰り返す:
⎿⎿ ColSum[c] = ColSum[c] + Table[r][c]

表示する(ColSum)
行の数と列の数の求め方: 擬似言語の 要素数(Table) は Python の len(table)、 JavaScript の table.length にあたり、いずれも行の数です。 要素数(Table[r])len(table[r])table[r].length で、 r 行目の列の数です。 列の数を 要素数(Table) で書いてしまう間違いに注意してください。

CHECK

このテーマのチェックリスト

表の問題が読めるようになれば、発展レベルの多くが解けるようになります。 実際の問題はクイズの「発展」に入っています。

次に読むページ