Created
December 7, 2012 13:29
-
-
Save ponkore/4233289 to your computer and use it in GitHub Desktop.
Project Euler Problem 1
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 1 | |
;;; http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%201 | |
;;; | |
;;; 10未満の自然数のうち、3 もしくは 5 の倍数になっているものは 3, 5, 6, 9 の4つがあり、 これらの合計は 23 になる。 | |
;;; 同じようにして、1,000 未満の 3 か 5 の倍数になっている数字の合計を求めよ。 | |
;;; 3 もしくは 5の倍数の場合 true、そうでない場合 false を返す filter 判定用関数 | |
(defn fizz-or-buzz? | |
"3か5で割り切れるならtrue、そうでないならfalseを返す。" | |
[n] | |
(or (zero? (mod n 3)) (zero? (mod n 5)))) | |
(defn problem-1 | |
"Projec Euler Problem#1" | |
([] (problem-1 1000)) | |
([n] (->> (range 1 n) (filter fizz-or-buzz?) (reduce +)))) |
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 1 | |
;;; http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%201 | |
;;; | |
;;; 10未満の自然数のうち、3 もしくは 5 の倍数になっているものは 3, 5, 6, 9 の4つがあり、 これらの合計は 23 になる。 | |
;;; 同じようにして、1,000 未満の 3 か 5 の倍数になっている数字の合計を求めよ。 | |
;;; iterate で繰り返すことができるよう、一つの引数を取り次へとつながるパラメータを戻り値として返す、 | |
;;; シーケンスジェネレータっぽいやつを作る。 | |
(defn fizzbuzz-seq | |
[[result n]] | |
(let [incn (inc n)] | |
[(or (zero? (mod incn 3)) (zero? (mod incn 5))) (inc n)])) | |
;;; テスト | |
;(take 10 (iterate fizzbuzz-seq [false 1])) | |
;=> ([false 1] [false 2] [true 3] [false 4] [true 5] [true 6] [false 7] [false 8] [true 9] [true 10]) | |
;;; それをフィルタする。良い感じ。 | |
;(->> (take 10 (iterate fizzbuzz-seq [false 1])) (filter first)) | |
;=> ([true 3] [true 5] [true 6] [true 9] [true 10]) | |
;;; 答え | |
(defn problem-1-2 | |
([] (problem-1-2 1000)) | |
([n] (->> (iterate fizzbuzz-seq [false 1]) | |
(take n) | |
(filter first) | |
(map second) | |
(reduce +)))) |
bouzuya さんへ
- 正確性を欠いていたのはどうやら自分のほうでした。私のようなおっさん世代は、自然数には0は含まないと教えられているのです。bouzuya さんに指摘いただくまで、微塵も疑いませんでした。気分を害されたのならすみません。
- 自分はこういった場での発言とかでへたを打つことが多いので、気をつけたいと思います。今はメンバーも少ないですが、Clojure コミュニティを広げるため、初心者も入ってきやすくするために、なるべくほんわかした感じで行きましょう。
初めまして。->>
便利そうですね。私こういうの大好きです。
fizz-or-buz?
述語があるとの事前情報があったので、シーケンスをフィルタする解なのだろうと思っていました。
どうやったら「別解」になるかなあなどと思いながら、私も解答つくってみました、、、が、かなりnaiveです。setの練習ですね。
https://gist.github.com/4245866 (ここを見てからだいぶ直したのは秘密です。履歴でばれますが)
あと、bouzuyaさん指摘の 3引数reduce、私もこの挙動が好きです。最初foldという名前で探していたのですが、
reduceのオーバーロード(?)で実現されていたのをみつけてびっくりしました。
ちなみに私は (apply + coll)
派ですが,この場合は apply
で書いても reduce
で書いてもどちらでもいいと思います.その理由は,...と書きはじめたら長くなったので別記事にまとめてみました.ご参考まで. > http://tnoda-clojure.tumblr.com/post/37700304493/apply-and-reduce
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
解答としては bouzuya さんのコードが文句無し模範解答と思います.
bouzuya さんが突っ込んでいるように, この問題に使うには少々おおげさなところが多いですが,
tnoda さんが言うように, もっと大きな問題で使われるようなイディオムが含まれていて,
参考になります.
コメントや doc-string が, きちんと書いてあるのは良いですね.
私も見習わなくては...
apply +
かreduce +
かは, 宗教戦争になりかねないので,...敢えて宗教戦争に参加すると :-), この場合は
apply +
の方が抽象的で良いと思います.