【Project EulerにRubyで挑戦シリーズ】問1:Multiples of 3 and 5

シリーズと言っても昨日思い立って一問目に挑戦してみただけなので第一回ですw
Project Eulerというサイトを活用してRubyのアウトプットを継続していきたいと思います。

スポンサーリンク

Project Eulerとは

Project Euler(プロジェク オイラー)と読みます。
オイラー関数のオイラーさんですね。懐かしい…

その名の通り、数学的なプログラムが掲載されている問題集サイトです。
2018年9月29日時点で627問が掲載されています。
会員登録して回答を提出していくとレベルが上っていくそうです。

問題を解くために利用するプログラミング言語は何を使っても良いので
Ruby ver 2.5.1を使っていきます。

今回の問題

Multiples of 3 and 5

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.

10未満の自然数のうち, 3もしくは5の倍数になるものは3,5,6,9の4つがあり, これらの合計は23になる.
同じようにして, 1000未満の3もしくは5の倍数になる数字の合計を求めよ。

書いた内容

とりあえず解いてみる

とりあえず、範囲オブジェクトで1~999までをeachで回し、
ブロック内部で条件に合致するものだけをローカル変数sumに足していけば良い
と考えてこうしてみました。

sum = 0
(1...1000).each do |n|
  if n % 3 == 0 || n % 5 == 0
    sum += n
  end
end
puts sum #=> 233168

injectメソッドを用いてリファクタリング

正しく動作できたためリファクタリングしました。
そもそもeachメソッドではなく、
injectメソッドで畳み込み演算をしていけば簡単に書けるのではと考え直し下記に。

*と範囲オブジェクトを[ ]に入れてsplat展開して配列を生成しています。
その配列をレシーバにselectメソッドを用いて、3もしくは5の倍数だけを抽出し、
ローカル変数 element に代入しました。

element = [*1...1000].select { |n| n % 3 == 0 || n % 5 == 0 }
puts element.inject { |result, n| result + n }
#=> 233168

シンボルを用いてリファクタリング

最後に、このinjectはただの足し算だからもっと簡単にかけないかと調べたら、
injectメソッドはinject(symbol)の形をとることで
ブロックの代わりにシンボル化されたメソッドを実行できるそうな。

puts [1, 2, 3].inject(:+)
#=> 1.+(2).+(3) すなわち 6 ですね

ということで最終形はワンライナーの下記に落ち着きました。シンプル〜!

puts [*1...1000].select { |n| n % 3 == 0 || n % 5 == 0 }.inject(:+)
#=> 233168

GitHubにリポジトリも作ったので反映しながら
こんな感じでのんびりProject Eulerを解き進めていこうと思います。

※Project Eulerのリポジトリ

この記事の内容が役に立ったと思いました、SNSで記事を共有していただけますと幸いです。