コンテンツへスキップ

【Ruby基礎】AtCoder Beginner Contest 024 A – 動物園

■はじめに

Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。
基本的にはAtCoderというプログラミングコンテスト(競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)

■問題

●出典

AtCoder Beginner Contest 024のA問題
https://atcoder.jp/contests/abc024/tasks/abc024_a

●問題文

ABC動物園は、高橋王国で一番の人気を誇る動物園です。
ABC動物園の入場料の設定は以下のようになっています。

  • 子供 1 人あたり A 円
  • 大人 1 人あたり B 円
  • 合計人数が K 人以上の団体は 1 人あたり C 円引き

今、子供 S 人、大人 T 人からなる団体が入場しようとしています。 この団体が合計で支払わなければならない入場料を求めてください。

●入力

入力は以下の形式で標準入力から与えられる。

A B C K
S T
  • 1 行目には入場料の値段設定を表す 4 つの整数 A,B,C,K が空白区切りで与えられる。各変数の意味は問題文と同様である。各変数は以下の制約を満たす。
    • 0≦C≦A≦B≦1,000
    • 0≦K≦100
  • 2 行目には団体が含む子供と大人の人数を表す 2 つの整数 S(0≦S≦100),T(0≦T≦100) が空白区切りで与えられる。

●出力

団体が合計で支払わなければならない入場料を 1 行に出力せよ。 出力の末尾に改行を入れること。

■回答

●愚直に書く

方針としては下記

  • 6つの入力をそれぞれ個別に取れるようにする
  • 割引前の合計を求める
  • 割引額を求める
  • 条件に合致したら割引するようにする
a, b, c, k = gets.split.map(&:to_i)
s, t = gets.split.map(&:to_i)

subtotal = a * s + b * t
discount = c * (s + t)
if k >= 20
  puts subtotal - discount
else
  puts subtotal
end

あれ、上記で出したらWA(いくつか通らない)になった…。
もう一度問題をよく読む。
割引の条件がおかしかった。「合計人数がK人以上」のところを、勝手に20人以上にしていた…。

a, b, c, k = gets.split.map(&:to_i)
s, t = gets.split.map(&:to_i)

subtotal = a * s + b * t
discount = c * (s + t)
if s + t >= k
  puts subtotal - discount
else
  puts subtotal
end

これで通った!

●リファクタリング/別アプローチ

今回はちょっとだけやることが多かったので三項演算子とか変数化の省略とかのことを考えずにまず出したので、これをコンパクトにしていく。

a, b, c, k = gets.split.map(&:to_i)
s, t = gets.split.map(&:to_i)

subtotal = a * s + b * t
puts s + t >= k ? subtotal - c * (s + t) : subtotal

まぁまぁコンパクトになったかな…?

●他の方の回答例

ロジックとしては自分の回答とおおよそ似通っている気がするけど、最上位の方々の回答は相変わらずわからない部分が多い…。
ddコマンドというのはRubyじゃなくてLinuxのコマンドなのか。

●出てきたメソッド等

公式リファレンスを見る訓練。

■振り返りなど

今回も手応えのある問題だった。これくらいの難易度でいろいろな種類の問題をやっていきたい。