B - Homework(AtCoder Beginner Contest 163復習)

4月19日、AtCoder Beginner Contest 163Rubyで参加しました。今回はB問題の復習です。

masuyama13.hatenablog.com

B - Homework

B - Homework

問題文

高橋君の夏休みは N 日間です。
夏休みの宿題が M 個出されており、i 番目の宿題をやるには Ai 日間かかります。
複数の宿題を同じ日にやることはできず、また、宿題をやる日には遊ぶことができません。
夏休み中に全ての宿題を終わらせるとき、最大何日間遊ぶことができますか?
ただし、夏休み中に全ての宿題を終わらせることができないときは、かわりに -1 を出力してください。

制約
1 ≤ N ≤ 106, 1 ≤ M ≤ 104, 1 ≤ Ai ≤ 104

入力
入力は以下の形式で標準入力から与えられる。
N M
A1...AM

出力
高橋君が遊ぶことのできる日数、または、-1 を出力せよ。

提出したコード

n, m = gets.split.map(&:to_i)
homeworks = gets.split.map(&:to_i)
homework_days = homeworks.sum
if homework_days > n
    puts -1
else
    puts n - homework_days
end

結果:AC(正解) 実行時間:56 ms

考えたことを言語化してみる

1行目:getsで標準入力値を取得し、splitで配列に入れて(末尾の改行も削除)、map(&:to_i)で各要素を文字列から整数に変換後、変数nとmにそれぞれ代入。(多重代入とmapの解説はこちら

2行目:標準入力の2行目の宿題にかかる日数(A1...AM)をgetsで取得し、1行目と同様配列に入れて整数に変換し、その配列にhomeworksという名前をつける。

3行目:宿題にかかる総日数をhomeworks.sumsumは配列の要素の合計を返す)で取得して変数homework_daysに代入。

4行目以降(if文):homework_days(宿題にかかる日数の合計)が、n(夏休みの日数)より大きければ、宿題は終わらないということなので-1を出力。そうでなければ(つまりhomework_daysがnより小さければ)、夏休みの日数 - 宿題にかかる日数 = 遊べる日数なので、n - homework_daysを出力。

改善点など

変数名のつけ方

振り返ってみて、まず変数名がよくないです。

ブログを書いていて気づいたのですが、homeworkは不可算名詞でした。homeworksなんて言葉は存在しない!

一方homework_daysは複数形になっているため配列じゃないのに配列みたいに見える。これもよくない。

つけ直すなら、一つ目の配列をhomeworksじゃなくてhomework_daysにして、合計日数の方は… homework_days_sumとか?競技プログラミングでは時間制限もあるので本番だったらhとかにしちゃいそう。解説でも記号になってました。

競技プログラミングでは深く考えなくてもいいのかもしれませんが、自分はプログラマになりたいので、変数名についてもちゃんと考えていきたいです。英語の勉強も少しずつやっていきます。

気になったこと

自分のプログラムでは、標準入力値のm(宿題の個数)を全く使っていません。言語によっては必要なのかもしれませんが、Rubyだと配列の要素数sizeなどでも取得できますし、使わないといけないということはなさそうです。

改善後のコード
n, m = gets.split.map(&:to_i)
homework_days = gets.split.map(&:to_i)
h = homework_days.sum
puts h > n ? -1 : n - h

(改善してみたところ)

  • 変数名の変更
  • if文を条件演算子に変更

条件演算子は、if文と同じように使えます。短く書けるので使えるようになりたいと思って初めて使ってみました。以下の2つは、同じ意味です。

if文:if 条件 (then) trueのときの処理 else falseのときの処理

条件演算子条件 ? trueのときの処理 : falseのときの処理

docs.ruby-lang.org