21
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby で競技プログラミングをするときのまとめ(多次元配列編)

21
Last updated at Posted at 2018-10-15
  • リクエストに応じて追記していきます。
  • 環境は 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] の処理
  }
}

両方(HW がわかっているなら上で十分)

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] のようにアクセスしたとき、ia.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(" ") }
21
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?