5月2日に開催されたAtCoder Beginner Contest 165にRubyで参加しました。
今日はA問題の復習です。
各問題の制約や入力・出力例はリンク先(AtCoderのサイト)をご覧ください。
A - We Love Golf
問題文
ジャンボ高橋君はゴルフの練習をすることにしました。
ジャンボ高橋君の目標は飛距離を K の倍数にすることですが、ジャンボ高橋君の出せる飛距離の範囲は A 以上 B 以下です。
目標の達成が可能であればOK
と、不可能であればNG
と出力してください。入力
入力は以下の形式で標準入力から与えられる。
K
A B
提出したコード
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
は覚えておきたいですね。