11/11 関数から「計算」へ(2), アルゴリズムと計算量(1)


質問と回答

Q.
>ΣnCk (k=0,1,,,n) = 2^n
>Σ(nCk)^2 (同上) = 2nCn
>であるが
>Σ(nCk)^3 (同上) = ???
>3乗の計算に関して何か知っている人がいれば教えてください。
A.
たぶん母関数を使って求まるのでしょうが,私も答えを知らないので,答えを知っているひとは答えてあげてください.
Q.
集合論における自然数の構成を負うために以下のコードを書きました:
def zerol()
 return Set.new()
end

def succ(s)
 return s | Set.new([s])
end

def number(n)
 s = zerol()
 for i in 1..n
   s = succ(s)
 end
 return s
end
succ の性質から明らかに s ⊂ succ(s) とならなければならないはずですが、superset?, subset? を使うとこれが正しく判定されないようです。
A.
面白いことに気がつきましたね.RubyのSetにおいて, ドキュメント を見ると, 「2つのオブジェクトの等価性は Object#eql? と Object#hash によります。 なぜなら、Set は Hash を記憶として使っているからです。」 と書かれています.一般のオブジェクト同士の同値性の完全な判定は非常にコストがかかるので,オブジェクトのアドレスをベースにした ハッシュ値を用いて同値性を判定するのが普通です.そのため,
irb(main):043:0> Set.new().hash()
=> 681390
irb(main):044:0> Set.new().hash()
=> 670910
irb(main):045:0> Set.new().eql?(Set.new())
=> false
のように,同値性を判断できなくなっているのです.

配列などの場合は,要素のハッシュ値を元に配列全体のハッシュ値を計算するようになっているので,

[1,2,3]==[1,2,3]
なども判定できるのですが,次の例のように自分自身を要素を含むような配列を作ると,途端にハッシュ値を計算できなくなります.
irb(main):046:0> a=[1,2,3]
=> [1, 2, 3]
irb(main):047:0> a[1]=a
=> [1, [...], 3]
irb(main):048:0> a.hash()
SystemStackError: stack level too deep
	from (irb):48:in `hash'
	from (irb):48
	from :0
Setクラスのhash関数を定義し直せば,問題の例は扱えるようにはなると思いますが,「自分自身を要素に含む集合」を定義すると 同様の問題が生じる可能性はあります.

前回の課題について


投票システム

vote.rbをダウンロードして,ホームディレクトリに保存する.ドックからターミナルを起動して,
ruby vote.rb 選択肢番号
のように使う.

練習,投票

関連リンク



今日の課題