Project Euler #003 – 最大の素因数

In: Project Euler

26 11月 2009

Project EulerをClojureでおさらいシリーズ。

週1門以上のペースじゃないと出題に追いつけないこの企画。
今回は Problem 3。

オリジナルはこちら

日本語訳:

13195 の素因数は 5, 7, 13, 29 である。

600851475143 の素因数で最大のものを求めよ。

素因数は対象の平方根を超えることはないので 2〜sqrt(N) のあいだの素数を調査すればよいことになる。

その昔、Rubyで解いたときのがこれ。

#!/usr/bin/env ruby
def lpf(num)  num_sqrt = Math::sqrt(num)
  (2..num_sqrt).each do |x|
    while num % x == 0
      num = num / x
    end
    return x if num == 1
  end
end
 
p lpf(600851475143)

もう笑っちゃうほど手続き型です。

素数列は使わずに整数列そのままでループしています。

2 → sqrt(num)の整数xで順に:
・numが割り切れればxで割れるだけ割る→商を次のnumに。
・numが1になったらそのときのxが答え。
・先頭に戻る(次のx)。

こんどはClojureで書くために再帰を使った定義を考えてみる。

ループの初期値(n = 元の数, d = 2)として:
・n = d なら d が答え。
・割り切れたら割り切れなくなるまで割って(商, d+1)で再帰。
・Numがdで割り切れなければ (n, d+1)で再帰。

あー、なんか思考が毒されてるぞ。
あやうく div_max とかいうムダな関数を定義することろだったわ。

書き直すと

ループの初期値(n = 元の数, d = 2)として:
・n = d なら d が答え。
・割り切れたら(n/d, d)で再帰。
・Numがdで割り切れなければ (n, d+1)で再帰。

コードにしてみるとこんな感じに:

(defn largest-prime-factor
  "Returns a largest prime factor."
  [number]
  (loop [n number d 2]
    (cond (= n d) n
          (= 0 (rem n d)) (recur (/ n d) d)
          :else (recur n (inc d)))))
 
(largest-prime-factor 600851475143)

2行目の文章は関数のドキュメントです。 この部分は習慣としてきちんと書くように心がけてみる。

意外と手続き型の考え方ってのは染みついているものだと実感。
再帰は不自由なようで自由度が高いような、不思議な感じです。

blog comments powered by Disqus
Get Adobe Flash playerPlugin by wpburn.com wordpress themes

About this blog

私 manjilab のポータル的サイトになっております。日々気付いたこと、考えたこと、発表したいものを載せていきます。

Photostream

    Lisp indent 考察Lisp indent 考察Lisp indent 考察Lisp indent 考察Lisp indent 考察Tips to use Clojure(Lisp) with TextMateTips to use Clojure(Lisp) with TextMateTips to use Clojure(Lisp) with TextMate