- リクエストに応じて追記していきます。
- 環境は AtCoder を想定しています。なお AtCoder の Ruby のバージョンは 2018年10月現在 2.3.3 です。
入力について
入力が地図のパターン
$H$, $W$ は整数
$c_{i,j}$ はなんらかの文字
$H \quad W$
$c_{1,1}c_{1,2}...c_{1,W}$
$c_{2,1}c_{2,2}...c_{2,W}$
$:$
$c_{H,1}c_{H,2}...c_{H,W}$
文字列の配列にしたいとき
H, W = gets.split.map(&:to_i)
c = H.times.map { gets.chomp }
1文字ずつの二次元配列にしたいとき
H, W = gets.split.map(&:to_i)
c = H.times.map { gets.chomp.chars }
入力が数の二次元配列のパターン
$H$, $W$ は整数
$a_{i,j}$ は整数
$H \quad W$
$a_{1,1} \quad a_{1,2} \quad ... \quad a_{1,W}$
$a_{2,1} \quad a_{2,2} \quad ... \quad a_{2,W}$
$...$
$a_{H,1} \quad a_{H,2} \quad ... \quad a_{H,W}$
H, W = gets.split.map(&:to_i)
a = H.times.map { gets.split.map(&:to_i) }
入力が幅と高さのみで、二次元配列を自分で作るパターン
$H$, $W$ は整数
$H \quad W$
H, W = gets.split.map(&:to_i)
a = H.times.map {|i|
W.times.map {|j|
# i, j による初期値
}
}
処理について
文字列の配列の各文字ごとに何かしたいとき
文字だけでいいとき
c.each {|line|
line.chars {|ch|
# ch の処理
}
}
インデックスが必要なとき
H.times {|i|
W.times {|j|
# c[i][j] の処理
}
}
二次元配列の各要素ごとに何かしたいとき
要素だけでいいとき
a.each {|row|
row.each {|elem|
# elem の処理
}
}
インデックスが必要なとき
H.times {|i|
W.times {|j|
# a[i][j] の処理
}
}
両方(H と W がわかっているなら上で十分)
a.each_with_index {|row, i|
row.each_with_index {|elem, j|
# i, j, elem の処理
}
}
地図とかで上下左右を参照するとき
H.times {|i|
W.times {|j|
[
[-1, 0], # 上
[ 1, 0], # 下
[ 0, -1], # 左
[ 0, 1], # 右
].each {|di, dj|
if 0<=i+di && i+di<H && 0<=j+dj && j+dj<W
# c[i + di][j + dj] の処理
else
# 範囲外のときの処理
end
}
# c[i][j] の処理
}
}
地図とかで斜めも含め八方を参照するとき
H.times {|i|
W.times {|j|
(-1..1).each {|di|
(-1..1).each {|dj|
if di==0 && dj==0
# c[i][j] の処理
elsif 0<=i+di && i+di<H && 0<=j+dj && j+dj<W
# c[i + di][j + dj] の処理
else
# 範囲外のときの処理
end
}
}
# c[i][j] の処理
}
}
インデックスについて
注意1:範囲外のアクセス(size 以上のとき)
a[i][j] のようにアクセスしたとき、i が a.size 以上であると a[i] が nil を返し、そのまま [j] でアクセスしてエラーを起こします。
undefined method `[]' for nil:NilClass (NoMethodError)
対処法として、i の大きさを確認するか、a[i] が nil でないことを確認しましょう。
注意2:範囲外のアクセス(0 未満のとき)
注意1では触れませんでしたが、Ruby では 配列のインデックスに負数を指定することができます。
-1 が一番最後で、後ろから -1, -2, ... という具合で指定できます。
これは便利なときと不便なときがあって、地図が上下左右でつながっている(ドラクエみたいな)問題では便利ですが、そうでないときは不便です。
不要なときは i の大きさを確認しましょう。a[i] が nil であるとは限らなくなるので、 nil チェックは使えません。
出力について
c が文字列の配列のとき
puts c
c が文字の二次元配列のとき
puts c.map(&:join)
a が数値の二次元配列で、スペース区切りで出力するとき
puts a.map {|line| line.join(" ") }
または
a.each {|line| puts line.join(" ") }