A - We Love Golf(ABC165復習)

5月2日に開催されたAtCoder Beginner Contest 165Rubyで参加しました。

今日はA問題の復習です。

各問題の制約や入力・出力例はリンク先(AtCoderのサイト)をご覧ください。

A - We Love Golf

問題文
ジャンボ高橋君はゴルフの練習をすることにしました。
ジャンボ高橋君の目標は飛距離を K の倍数にすることですが、ジャンボ高橋君の出せる飛距離の範囲は A 以上 B 以下です。
目標の達成が可能であれば OK と、不可能であれば NG と出力してください。

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

A - We Love Golf

提出したコード

k = gets.to_f
a, b = gets.split.map(&:to_i)
c = (a / k).ceil
d = (b / k).floor
puts d - c >= 0 ? "OK" : "NG"

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

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

A以上B以下の範囲にKの倍数があればOK、なければNGを出力すればいいと考えました。

1行目:標準入力値を取得してto_fで文字列からFloat(小数)へ変換、kに代入

2行目:標準入力値を取得してa, bに代入

3行目:a / kの結果(小数)をceilで切り上げて整数にして c に代入

4行目:b / kの結果(小数)をfloorで切り捨てて整数にして d に代入

5行目:d - cが0以上ならA〜Bの間にKで割り切れる数(Kの倍数)があるということなのでOK、そうでなければNGを出力。

Float#ceil (Ruby 2.7.0 リファレンスマニュアル)

Float#floor (Ruby 2.7.0 リファレンスマニュアル)

数学的じゃないプログラムだなと思いながらも、時間制限もあったので提出しました。

もっといいプログラムにできないか考えてみました。

k = gets.to_f
a, b = gets.split.map(&:to_i)
(a..b).each do |n|
  if n % k == 0
    puts "OK"
    exit
  end
end
puts "NG"

AからBの範囲の数字を、1つずつKで割ってみて、n % k == 0つまり余りがゼロならOKを出力してそこでプログラム終了。余りがゼロにならなければexitが呼ばれないので最終行まで実行され、NGが出力されるというプログラムです。

breakは使ったことがあったのですが、exitは今回初めて知りました。exitが呼ばれると、そこでプログラムを終了させることができます。

上のコードでexitではなくbreakを使った場合、breakによりif文のループを抜けますがプログラムは終了しないので、最終行のNGが出力されてしまいます。

eachの代わりにuptoを使うこともできます。

k = gets.to_f
a, b = gets.split.map(&:to_i)
a.upto(b) do |n|
  if n % k == 0
    puts "OK"
    exit
  end
end
puts "NG"

Integer#upto (Ruby 2.7.0 リファレンスマニュアル)

今回はeachでもいいかなと思いますが、uptoの逆で1つずつ数を減らしながら処理できるdowntoは覚えておきたいですね。

Integer#downto (Ruby 2.7.0 リファレンスマニュアル)