Last active
February 18, 2017 06:52
-
-
Save plaster/4357479 to your computer and use it in GitHub Desktop.
Project Euler Problem 16 solution in Clojure
This file contains 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
;;;; Project Euler Problem 16 solution | |
;;;; http://projecteuler.net/problem=16 | |
(use 'clojure.test) | |
(import 'java.math.BigInteger) | |
;; Character/digit usage from: https://gist.github.com/4276901 | |
(def solve | |
(comp (partial apply +) | |
(partial map #(Character/digit ^char % 10)) | |
str | |
#(. (BigInteger. "2") pow %) | |
;; no reflection warnings at this method call. really? | |
;; cf. #(. % pow %2) => reflection warning "call to pow can't be resolved." | |
)) | |
(is (= 26 (solve 15))) | |
(is (= 1366 (solve 1000))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@ypsilon-takai さんの指摘どおり、この問題なら数値のまま解くのが自然ですね。文字列化するにも内部的にはmodとquotしてるでしょうから、実行効率もよさそうな気がします。
@tnoda さんの
lazy-seq
わかりやすくて素敵です。別のところで話題になっていた気がしますが、再帰のどこに lazy-seq を入れるか悩みどころです。
ほとんど好みの問題のような気もするのですが、
(cons (rem x 10) (lazy-seq (digits* (quot x 10))))
のように書きたくなります。lazy-seq
にすると、先頭の要素すら、とり出されるまで計算されない** 一方で、先頭の要素を取り出すだけで再帰呼び出しが1段進んで、
(pos? x)
は評価されるVS
lazy-seq
にすると、先頭の要素を取り出しただけでは他の計算は何も起きない** ただし、先頭の要素の
(rem x 10)
は即座に評価される徹底するならいっそ、
if
の外にまでlazy-seq
を出してもいいのかも? しれません。真面目にトレードオフを考える必要がある場面があるとしたらどういうときなのか、もうちょっと考えてみます。
あと、
pos?
みたいな基本的な関数をちゃんと使えるようにしたいですね。覚えます。