challenge 最大公約数(除算禁止)

あなたが使っている言語で除算と剰余が使えなくなりました。

以下の条件のもと最大公約数を求めるプログラムを書いてください。

条件

  • 除算および剰余の使用禁止
  • 加算や乗算から除算・剰余を単純に定義することも禁止とする
  • ただし, ビットシフトが面倒な場合には引数を2で割った商を返す関数を実装しても構わない
  • 多倍長演算をサポートすること(各言語のライブラリ状況を見たいので)
  • 引数は2つの正整数と仮定して構わない
  • F_1=1, F_2=1のフィボナッチ数列で2000番目と1999番目の最大公約数を求めたときのループ回数を教えてください

Posted feedbacks - Common Lisp

gcd は組み込みで存在しますが、こんな式を基に書いてみました。呼び出し回数 1937 回。

  • gcd(x,x) = x
  • gcd(2x+1, 2y+1) = gcd(2x+1, x-y)
  • gcd(2x+1, 2y) = gcd(2x+1, y)
  • gcd(2x, 2y) = 2*gcd(x, y)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
(defun *gcd (x y &optional (acc 1) (count 0))
  (incf count)
  (cond ((= x y)
         (values count (* acc x)))
        ((and (oddp x) (oddp y)) ; odd, odd
         (*gcd (min x y) (ash (abs (- x y)) -1) acc count))
        ((oddp x) ; odd, even
         (*gcd x (ash y -1) acc count))
        ((oddp y) ; even, odd
         (*gcd (ash x -1) y acc count))
        (t ; even, even
         (*gcd (ash x -1) (ash y -1) (ash acc 1) count))))

(defun fib (x)
  (loop with l = '(1 1) for i from 2 to x
    do (push (+ (car l) (cadr l)) l)
    finally (return (car l))))

(format t "~{Called ~D times, result is ~D~}"
        (multiple-value-list (*gcd (fib 2000) (fib 1999))))

Index

Feed

Other

Link

Pathtraq

loading...