■はじめに
Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。 基本的にはAtCoderというプログラミングコンテスト(競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、最も簡単なA問題を解いていく)
■問題
●出典
AtCoder Beginner Contest 003のA問題 https://atcoder.jp/contests/abc003/tasks/abc003_1
●問題文
AtCoder社の社員である青木さんの給料は以下のように決められます。 ある月に、青木さんがタスクをこなした数を x とします。 この月の給料は、1 から x までの整数が 1 面ずつに書かれた x 面ダイスを振って出た目 × 1 万円がもらえます。 ただし、このダイスは、どの面が出る確率も等しく 1/x です。 青木くんは、暮らしていくのに十分な給料が得られるかどうかが心配で、平均いくら程度給料がもらえるか調べたいです。 毎月、青木くんはちょうど N 個のタスクをこなすこととし、毎月の給料の平均値を求めるプログラムを書いてください。 (サイコロ給というやつですね。基本給なしでサイコロだけというのはエグい…)
●入力
入力は以下の形式で標準入力から与えられる。
N
1 行目には、整数で、青木くんが毎月こなすタスクの数 N (4≦N≦100) が与えられる。
●出力
青木くんがもらえる毎月の給料(単位は円)の平均値を 1 行で出力せよ。 絶対誤差、または、相対誤差が 10^−6以下であれば許容される。 また、出力の末尾には改行を入れること。
■回答
●愚直に書く
愚直に書く…と言っても今回は昨日よりちょっとややこしくて、ノールックでパッとは書けなかった。 rangeを配列にしてsumするということにたどり着いて、できた。
n = gets.to_i
range = (1..n).to_a
p range.sum * 10000 / n
●リファクタリング
あまり思いつかないな…元々はeach
して+=
で足し上げていこうと思っていたから、それが愚直な回答で、上述したものがある程度整理したものということにはなる。
少しでもコード長を短くするとしたらrange
の変数を使わずにそのままsumするくらいしか思いつかない。
n = gets.to_i
p (1..n).to_a.sum * 10000 / n
●他の方の回答例
上位の方で下記のような書き方が非常に沢山あった。
puts (gets.to_i + 1) * 5000
なんで1を足して5000をかけると正しくなるのだっけ…。 あっっ、連続する数値の平均値の出し方が
(最小の値 + 最大の値) / 2
だから、
(1 + N) / 2 * 10000
=> (1 + N) * 5000
でいいのか、そうか〜。 出力例に書いてあった式に囚われて思いつかなかった…。
■振り返りなど
今日も気づきがありました。 A問題しかやってなくて語るのもアレですが、AtCoderはパズル的な面白さとRubyの勉強が両方できるので、楽しい。