【Ruby基礎】AtCoder Beginner Contest 022 A – Best Body

■はじめに

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

■問題

●出典

AtCoder Beginner Contest 022のA問題
https://atcoder.jp/contests/abc022/tasks/abc022_a

●問題文

高橋君は太りやすく痩せやすい体質です。そこで彼は N 日間の体重の変化量を記録してみました。
1 日目の高橋くんの体重は W キログラムでした。 i 日目 (2≦i≦N) の体重の変化量は Ai キログラムでした(Ai は負になり得ます)。 つまり i−1 日目の体重を X キログラムとすると、 i 日目の体重は X+Ai キログラムだったということです。
ところで、高橋君の個人的な価値観では、体重が S キログラム以上 T キログラム以下の体型が「ベストボディー」だと考えています。
体重を記録した N 日間のうち、高橋君がベストボディーであった日数を求めてください。

●入力

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

N S T
W
A2
A3
:
AN
  • 1 行目には高橋君が体重を記録した日数を表す整数 N(2≦N≦1,000) 、ベストボディーの基準となる値 S,T(1≦S≦T≦10^5) が空白区切りで与えられる。
  • 2 行目には 1 日目の高橋君の体重を表す整数 W(1≦W≦10^5 ) が与えられる。
  • 3 行目からの N−1 行のうち i 行目には i+1 日目の体重の変化量を表す整数 Ai+1
    (−10^5 ≦Ai+1 ≦10^5 ) が与えられる。
  • 高橋君の体重が 0 キログラム以下になることはない。

●出力

高橋君がベストボディーであった日数を 1 行で出力せよ。出力の末尾にも改行を入れること。

■回答

●愚直に書く

これは入力がまず難しい系だ…。

  • 高橋くんの体重を1日目から最終日まで順番に並んだ数値を配列に入れる
  • 上記配列の要素の中で、S以上T以下になっているものの個数を数える

という方針でやってみる。

まずは

n = gets.split.map(&:to_i)
w = gets.to_i

weight = w
ary = (n[0] - 1).times.map do
  weight += gets.to_i
end
ary.unshift(w)
p ary

上記で、例えば入力が

5 60 70
50
10
10
10
10

上記だった場合に

[50, 60, 70, 80, 90]

と表示できた!

続いて後半。
上記で作った配列の中でS以上T以下が該当する要素の個数を数える。
条件に合う要素を抽出するのはselectを使って、配列の要素数を数えるのはcountを使う。

前半のコードと合わせて、

n = gets.split.map(&:to_i)
w = gets.to_i

weight = w
ary = (n[0] - 1).times.map do
  weight += gets.to_i
end
ary.unshift(w)

new_ary = ary.select do |x|
  n[1] <= x && x <= n[2]
end

p new_ary.count

これで通った!

ちなみに
n[1] <= x <= n[2]のように比較演算を2個繋げて書くのはできない。(前も間違えた気がするけど忘れてた…)

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

ここまでに手間取りすぎたので割愛

●他の方の回答例

上位層の回答はちょっと難しかったけど汗、少し下の方を見て自分の回答の方針に近い方の回答をもとに整理したのが下記

n, s, t = gets.split.map(&:to_i)
w = 0
b = 0
n.times do
  w += gets.to_i
  b += 1 if s <= w && w <= t
end
p b
  • n, s, t = gets.split.map(&:to_i)なんていう取り方ができるのか。
  • b = 0で最終的にカウントする数値もtimesメソッドの中で足し上げていくのか、なるほど。

●出てきたメソッド等

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

■振り返りなど

2日前にやったB問題より確実に難しい気がする汗。
だいぶ手こずったけど、まずこれくらいの問題を迷いなく書けるようになりたい。