Created
December 15, 2012 07:21
-
-
Save plaster/4291907 to your computer and use it in GitHub Desktop.
Project Euler Problem 9 solution in Clojure (#mitori_clj)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(use 'clojure.test) | |
;; ピタゴラス数チェック | |
(defn pythagorean? | |
[a b c] | |
(= (* c c) (+ (* a a) (* b b)))) | |
(is (pythagorean? 3 4 5)) | |
;; 合計が a+b+c かつ 0 < a < b < c になるような組の列挙 | |
;; もう少し効率的に枝刈りできるかもしれない | |
(defn candidates | |
[a+b+c] | |
(for [c (range (+ a+b+c 1)) | |
:let [a+b (- a+b+c c)] | |
b (range (+ a+b 1)) | |
:let [a (- a+b b)] | |
:when (< 0 a b c) | |
] | |
[ a b c ] | |
)) | |
(is (every? #(= 1000 (apply + %)) (candidates 1000))) | |
;; "(a,b,c)の組および解答フォーム入力用の積" | |
(defn solve [n] | |
(for [abc (candidates n) | |
:when (apply pythagorean? abc) ] | |
[ abc (apply * abc) ])) | |
;; (solve 1000) => ([[200 375 425] 31875000]) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; ピタゴラス数チェック | |
(defn pythagorean? | |
[a b c] | |
(= (* c c) (+ (* a a) (* b b)))) | |
(is (pythagorean? 3 4 5)) | |
;; 合計が a+b+c かつ 0 < a < b < c になるような組の列挙 | |
;; もう少し効率的に枝刈りできるかもしれない | |
(defn candidates | |
[a+b+c] | |
(for [c (range (+ a+b+c 1)) | |
:let [a+b (- a+b+c c)] | |
b (range (+ a+b 1)) | |
:let [a (- a+b b)] | |
:when (and (< 0 a b c) (pythagorean? a b c)) | |
] | |
[ a b c ] | |
)) | |
(is (every? #(= 1000 (apply + %)) (candidates 1000))) | |
;; pe-9.core=> (time (apply list (candidates 10000))) | |
;; "Elapsed time: 6183.66497 msecs" | |
;; @kohyamaさんアドバイス版 | |
(defn candidates2 | |
[a+b+c] | |
(for [a (range 1 (quot (inc a+b+c) 3)) | |
:let [b+c (- a+b+c a)] | |
b (range (inc a) (quot (inc b+c) 2)) | |
:let [c (- b+c b)] | |
:when (and (< 0 a b c) (pythagorean? a b c)) | |
] | |
[ a b c ] | |
)) | |
;; pe-9.core=> (time (apply list (candidates2 10000))) | |
;; "Elapsed time: 1469.798884 msecs" | |
;; ([2000 3750 4250]) | |
;; "(a,b,c)の組および解答フォーム入力用の積" | |
(defn solve [n] | |
(for [abc (candidates n) ] | |
[ abc (apply * abc) ])) | |
;; (solve 1000) => ([[200 375 425] 31875000]) |
オーバーロードの解決ができないときにreflectionが使われるみたいですね。Mathは特に速いことが望まれる場面多そうですし、一方で long と double のオーバーロードだらけなので、注意が要りそうです。
もう一つ付け加えると,メソッド呼び出しのレシーバのクラスを型推論できないときも reflection を使うみたいです.たとえば,
user> (defn str* [x] (.toString x))
Reflection warning, NO_SOURCE_FILE:1 - reference to field toString can't be resolved.
#'user/str*
で,これも,
user> (defn date->str [^java.util.Date x] (.toString x))
#'user/date->str
のように型ヒントをつけてあげると怒られなくなりますね.
もう一つ付け加えると,メソッド呼び出しのレシーバのクラスを型推論できないときも reflection を使うみたいです.
16を解いているときにちょうど疑問に思っていた内容で、大変参考になりました。ありがとうございます。
詳しくはあちらに書きます(が、URL未アナウンスです……)。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
確かに、実行時ではなかったです。ありがとうございます。
では警告が1度だけ出るのに、中身を使う
では一度も出ませんでした。
オーバーロードの解決ができないときにreflectionが使われるみたいですね。
Math
は特に速いことが望まれる場面多そうですし、一方で long と double のオーバーロードだらけなので、注意が要りそうです。私が「コンパイル時に警告」でないと思ったのは lein compile で警告が出なかったためだったのですが、
rm -r target; lein compile したところ、期待どおり
の警告メッセージを得ることができました。
しかも、最初に私が悩んだ
は出ていないので、こちらは私が書いた部分のコードには直接関係ない警告メッセージだったというのも確定ですね。
いろいろすっきりしました、本当にありがとうございます。