INDEX
■はじめに
Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。
基本的にはAtCoderというプログラミングコンテスト(競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)
■問題
●出典
AtCoder Beginner Contest 015のB問題
https://atcoder.jp/contests/abc015/tasks/abc015_2
●問題文
高橋くんは、上司から
- 会社で作っている N 個のソフトウェアに平均でどれくらいのバグがあるか調べろ
- ただし、バグがないソフトは調査母数に含めるな
と指示されました。
しかも、上司は小数が嫌いです。とはいえ、バグ数の平均値を過小報告するわけにもいかないので、値を切り上げて報告することにしました。
高橋くんは、素早くバグ数の平均値をまとめて上司に報告する必要があります。 ソフトウェアごとのバグ数が与えられるので、バグが含まれるソフトウェアの、バグ数の平均値を小数で切り上げて求めてください。
●入力
入力は以下の形式で標準入力から与えられる。
N
A1 A2 ... AN
- 1 行目には、ソフトウェアの数を表す整数 N(1≦N≦100) がスペース区切りで与えられる。
- 2 行目では、それぞれのソフトウェアに含まれるバグの数の情報が、スペース区切りで与えられる。 i 番目のソフトウェアのバグの数は、 i 番目に与えられる整数 Ai(0≦Ai≦100)によって与えられる。
- 与えられるソフトウェアのバグの合計数は、 1 つ以上であることが保証されている。
●出力
バグが含まれるソフトウェアの、バグ数の平均値を小数で切り上げて 1 行で出力せよ。出力の末尾には改行をいれること。
■回答
●愚直に書く
まずは標準入力を取る。
n = gets.to_i
a = gets.split.map(&:to_i)
「バグがないソフトは調査母数に含めない」を一旦無視してシンプルに「バグの合計を総ソフト数で割って繰り上げる」を作る。割った時に端数を表示するようにto_f
して、最後にceil
で繰り上げる。
(a.sum.to_f/n).ceil
ここまではうまくいった。
「バグがないソフトは調査母数に含めない」を考える。
a配列を見て「要素がゼロだったら取り除いて、取り除いた後の要素数を数える」という感じでできそう。
bug_files = a.delete_if{|x| x == 0}.size
最終的にできたのが下記
n = gets.to_i
a = gets.split.map(&:to_i)
bug_files = a.delete_if{|x| x == 0}.size
p (a.sum.to_f/bug_files).ceil
通った!!
●リファクタリング/別アプローチ
あまり思いつかないな〜。少しでもコード長を短くするなら変数名を短くするとか変数化をしないで1行にするとかもできそうだけど見づらくなりそうなので却下。
●他の方の回答例
delete_if
じゃなくてdelete
というメソッドもあるのか。
そして今知ったけどこれらは両方とも!
が付いていない破壊的メソッド。「破壊的メソッドは必ず!
がついてるわけではない」というのはよく見るけど例をすぐ忘れるのでメモ。
deleteを使ってbug_files
という変数化をやめると下記のような感じ。
n = gets.to_i
a = gets.split.map(&:to_i)
a.delete(0)
p (a.sum.to_f/a.size).ceil
通った!
●出てきたメソッド等
公式リファレンスを見る訓練。
- delete_if
https://docs.ruby-lang.org/ja/latest/method/Array/i/delete_if.html - delete
https://docs.ruby-lang.org/ja/latest/method/Array/i/delete.html
■振り返りなど
delete
delete_if
は破壊的メソッドというのを確認できて良かった。