Comment detail
最大公約数(除算禁止) (Nested Flatten)ちょっと補足。 > ループ回数は互除法でやった場合と同じになります。 というのはあくまで引数が隣り合うフィボナッチ数である場合の話です。
出題者です.
>隣り合うフィボナッチ数の場合は実は減算法でもあまり効率が悪くなりません。常に差がひとつ前のフィボナッチ数になるわけですから。
全くもってその通りです. 1024bitと512bitの素数とかでやった方が良かったようでorz
この回答が破綻するのは一方が他方よりはるかに大きな場合ですね。m >> n で m = q*n + rのとき n >> r になるような組み合わせを続けてゆくと減算のみによる方法では悲惨なことに。
減算を繰り返して割り算の代わりにする方法だと差が大きいときに問題になる、ということで 「文字列の長さをみて小さい側を10**n倍する」 という荒技を使ってみました。
# Screencast-o-maticで撮りながら作ったのにアップロード中にブラウザが落ちて消滅…orz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def gcd(x, y):
if x == y: return x
if x < y: y, x = x, y
lx = len(str(x))
ly = len(str(y))
diff = lx - ly
z = abs(y * 10 ** diff - x)
z2 = abs(y * 10 ** (diff + 1) - x)
z = min(z, z2)
if diff > 0:
z2 = abs(y * 10 ** (diff - 1) - x)
z = min(z, z2)
# zはxとyと公約数を共有する
if z < y:
return gcd(y, z)
return gcd(z, y)
|
なんでscreencastを取ろうと思ったのかに関しての参考文献
>例えばどう書く?orgの問題を解くまでのコーディングとかが公開されたら面白そう。
http://d.hatena.ne.jp/higepon/20071108/1194495170
>ブラウザだけでスクリーンキャストが手軽に作成できる『Screencast-O-Matic』 | 100SHIKI.COM
http://www.100shiki.com/archives/2007/08/screencastomatic.html
試しに動かしてみたら gcd(10, 1) でスタックオーバーフローしてしまいました。再帰呼び出し時に z==0 だと無限ループするみたいです。





shiro
#4783()
[
Scheme
]
Rating3/3=1.00
Z80マシン語で遊んでいたころ、除算を使わないでもこれでgcdが計算できることに気づいて大発見をしたような気分になりました。後でよく考えたらユークリッドの互除法を非効率にやっているだけでした。
隣り合うフィボナッチ数の場合は実は減算法でもあまり効率が悪くなりません。常に差がひとつ前のフィボナッチ数になるわけですから。
gosh> (time (gcd-nodiv (fib 2000) (fib 1999)))
;(time (gcd-nodiv (fib 2000) (fib 1999)))
; real 0.002
; user 0.000
; sys 0.000
1
ループ回数は互除法でやった場合と同じになります。
gosh> (gcd-nodiv/cnt (fib 2000) (fib 1999) 1)
1
1998
実はこの引数の場合は、組み込みのgcd (互除法使用) の方が遅かったりします。bignumの除算が重いんじゃないかな。
gosh> (time (gcd (fib 2000) (fib 1999)))
;(time (gcd (fib 2000) (fib 1999)))
; real 0.014
; user 0.010
; sys 0.000
1
Rating3/3=1.00-0+
2 replies [ reply ]