第45回 Ruby/Rails勉強会@関西に行ってきた

第45回 Ruby/Rails勉強会@関西

演習問題をやってみた

正の整数 n の階乗 n! を求める方法を何通りでも考えてください

class Integer
  def !
    case self
    when 0, 1
      1
    else
      self * (self-1).!
    end
  end
end
# とか
class Integer
  def !
    (1..self).inject(1, &:*)
  end
end

0.!         # => 1
1.!         # => 1
2.!         # => 2
3.!         # => 6
4.!         # => 24

inject の初期値を 1 にするのは、いつものように id:no6v に教えてもらった。

文字列 "零 一 二 三 四 五 六 七 八 九 十 十一 十二 十三 十四 十五" があります。これから次のような日本語の漢数字の読みを表すハッシュテーブルを作ってください。

"零 一 二 三 四 五 六 七 八 九 十 十一 十二 十三 十四 十五".split(/\s+/).
  each_with_index.inject(Hash.new){|h, a|h[a[1]]=a[0];h}
# >> {0=>"零",  1=>"一",  2=>"二",  3=>"三",  4=>"四",  5=>"五",
# >>  6=>"六",  7=>"七",  8=>"八",  9=>"九",  10=>"十",  11=>"十一",
# >>  12=>"十二",  13=>"十三",  14=>"十四",  15=>"十五"}

シンボルの配列 syms があります。これを先頭だけ大文字化され、昇順にソートされた文字列の配列に変えてください。

syms = [:tokyo, :kyoto, :osaka, :kobe, :matze, :sendai]

syms.map{|i|i.to_s.capitalize}.sort
# => ["Kobe", "Kyoto", "Matze", "Osaka", "Sendai", "Tokyo"]

正の整数 n の二重階乗 n!! を求めるメソッドを書いてください。

class Integer
  def factorial2
    step(1, -2).inject(1, &:*)
  end
end

(0..9).map(&:factorial2)
# => [1, 1, 2, 3, 8, 15, 48, 105, 384, 945]

残念ながら !! という名前のメソッドは作れない。

n までの整数からすべての合成数を除いて素数だけを残すやりかたとして「エラトステネスのふるい」というアルゴリズムが有名です。このアルゴリズムイテレータを使ってうまく実装してください。

require 'prime'
class Integer
  def eratosthenes
    Prime::EratosthenesGenerator.new.inject([]) do |prime, i|
      return prime  if i > self
      prime << i
    end
  end
end

20.eratosthenes     # => [2, 3, 5, 7, 11, 13, 17, 19]

冗談です。

class Integer
  def eratosthenes
    (2..Math.sqrt(self).to_i).
      inject((2..self).to_a) do |sieve, prime|
      sieve.reject{|i|i > prime && i % prime == 0}
    end
  end
end

20.eratosthenes     # => [2, 3, 5, 7, 11, 13, 17, 19]

次のメソッドは二項分布を生成します。これを改良してください。ちなみに二項分布は次のように試行回数 n と確率 p をパラメータとする確率分布です。ここでは二項係数 nCx を計算するのにパスカルの三角形を構成して使っています。

[あとで書く] かも