コンテンツへスキップ

【Ruby基礎】AtCoder Beginner Contest 058 A – ι⊥l

  • by

■はじめに

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

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

■問題

●出典

AtCoder Beginner Contest 058のA問題
https://atcoder.jp/contests/abc058/tasks/abc058_a

●問題文

3 本の柱が等間隔に並んでいます。柱の高さは左から順に a メートル, b メートル, c メートル です。 柱の先端が同一直線上に並んでいる時、つまり b−a=c−b を満たしているとき、 この柱の並び方を美しいと呼びます。

柱の並び方が美しいかどうかを判定してください。

●制約

  • 1≤a,b,c≤100
  • a,b,c は整数である。

●入力

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

a b c

●出力

柱の並び方が美しい場合 YES を、そうでない場合 NO を 1 行に出力せよ。

■回答

●愚直に書く

まずは愚直に。b−a=c−b を条件にする。

a, b, c = gets.split.map(&:to_i)
if b - a == c - b
  puts "YES"
else
  puts "NO"
end

通った!文章中の=はコードでは==と書くので注意。

●メソッド化して書く

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

今回は、メインメソッド、「美しい」かの判定メソッド、標準入力を取るメソッドの3つ。

def main
  a, b, c = read_nums
  puts is_beautiful?(a, b, c)
end

def is_beautiful?(a, b, c)
  if b - a == c - b
    "YES"
  else
    "NO"
  end
end

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

main

通った!

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

まずは三項演算子。

a, b, c = gets.split.map(&:to_i)
puts b - a == c - b ? "YES" : "NO"

通った!

あと思いついたのは、前回出てきたsumを活かして、変数を1つの配列で標準入力を取得してsumして3で割ったものが配列2番目の要素と同じだったら条件を満たすような気がする。

n = gets.split.map(&:to_i)
puts (n.sum / 3 == n[1]) ? "YES" : "NO"

あれ、WA(一部結果がおかしい)になるな、、、どういう場合に条件を満たせなくなるんだろう…。

わからないので他の方の回答を見てみることにする。

●他の方の回答例

基本的な考え方はb−a=c−bを条件にする回答が多かった。
a+c=2bを条件にしている回答もあってなるほどと思った。自分の回答に適用すると下記になる。

a, b, c = gets.split.map(&:to_i)
puts a + c == b * 2 ? "YES" : "NO"

上位の回答を40個くらい見たけど、sumを使ってる人いなかったな…。WAになってしまう入力値を知りたい。
あっ、そうか、/3した時に余が出ると切り捨てられてしまっておかしくなる気がする。

n = gets.split.map(&:to_i)
puts (n.sum / 3.0 == n[1]) ? "YES" : "NO"

これで通った!
ただ、小数点のことをわざわざ考える必要があるということを踏まえると、今回は普通の解き方の方が良いか…。

●出てきたメソッド等

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

今回は特に無し。

■振り返りなど

今回のsumはそこまでスマートではなかったけど、WAの原因がわかったので良かった。