4月19日、AtCoder Beginner Contest 163にRubyで参加しました。今回はB問題の復習です。
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.sum
(sum
は配列の要素の合計を返す)で取得して変数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のときの処理