Skip to content

Instantly share code, notes, and snippets.

@tkareine
Created August 30, 2012 19:27
Show Gist options
  • Save tkareine/3538550 to your computer and use it in GitHub Desktop.
Save tkareine/3538550 to your computer and use it in GitHub Desktop.
(ns pi-estimation
"See Opinion 18 in <http://programmers.blogoverflow.com/2012/08/20-controversial-programming-opinions/>")
;; Given that Pi can be estimated using the function 4 * (1 – 1/3 + 1/5
;; – 1/7 + …) with more terms giving greater accuracy, write a function that
;; calculates Pi to an accuracy of 5 decimal places.)
;; with lazy-seq
(defn odds []
(iterate (partial + 2) 1))
(defn invert [ns]
(map #(/ 1 %) ns))
(defn pi-seq-terms []
(let [plus-minuses (cycle [+ -])
inverted-odds (invert (odds))]
(map #(%1 %2) plus-minuses inverted-odds)))
(defn pi-seq [n]
(* 4 (reduce + (map double (take n (pi-seq-terms))))))
;; with loop/recur
(defn sum-pi-loop-terms-upto [n]
(loop [depth n
sum 1
term-denom -3]
(if (> depth 1)
(let [term (/ 1.0 term-denom)
next-term-denom (if (neg? term-denom) (+ (- term-denom) 2) (- (+ term-denom 2)))]
(recur (dec depth) (+ sum term) next-term-denom))
sum)))
(defn pi-loop [n]
(* 4 (sum-pi-loop-terms-upto n)))
;; On MacBook Air 3,1 (late 2010), 1.4 Ghz Intel Core 2 Duo:
;;
;; $ clj
;; Clojure 1.4.0
;; user=> (use 'pi-estimation :reload-all)
;; nil
;; user=> (dotimes [_ 3] (pi-seq 5000) (pi-loop 5000))
;; nil
;; user=> (time (pi-seq 5000))
;; "Elapsed time: 97.103 msecs"
;; 3.1413926535917907
;; user=> (time (pi-loop 5000))
;; "Elapsed time: 0.229 msecs"
;; 3.141392653591791
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment