コンテンツへスキップ

【Ruby基礎】AtCoder Beginner Contest 017 A – プロコン

  • by

■はじめに

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

■問題

●出典

AtCoder Beginner Contest 017のA問題
https://atcoder.jp/contests/abc017/tasks/abc017_1

●問題文

高橋君はプロコン(ここでいうプロコンとは、グラフ上に適切にプロットする力を問うコンテストである)に参加している。
高橋君は 3 つの課題に取り組んだ。
課題ごとに配点が定められており、各課題ごとに 1 以上 10 以下の整数による評価が付けられる。評価の数字が X であるとき、その課題においては配点の X 割の得点が与えられる。
3 つの課題の配点と評価が与えられるので、高橋君が合計で何点獲得したのかを求めてほしい。

●入力

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

s1 e1
s2 e2
s3 e3

(補足文は省略。 https://atcoder.jp/contests/abc017/tasks/abc017_1 を参照)

●出力

合計得点を 1 行に出力せよ。出力の末尾にも改行を入れること。

■回答

●愚直に書く

まずは標準入力を取る

x1 = gets.split.map(&:to_i)
x2 = gets.split.map(&:to_i)
x3 = gets.split.map(&:to_i)

p x1
p x2
p x3

これで、下記が入力された時に

50 7
40 8
30 9

下記が出力される。

[50, 7]
[40, 8]
[30, 9]

次は50×0.740×0.830×0.9をやっていくんだけど、条件の中に「sは10の倍数」とあるので、5×74×83×9とした方がto_fとかしなくて良いのでシンプルになりそう。
よって、愚直に書くとこんな感じか。

x1 = gets.split.map(&:to_i)
x2 = gets.split.map(&:to_i)
x3 = gets.split.map(&:to_i)

puts (x1[0]/10 * x1[1]) + (x2[0]/10 * x2[1]) + (x3[0]/10 * x3[1])

通った!

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

今回はリファクタリングが必要そう。
(xn[0]/10 * xn[1])というのが3回繰り返されているのでまとめたい。

x1 = gets.split.map(&:to_i)
x2 = gets.split.map(&:to_i)
x3 = gets.split.map(&:to_i)

two_ary =  x1.zip(x2, x3)
transpose = two_ary.transpose

sum = 0
transpose.each do |ary|
  sum += ary[0]/10*ary[1]
end
puts sum

transposeまで使って無理やりまとめたけど、絶対もっとシンプルに書ける気がする…。うーんでも限界なので打ち止め。

●他の方の回答例

うーん上位の方々の回答、難しい…。
injectがよく出てくる。

下記くらいの書き方は自分にはわかりやすくてなるほどとなった。

ans = 0
3.times do
  s, e = gets.split.map(&:to_i)
  ans += s * e / 10
end

puts ans

そうか、標準入力は必ずしも初めに変数に入れなくてもよくて、今回でいうとtimesメソッドの中で繰り返し要素として使えば変数3つ用意する必要もないのか。

●出てきたメソッド等

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

■振り返りなど

  • injectよくわからない…こういうものがあると認識しておいてまた次の機会に備えよう。
  • A問題なのにかなり手こずった。