【ruby】数学問題でよく使うメソッドその1

AtCorderの問題を解いていると数学問題がよく出てくる。そこで使うメソッド類をまとめておく。

primeモジュール

素数を扱う時に使うのがprimeモジュール。コードの最上段にこれを書いておく。

require 'prime'

素数

# 小さい方からn個の素数
Prime.take(5)
=> [2, 3, 5, 7, 11]

# n以下の素数を列挙
Prime.each(15).to_a
=> [2, 3, 5, 7, 11, 13]

# n以下の最大の素数
Prime.take_while{|v| v < 100}.last
=> 97

# n以上の最小の素数
Prime.find{|v| v >= 100}
=> 101

# nが素数かチェック
Prime.prime?(11)
=> true

124.prime?
=> false

素因数分解

# nを素因数分解
Prime.prime_division(36)
=> [[2, 2], [3, 2]]  # 2^2, 3^2

# nの約数の個数
# n = a^x * b^y * c^z なら
# 個数は (x + 1)(y + 1)(z + 1)
Prime.prime_division(36).map{|k, v| v + 1 }.inject(:*)
=> 9

injectメソッド

num = [4, 3, 2, 1]
num.inject(:+)
=> 10  # 要素を1つ目から順に足していく
num.inject(5, :+)
=> 15  # injectで渡された値に要素を1つ目から順に足していく

上では足し算のみでやったが、四則演算は全て同じ。

約数の列挙

Qiitaで@scivolaさんの解がコンパクトで良い感じでした。

require "prime"

def divisors(n)
  n.prime_division.inject([1]) do |ary, (p, e)|
    (0..e).map{ |e1| p ** e1 }.product(ary).map{ |a, b| a * b }
  end.sort
end

division(36)
=> [1, 2, 3, 4, 6, 9, 12, 18, 36]

三角関数

# 円周率
MATH::PI
=> 3.141592653589793

# 角度をラジアンに
deg = gets.to_i
puts deg * Math::PI / 180

# 三角関数
Math.sin(rad)
Math.cos(rad)
Math::tan(rad)  # tanだけ違うから注意

# 逆三角関数
Math::asin(rad)  # asinだけ違うから注意
Math.acos(rad)
Math.atan(rad)

まとめ

滅多に使うことはないけど(それこそプロコンくらい…)、いざ出てきた時に困るのでまとめてみた。