最大公約数
一昨日の続きです.今日は,2つの数を素因数分解し,共通する因数を得て演算し,最大公約数を得る,というメソッド(というと語弊があるけど)を考えてみました.
配列の共通する要素
まず,どのようにして共通する要素を求めるか?普通は,「そんなの,and演算すりゃ良いじゃないか」と考えます.しかし,それでは少し困った事があります.
とりあえずand演算から考えてみます.
> [2,2,3] & [2,3,3] # 12と18を素因数分解したもの => [2, 3]
これだと,問題無いですね.2,3だけでいいですから.しかし,次の場合,
> [2,2,3] & [2,2,2,3] # 12と24 => [2, 3]
これだと,最大公約数は12なのに,結果を演算した時に12ではなく6になってしまいます.そこで,and演算を自分流に作ります.
class Array def my_and(other) arr = [] nother = other.dup self.each{|e| if nother.include? e nother.each_index{|i| if nother[i] == e arr.push e nother.delete_at(i) # 要素を消す break end } end } arr end end
selfの要素を一つ一つ見ていって,ohterをdupして得られたnotherに同じ要素が含まれているか調べ,含まれていたらその要素をarrにpush,notherから削除し,selfの次の要素を見ます.頑張って脳でイメージしてください.説明が上手く出来ません.
実行すると,こんな感じです.
> [2,2,3].my_and [2,2,2,3] => [2, 2, 3]
望み通りの結果が得られました.
共通する素因数
とりあえず,これでand演算の問題は解決しました.次は,2つの数から共通する素因数を得ます.
これはもう簡単で,
class Integer def comfact(other) a1 = self.factor a2 = other.factor a1.my_and a2 end end >12.comfact 24 => [2, 2, 3]
factorメソッドに関しては,一昨日のを参照してください.一応,下にソースを載っけてありますが.
最大公約数
さて,やっと最大公約数です.考え方としては,comfactによって得られた配列を,ひたすらに掛ければ良いかしら.
class Integer def maxcomfact(other) m = 1 self.comfact(other).each{|e| m *= e } m end end > 12.maxcomfact 24 => 12
お,なんか動いてるっぽい.
色々試してみた感じ,なんとか動きました.とりあえず完成.ただ,2項だけしか演算できない訳だから,今度は配列に対してやってみるか.
以下,とりあえず完成版のソースを載せます.
class Array def my_and(other) arr = [] nother = other.dup self.each{|e| if nother.include? e nother.each_index{|i| if nother[i] == e arr.push e nother.delete_at(i) break end } end } arr end end class Integer def prime? return false if self < 2 (2 ... self).each{|x| # 割り切れたら素数じゃない return false if self % x == 0 } true end def factor primes = [] # 素数なら配列に突っ込んで返す return primes.push(self) if self.prime? # 1以下の数なら素因数分解出来ないので空の配列を返す return primes if self < 2 n = self # 2から順番に,素数で割っていく (2 ... n).each{|p| if p.prime? while n % p == 0 primes.push(p) n = n / p end end break if n == 1 } primes end def comfact(other) a1 = self.factor a2 = other.factor a1.my_and a2 end def maxcomfact(other) m = 1 self.comfact(other).each{|e| m *= e } m end end
楽しいわぁ.