質問: gets.chomp.to_i n.times do gets.chomp.split(/\n/).map(&:to_i) できたらココの時点で def ~~(, , ,) ``` のようなメソッドで数値が入力されるごとにすぐ計算。そしてその結果は配列に入れておくなりして次の数字が入力される頃には引数が初期値に戻り、繰り返し。 のような再帰関数のような処理で行えないものかと思い質問させていただきました。 もしかしたらifなどのネストでやるべきかとも思いますが方法がありましたらぜひお願いします。 理解に努めますが、Ruby以外分からないのでその際は言葉で説明して頂けると助かります。 よろしくお願いいたします。
回答: もし、単純に「コード量を減らす」事が目的であれば、いわゆるコードゴルフというもので、いろいろなテクニックがあります。yukicoderでは正解(AC)になった回答を言語別にコードの長さ順で並べ替えられるので、他の人のテクニックを見ると良いでしょう。1バイト縮めるだけに全く違うアプローチを使うとか結構面白いです。ただ、一概にこうすると良いというのがないというのがあります。 そうではなく、可読性を上げたいというのであれば、次のように書くことをオススメします。 1. 始めに入力部分だけで完結させる。 2. 入力値から出力値を求める。 3. 最後は単に出力する。 例えば先ほどのyukicoderのNo.13 囲みたい!の問題を見てみましょう。入力の規則は下記のようになっています。 > > 1行目には 横を表すW (1≤W≤100)と縦を表すH (1≤H≤100)数値が半角スペース区切りで与えられる。 > > 2行目以降には、各行i列目j行目を表す数値Mij (1≤Mij≤1000)Mijが半角スペース区切りで与えられる。 > > > ``` w, h = gets.split.map(&:to_i) m = h.times.map { gets.split.map(&:to_i) } ``` これで、Mijが`m[j][i]`としてアクセス可能です。このあと、ゆっくり処理を考えます。 競プロでは入力に対して、処理の方が大変大きいです。その場合、入力をまとめて始めにやった方がわかりやすいですし、速度が不利になると言うことはありません。大量のログ解析やWebアクセスなどデータが大量にあり、入力に待ちが発生しやすい場合は、マルチスレッドにして各行を並列に読み込んで処理して、いらなくなったデータをどんどん捨てていく方が有利になりますが、入力が小さいときは無視できるような違いしかありません(かといって、別の所では必要になるテクニックではありますが)。 例題の場合はこうなります。 ※ 2.4.0で追加された`Array#sum`を使っているので、2.4.0以降でないと動きません。 ``` # frozen_string_literal: true # 入力処理 n = gets.to_i students = Array.new(n) { gets.split } .map { |field, *scores| [-field, scores.map(&:to_i)] } # 結果作成 results = students.map do |field, scores| next false if scores.sum < 350 case field when 'so' scores[0] + scores[4] >= 150 when 'sc' scores[1] + scores[3] >= 150 end end # 出力処理 students.zip(results).each do |student, result| if result case student.first when 'so' puts '文系クラス合格' when 'sc' puts '理系クラス合格' end else puts '残念でした' end end ``` 入力の時点で文系か理系かのところと各スコアを分離します。各スコアは数値に変換しておきます。文系か理系かはシンボルにしても良いかもしれません(でも、freezeしているから速度は違わないかな)。結果を求める処理では合格判定だけを結果として得ます。何を出力するかはその後です。最後に結果に基づき出力します。 競プロからは離れてしまいますが、本格的にやるにはクラスを作った方がRubyらしくなります。競プロはアルゴリズムしか重要視されませんが、本当に可読性を高めようと思うなら、細かくクラスやメソッドにわけることが重要になります。もうひとつ重要な考えとしてオブジェクトをmutableとimmutableのどちらで扱うかです。上記コードはimmutableで書いていますが、オブジェクトの生成にはコストがのしかかってくるため、処理時間がシビアな問題ではきつくなる場合があります。