INDEX
■はじめに
Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。
基本的にはAtCoderというプログラミングコンテスト(競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)
(5/23時点の方針)
メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。
(2022/10/17時点の方針)
しばらくはB問題を小さい番号の方からやっていく。たまにA問題もやるかも。
■問題
●出典
AtCoder Beginner Contest 071のA問題
https://atcoder.jp/contests/abc071/tasks/abc071_a
●問題文
すぬけ君は,数直線上の位置 x に住んでいます. また,位置 a,b にはそれぞれ出前を行っている店 A,B が存在します.
すぬけ君は,店 A,B のうち,より近いほうから出前をとることにしました. どちらの店がすぬけ君の住んでいる位置により近いかを求めてください.
ただし,数直線上の 2 点 s,t の間の距離は ∣s−t∣ で表されます.
●制約
- 1≤x≤1000
- 1≤a≤1000
- 1≤b≤1000
- x,a,b は互いに異なる
- すぬけ君の位置から店 A,B までの距離は異なる
●入力
入力は以下の形式で標準入力から与えられる。
x a b
●出力
店 A のほうが近いなら A を,店 B のほうが近いなら B を出力せよ.
■回答
●愚直に書く
x-a
とx-b
の絶対値の小さい方、という感じかな?
えーと、小さい方の数値をただ出すだけならmin
メソッドで一発だけど、小さい数値になるのはaかbのどちらか、となると、条件分岐でputsすることになるのかな…?
x, a, b = gets.split.map(&:to_i)
p [(x - a).abs, (x - b).abs].min
上記だとaまでの距離とbまでの距離のうち小さい方の数値を出力することになるので、求める解答では無い。
x, a, b = gets.split.map(&:to_i)
puts (x - a).abs < (x - b).abs ? "A" : "B"
これで通った!
●メソッド化して書く
メソッドを作る練習のために、あえてそういう書き方をする。
今日は割愛。
●リファクタリング/別アプローチ
リファクタリングもちょっと思いつかないので割愛。
●他の方の回答例
基本的には皆さん同じ考え方だった。
ひとつ、宇宙船演算子を使っている解答があったのでメモ。
x, a, b = gets.split.map(&:to_i)
puts " BA"[(x - a).abs <=> (x - b).abs]
宇宙船演算子(<=>
)は、以下のように返す演算子。
10 <=> 20 # -1←左辺が小さい場合は-1
20 <=> 10 # 1←右辺が小さい場合は1
20 <=> 20 # 0←両辺が等しい場合は0
20 <=> '20' # nil←数値と文字列は比較できないのでnil
上記のコードを噛み砕くと、
" BA"[x]
というのは BA
(1文字目に半角スペースが入ってる)という文字列からx番目を表示する、と言う意味で、xの部分を宇宙船演算子によって以下3パターンに分けている。
-1
→これは後ろから1番目の意味なので、A
を返す1
→これは先頭から2番目の意味なので、B
を返す0
→これは先頭から1番目の意味なので、- ただし今回はaとbが異なる数値であることが保証されているので、
0
になることはない
- ただし今回はaとbが異なる数値であることが保証されているので、
なるほどな〜、面白い。
●出てきたメソッド等
公式リファレンスを見る訓練。
- Integer#abs
https://docs.ruby-lang.org/ja/latest/method/Integer/i/abs.html - Ruby の <=> 演算子が返す値を覚える方法(公式リファレンスではないが)
https://qiita.com/takuya0301/items/364f2b3f7ba2c36e0f62
■振り返りなど
宇宙船演算子。サラッと使ってみたい。