コンテンツへスキップ

【Ruby基礎】AtCoder Beginner Contest 065 A – Expired?

  • by

■はじめに

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

(5/23時点の方針)
メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。

(2022/10/17時点の方針)
しばらくはB問題を小さい番号の方からやっていく。たまにA問題もやるかも。

■問題

●出典

AtCoder Beginner Contest 065のA問題
https://atcoder.jp/contests/abc065/tasks/abc065_a

●問題文

高橋君は胃が強いので、賞味期限を X 日まで過ぎた食品を食べてもお腹を壊しません。 賞味期限を X+1 日以上過ぎた食品を食べると、お腹を壊します。

また、賞味期限を過ぎずに食べると、おいしく感じます。そうでない場合、おいしく感じません。

高橋君は、賞味期限の A 日前に食品を買ってきて、買ってから B 日後に食べました。

高橋君が食品をおいしく感じた場合 delicious を、おいしくは感じなかったがお腹は壊さなかった場合 safe を、お腹を壊した場合 dangerous を出力するプログラムを作成してください。

●制約

  • 1≦X,A,B≦10^9

●入力

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

X A B

●出力

高橋君が食品をおいしく感じた場合 delicious を、おいしくは感じなかったがお腹は壊さなかった場合 safe を、お腹を壊した場合 dangerous を出力せよ。

■回答

●愚直に書く

若干ややこしいが、紙に書き出して整理した。

  • bがa+xより大きい→自動的にdangerous
  • bがa+x以下→bとaの比較でsafedelicious か決まる

となるので、下記のようにした。

x, a, b = gets.split.map(&:to_i)

if b > a + x
  puts "dangerous"
elsif (b <= a + x) && (b > a)
  puts "safe"
else
  puts "delicious"
end

通った!

●メソッド化して書く

メソッドを作る練習のために、あえてそういう書き方をする。

def main
  x, a, b = read_nums
  puts is_expired?(x, a, b)
end

def is_expired?(x, a, b)
  if b > a + x
    "dangerous"
  elsif (b <= a + x) && (b > a)
    "safe"
  else
    "delicious"
  end
end

def read_nums
  gets.split.map(&:to_i)
end

main

通った!

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

時間がないので割愛。

●他の方の回答例

皆さんの条件がシンプルだなと思って見ていたら、そうか、僕がelsifでつけていた(b <= a + x)は、ifの条件が当てはまらない時点で絶対にtrueだから書く必要がないのか。

つまり下記で良い。

x, a, b = gets.split.map(&:to_i)

if b > a + x
  puts "dangerous"
elsif b > a
  puts "safe"
else
  puts "delicious"
end

あとは、今までちょっと避けていたけど入れ子の三項演算子を書いてみる。

x, a, b = gets.split.map(&:to_i)
puts b > a + x ? "dangerous" : b > a ? "safe" : "delicious"

可読性としてはifを使ったままの方が良い気もするけど、入れ子の三項演算子も慣れておきたい。

●出てきたメソッド等

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

今回は特に無し。

■振り返りなど

久しぶりにA問題。条件にちょっと手間取ったけど比較的スムーズにできて良かった。