02

Task

Exercise 4

次のような、繰り返しを使ったプログラムを作成せよ。

$$ nCr = {n × (n - 1) × … × (n - r + 1) \over r × (r - 1) × … × 1} $$

Program, execution and description

前回はHTMLになって読めなかったので、お手数ですが #1 をご確認頂けますと幸いです。

前回作成した Sym classの +@ -@ !@ 関数を再定義することで、 階乗 (!Sym.new(4) => 24) などの機能追加を実施しました。

Sym は代数計算をするために各演算を再定義している class です。 今回作成した Sym class のコードについては最後に記載しました。

まず +@ -@ については、 +self.to_f, -self.to_f のみを返す関数を登録します。 つぎに!@ については、 self.to_i の階乗を計算して返す関数を登録します。

また前回同様に、 <=> 演算子から、値を代入するようになっています。 以上から、 a ~ c のコード は以下のようになります。

p2, n, r = (0..5).map do Sym.new end p2 <=> +2 a = p2 ** n b = !n c = !n / !(n - r) / !r puts " i \t| 2^n \t\t| n! \t\t| nC1 \t\t| nC2 \t\t| nC3 \t\t | nC4" puts " :-\t| :- \t\t| :- \t\t| :-- \t\t| :-- \t\t| :-- \t\t | :-" (0..9).map do |i| n <=> i puts " #{i} \t|" + " 2^#{i} = #{a} \t|" + " #{i}! = #{b} \t|" + " #{i}C#{r <=> 1} = #{c} \t|" + " #{i}C#{r <=> 2} = #{c} \t|" + " #{i}C#{r <=> 3} = #{c} \t|" + " #{i}C#{r <=> 4} = #{c}" end

About Task

実行結果は以下のようになります。

i 2^n n! nC1 nC2 nC3 nC4
0 2^0 = 1 0! = 1 0C1 = 1 0C2 = 0 0C3 = 0 0C4 = 0
1 2^1 = 2 1! = 1 1C1 = 1 1C2 = 0 1C3 = 0 1C4 = 0
2 2^2 = 4 2! = 2 2C1 = 2 2C2 = 1 2C3 = 0 2C4 = 0
3 2^3 = 8 3! = 6 3C1 = 3 3C2 = 3 3C3 = 1 3C4 = 0
4 2^4 = 16 4! = 24 4C1 = 4 4C2 = 6 4C3 = 4 4C4 = 1
5 2^5 = 32 5! = 120 5C1 = 5 5C2 = 10 5C3 = 10 5C4 = 5
6 2^6 = 64 6! = 720 6C1 = 6 6C2 = 15 6C3 = 20 6C4 = 15
7 2^7 = 128 7! = 5040 7C1 = 7 7C2 = 21 7C3 = 35 7C4 = 35
8 2^8 = 256 8! = 40320 8C1 = 8 8C2 = 28 8C3 = 56 8C4 = 70
9 2^9 = 512 9! = 362880 9C1 = 9 9C2 = 36 9C3 = 84 9C4 = 126

Consideration

About code

まず、前回とおなじく演算の左側のオペランドは Sym objectでないといけないので、 p2 <=> +2 という Sym object を定義することが必要でした。 つぎに、 階乗を計算する !@ 関数を(1..self.to_i).inject(:*) と再定義したのですが、 * は関数として定義しているため、 :* というように書くことができました。 また、数学では 0! = 1 と定義されているので、 self.to_i が0のときは 1をかえすよう、 || 1 を最後に追加する必要がありました。

About Exercise d

時間内に debug できなかったのですが、sum 関数を途中まで作成しました。 sum 内で値を動かす変数と、from=0 => to=∞ のような範囲を指定することで、各合計値を返します。 これらから、 _sin.sum(k, 0, n) のように sigma のような機能を追加する予定です。

_sin = m1 ** k / !(p2 * k + 1) * x ** (p2 * k + 1) _cos = m1 ** k / !(p2 * k) * x ** (p2 * k) sin = _sin.sum(k, 0, n) cos = _cos.sum(k, 0, n)

sum 関数は以下のようになりました。

def sum(_, from, to) @_[->{ (from.to_i..to.to_i).inject(0) do |acc, i| _ <=> i acc + self.to_f end }] end

Sym

class Sym def initialize(init = 0.0) @v = init @_ = ->fun{Sym.new(fun)} end def to_f() (@v.is_a? Numeric) ? @v: @v[] end def to_i() self.to_f.to_i end def to_s() self.to_f.to_s end def +(_) @_[->{self.to_f + _.to_f}] end def -(_) @_[->{self.to_f - _.to_f}] end def *(_) @_[->{self.to_f * _.to_f}] end def /(_) @_[->{self.to_f / _.to_f}] end def %(_) @_[->{self.to_f % _.to_f}] end def **(_) @_[->{self.to_f ** _.to_f}] end def ==(_) self.to_f == _.to_f end def <=>(_) @v = _ end def +@() @_[->{+self.to_f}] end def -@() @_[->{-self.to_f}] end def !@() @_[->{(1..self.to_i).inject(:*) || 1}] end end