Skip to content

Instantly share code, notes, and snippets.

@plaster
Last active February 18, 2017 06:52
Show Gist options
  • Save plaster/4357479 to your computer and use it in GitHub Desktop.
Save plaster/4357479 to your computer and use it in GitHub Desktop.
Project Euler Problem 16 solution in Clojure
;;;; 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)))
@plaster
Copy link
Author

plaster commented Jan 3, 2013

@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? みたいな基本的な関数をちゃんと使えるようにしたいですね。覚えます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment