LoginSignup
0
0

More than 1 year has passed since last update.

AtCoder ABC224B を Ruby らしく

Posted at

問題は以下を参照して下さい。

たんに四重ループ総当りで解ける簡単な問題ですが、Rubyらしくというのにこだわってみました。コードは以下です。

atcoder224b.rb
h, w = gets.split.map(&:to_i)
a = h.times.map { gets.split.map(&:to_i) }

def selected_loop(x)
  x.pred.times do |i1|
    (i1.next...x).each do |i2|
      yield(i1, i2)
    end
  end
end

e = Enumerator.new do |y|
  selected_loop(h) do |i1, i2|
    selected_loop(w) do |j1, j2|
      y << (a[i1][j1] + a[i2][j2] <= a[i2][j1] + a[i1][j2])
    end
  end
end

puts e.all? ? "Yes" : "No"

総当りの四重ループですが、行方向と列方向のループが同様に書けるので、自分でイテレータ(繰り返し用のメソッド)を定義してみました。それがselected_loopメソッドで、「ブロック」のついたメソッドとして定義されています。yieldがありますよね。ブロック変数には、行あるいは列方向に、あらかじめ条件を満たした数値が順に入ります。

もうひとつ工夫したのは、すべての判定をEnumerator化しているということです。変数eがそれです。問題の条件は、すべての判定が真なら Yes を出力せよということなので、それをEnumerable#all?メソッドでやりたかったのですね。

競プロで自分でイテレータ用メソッドを定義したり、Enumeratorをそれらしく使えたりする問題はあまりないので、趣味的にこだわってみました笑。

なお、この解法は短くもありませんし、速くもありません。ただ、可読性は多少よいのかなと思っています。

0
0
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
0
0