Mercurial > lasercutter
diff src/clojureDemo/project_euler.clj @ 1:6d9bdaf919f7
added clojureDemo source
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 20 Aug 2010 00:32:44 -0400 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojureDemo/project_euler.clj Fri Aug 20 00:32:44 2010 -0400 1.3 @@ -0,0 +1,559 @@ 1.4 + 1.5 +(ns clojureDemo.project-euler 1.6 + 1.7 +(:refer-clojure :exclude [+ - / * 1.8 + assoc conj dissoc empty get into seq 1.9 + = < > <= >= zero? 1.10 + ]) 1.11 + 1.12 +(:use [clojure.contrib.generic 1.13 + arithmetic 1.14 + collection 1.15 + comparison 1.16 + ]) 1.17 + 1.18 +(:use [clojure.contrib 1.19 + combinatorics 1.20 + repl-utils 1.21 + def 1.22 + duck-streams 1.23 + shell-out 1.24 + import-static 1.25 + lazy-seqs 1.26 + logging 1.27 + map-utils 1.28 + math 1.29 + mock 1.30 + monads 1.31 + ns-utils 1.32 + seq-utils 1.33 + function-utils 1.34 + profile 1.35 + str-utils 1.36 + ]) 1.37 + 1.38 +(:use [clojure.contrib.pprint :exclude [write]]) 1.39 + 1.40 +(:use [clojure.contrib.pprint.examples 1.41 + hexdump 1.42 + json 1.43 + multiply 1.44 + props 1.45 + show-doc 1.46 + xml 1.47 + ]) 1.48 + 1.49 +(:import java.io.File) 1.50 +(:import [java.util Calendar Date]) 1.51 + 1.52 +) 1.53 + 1.54 + 1.55 + 1.56 + 1.57 + 1.58 +(defn range-sum 1.59 + "calculates the sum of a range. Takes the exact same arguments 1.60 + as clojure.core/range equilivent to (reduce + (range start end step)), but O(1)." 1.61 + ([end] 1.62 + (/ (* end (- end 1) ) 2)) 1.63 + 1.64 + ([start end] 1.65 + (- (range-sum end) (range-sum start))) 1.66 + 1.67 + ([start end step] 1.68 + (letfn [(zero-sum [end step] (* step (range-sum 0 (ceil (/ end step)))))] 1.69 + (+ (zero-sum (- end start) step) (* start (int (/ (- end start) step))))))) 1.70 + 1.71 + 1.72 + 1.73 +(defn range-sum-squares 1.74 + "equivalent to (reduce + (map #(expt % 2) (range start end step))), 1.75 + but runs in O(1) time." 1.76 + ([end] 1.77 + (let [n (- end 1)] 1.78 + (- (* (expt n 3) 1/3) ;continous volume 1.79 + (+ (* -1/6 n) (* -1/2 (expt n 2)))))) ;discrete correction 1.80 + 1.81 + ([start end] 1.82 + (- (range-sum-squares end) (range-sum-squares start))) 1.83 + 1.84 + ([start end step] 1.85 + ;; (letfn [(zero-sum-squares [end step] 1.86 + ;; (* step step (range-sum-squares 0 (ceil (/ end step)))))] 1.87 + ;; (+ 1.88 + ;; (* 2 step (range-sum (ceil (/ (- end start) step)))) 1.89 + ;; (zero-sum end step) 1.90 + ;; (* start start (int (/ (- end start) step))))))) 1.91 +)) 1.92 + 1.93 + 1.94 +(defn prime-factors 1.95 + "all the prime factors of the number n" 1.96 + [n] 1.97 + (filter #(= 0 (rem n %)) (for [p primes :while (<= p n)] p))) 1.98 + 1.99 +(defn factor? [a b] (= 0 (rem a b))) 1.100 + 1.101 +(defn factor-map [a b] 1.102 + (if (factor? a b) 1.103 + {b (quot a b)} 1.104 + nil)) 1.105 + 1.106 + 1.107 +(defn divides? [numerator divisor] (= (rem numerator divisor) 0)) 1.108 + 1.109 + 1.110 +(def != (comp not =)) 1.111 + 1.112 + 1.113 +(defn decompose [number factor] 1.114 + (loop [n number counter 0] 1.115 + (if (!= (rem n factor) 0) 1.116 + counter 1.117 + (recur (/ n factor) (inc counter))))) 1.118 + 1.119 + 1.120 + 1.121 + 1.122 + 1.123 + 1.124 + 1.125 +(defn single-factor [{num :current-num index :prime-index factors :prime-factors :as old-state}] 1.126 + (let [divisor (nth primes index) 1.127 + new-index (inc index) 1.128 + done? (= num 1)] 1.129 + (if (divides? num divisor) 1.130 + (let [new-num (/ num (expt divisor (decompose num divisor))) 1.131 + factors (assoc factors divisor (decompose num divisor))] 1.132 + [[factors done?] (assoc old-state 1.133 + :current-num new-num :prime-index new-index :prime-factors factors)]) 1.134 + 1.135 + [[factors done?] (assoc old-state 1.136 + :current-num num :prime-index new-index :prime-factors factors)]))) 1.137 + 1.138 + 1.139 +(defn wtf "a is not used" [a] (domonad state-m [part single-factor] part)) 1.140 + 1.141 +(defn fuck-it [] 1.142 + (domonad state-m 1.143 + [[factors done?] 1.144 + (state-m-until second wtf nil)] 1.145 + 1.146 + factors)) 1.147 + 1.148 +(defn prime-factor-map [num] 1.149 + 1.150 + (first ((fuck-it) {:prime-factors {} 1.151 + :prime-index 0 1.152 + :current-num num}))) 1.153 + 1.154 +(defn prime-factors-monad [num] 1.155 + (sort (keys (prime-factor-map num)))) 1.156 + 1.157 + 1.158 + 1.159 + 1.160 + 1.161 + 1.162 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1.163 +;; fun with state monad 1.164 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1.165 + 1.166 + 1.167 +(defn ++ [{num :num :as world}] 1.168 + (let [num++ (inc num)] 1.169 + [num++ (assoc world :num num++)])) 1.170 + 1.171 +(defn huh? [] 1.172 + (with-monad state-m 1.173 + (domonad [x ++ 1.174 + y ++] 1.175 + y))) 1.176 + 1.177 + 1.178 +(comment 1.179 + 1.180 +huh? 1.181 +-> 1.182 +((let [m-bind (fn m-bind-state [mv f] 1.183 + (fn [s] 1.184 + (let [[v ss] (mv s)] 1.185 + ((f v) ss))))] 1.186 + (m-bind 1.187 + ++ (fn [x] ++))) {:num 1}) 1.188 + 1.189 + 1.190 +) 1.191 + 1.192 + 1.193 +(defn wordify [n] (cl-format nil "~R" n)) 1.194 + 1.195 +(defn british-letter-count-prof [n] 1.196 + (prof :total 1.197 + (let [and? (prof :rem-test (if (and (> n 99) (!= 0 (rem n 100))) 3 0)) 1.198 + word (prof :wordify (wordify n)) 1.199 + word-seq (prof :sequence (seq word)) 1.200 + word-filter (prof :filter (filter #(Character/isLetter %) word-seq)) 1.201 + word-count (prof :count (count word-filter)) 1.202 + answer (prof :add (+ and? word-count))] 1.203 + answer))) 1.204 + 1.205 +(defn british-letter-count-prof2 1.206 +"now this is faster, because it uses string manipulation. go profiling!" 1.207 +[n] 1.208 + (prof :total 1.209 + (let [and? (prof :rem-test (if (and (> n 99) (!= 0 (rem n 100))) 3 0)) 1.210 + word (prof :wordify (wordify n)) 1.211 + word-regex (prof :regex (re-gsub #"[\W-,]" "" word)) 1.212 + 1.213 + word-count (prof :count (.length word-regex)) 1.214 + answer (prof :add (+ and? word-count))] 1.215 + answer))) 1.216 + 1.217 + 1.218 + 1.219 + 1.220 + 1.221 + 1.222 + 1.223 + 1.224 + 1.225 + 1.226 + 1.227 + 1.228 + 1.229 + 1.230 + 1.231 + 1.232 + 1.233 + 1.234 + 1.235 +;pseudo code for primes 1.236 + 1.237 +;fn prime-decomposition 1.238 +; [n] 1.239 +; map = {} 1.240 +; 1.241 +; for x in primes 1.242 +; add to map (divide teh fick out n x) 1.243 +; n = n / prime-factors 1.244 +; if n == 1 BREAK; 1.245 +; 1.246 +; 1.247 + 1.248 + 1.249 + 1.250 +(defn rng [seed] 1.251 + (let [m 259200 1.252 + value (/ (float seed) (float m)) 1.253 + next (rem (+ 54773 (* 7141 seed)) m)] 1.254 + [value next])) 1.255 + 1.256 + 1.257 +(defn yeah! [] 1.258 + (let [name sequence-m 1.259 + m-bind (:m-bind name) 1.260 + m-result (:m-result name) 1.261 + m-zero (:m-zero name) 1.262 + m-plus (:m-plus name)] 1.263 + 1.264 + 1.265 + (m-bind (range 5) (fn [a] (m-bind [2 3] (fn [b] (m-result (+ a b)))))))) 1.266 + 1.267 + 1.268 +(defn ohhhh!! [] 1.269 + 1.270 + (let 1.271 + [name state-m 1.272 + m-bind (:m-bind name) 1.273 + m-result (:m-result name) ] 1.274 + 1.275 + (m-bind rng (fn [x1] (m-bind rng (fn [x2] (m-result (+ x1 x2)))))))) 1.276 + 1.277 + 1.278 + 1.279 +(defmulti palindrome? class) 1.280 + 1.281 +(defmethod palindrome? (class "string") [a] 1.282 + (= (seq a) (reverse a))) 1.283 + 1.284 +(defmethod palindrome? (class 500) [a] 1.285 + (palindrome? (str a))) 1.286 + 1.287 + 1.288 + 1.289 + 1.290 + 1.291 + 1.292 + 1.293 + 1.294 +(defn circulars 1.295 + "returns a vector of all the circular permutations of a number" 1.296 + [n] 1.297 + (map #(Integer. (apply str %)) (rotations (seq (str n))))) 1.298 + 1.299 + 1.300 +(defn prime-factors 1.301 + [n] 1.302 + (for [a primes :while (<= a n) :when (= (rem n a) 0)] a)) 1.303 + 1.304 + 1.305 +(defmethod = [nil java.lang.Integer] [ a b ] 1.306 + false) 1.307 + 1.308 + 1.309 + 1.310 +(def mil 1000000) 1.311 +(def bil 1000000000) 1.312 + 1.313 +(defn primes-under-million [] (apply hash-set (take 78498 primes))) 1.314 +(def primes-under-million (memoize primes-under-million)) 1.315 + 1.316 + 1.317 +(defn primes-under-billion [] (apply hash-set (take 664579 primes))) 1.318 +(def primes-under-billion (memoize primes-under-billion)) 1.319 + 1.320 + 1.321 + 1.322 + 1.323 + 1.324 +(defn prime? [n] (not (nil? (get (primes-under-billion) n)))) 1.325 + 1.326 + 1.327 +(defn circular-memoize 1.328 + "assumes that f is a predicate that takes in a number for which, 1.329 + if the predicate is true for the number, it is also true for all 1.330 + of the circular permutations of the number. Memoizes the result 1.331 + for all circular permutations so as to avoid subsequent computation." 1.332 + [f] 1.333 + (let [mem (atom {})] 1.334 + (fn [n] 1.335 + (if-let [e (find @mem n)] 1.336 + (val e) 1.337 + (let [ret (f n)] 1.338 + (dorun (for [circ (circulars n)] 1.339 + (swap! mem assoc n ret))) 1.340 + ret))))) 1.341 + 1.342 +(defn circularly-prime? 1.343 + [n] 1.344 + (not (some (comp not prime?) (circulars n)))) 1.345 + 1.346 +(def circularly-prime? (memoize circularly-prime?)) 1.347 + 1.348 + 1.349 +(defmethod = :default [& args] 1.350 + (apply clojure.core/= args)) 1.351 + 1.352 +(def logins 1.353 + (map str 1.354 + [319 680 180 690 129 620 762 689 762 318 1.355 + 368 710 720 710 629 168 160 689 716 731 1.356 + 736 729 316 729 729 710 769 290 719 680 1.357 + 318 389 162 289 162 718 729 319 790 680 1.358 + 890 362 319 760 316 729 380 319 728 716])) 1.359 + 1.360 +(defn remove-multiples [n] 1.361 + (reduce (fn [a b] (if (= (last a) b) a (conj a b))) [] n)) 1.362 + 1.363 +(defn insert [item n vect] 1.364 + (let [split (split-at n vect)] 1.365 + (apply vector (flatten [(first split) item (last split)])))) 1.366 + 1.367 +(defn expand-code [old-code [c b a]] 1.368 + (let [main-length (count old-code)] 1.369 + (for [x (range (inc main-length)) y (range (inc x)) z (range (inc y))] 1.370 + (insert c z (insert b y (insert a x old-code)))))) 1.371 + 1.372 +(defn domain-expand-contract [old-domain constraint] 1.373 + (let [new-domain 1.374 + (map remove-multiples 1.375 + (remove-multiples 1.376 + (sort 1.377 + (apply concat 1.378 + (map #(expand-code % constraint) old-domain))))) 1.379 + min-code-length (apply min (map count new-domain)) ] 1.380 + (map #(apply str %) (filter #(= (count %) min-code-length) new-domain)))) 1.381 +(def domain-expand-contract (memoize domain-expand-contract)) 1.382 + 1.383 + 1.384 + 1.385 +(defn lazy-fibo 1.386 + ([] (concat [0 1] (lazy-fibo 0 1))) 1.387 + ([a b] (let [n (+ a b)] (lazy-seq (cons n (lazy-fibo b n)))))) 1.388 + 1.389 + 1.390 +(defn collatz-seq [n] 1.391 + (lazy-seq 1.392 + (cond (= n 1) [1] 1.393 + (even? n) (lazy-seq (cons n (collatz-seq (/ n 2)))) 1.394 + (odd? n) (lazy-seq (cons n (collatz-seq (+ 1 (* 3 n)))))))) 1.395 +(def collatz-seq (memoize collatz-seq)) 1.396 + 1.397 + 1.398 + 1.399 +(defn pythagorean-triple? [a b c] 1.400 + (let [[a b c] (sort [a b c])] 1.401 + (= (+ (* a a) (* b b) ) (* c c)))) 1.402 + 1.403 + 1.404 +(defn sum-squares [coll] 1.405 + (reduce + (map #(* % %) coll))) 1.406 + 1.407 + 1.408 +(defn british-letter-count [n] 1.409 + 1.410 + (let [and? (if (and (> n 99) (!= 0 (rem n 100))) 3 0)] 1.411 + 1.412 + (+ and? (count (filter #(Character/isLetter %) (seq (wordify n))))))) 1.413 + 1.414 + 1.415 + 1.416 +(defmacro apply-macro 1.417 + "This is evil. Don't ever use it. It makes a macro behave like a 1.418 + function. Seriously, how messed up is that? 1.419 + 1.420 + Evaluates all args, then uses them as arguments to the macro as with 1.421 + apply. 1.422 + 1.423 + (def things [true true false]) 1.424 + (apply-macro and things) 1.425 + ;; Expands to: (and true true false)" 1.426 + [macro & args] 1.427 + (cons macro (flatten (map eval args)))) 1.428 + 1.429 +(defn fun1 [] (Thread/sleep 5000) 5) 1.430 + 1.431 +(defn fun2 [] (Thread/sleep 30000) 5) 1.432 + 1.433 + 1.434 +(def naturals (iterate inc 0)) 1.435 + 1.436 + 1.437 + 1.438 + 1.439 +(defn race [] 1.440 + (let [result (ref nil) 1.441 + threads [(Thread. (fn [] (try 1.442 + (let [answer (fun1)] 1.443 + (dosync (ref-set result answer))) 1.444 + (catch Exception _ nil)))) 1.445 + (Thread. (fn [] (try 1.446 + (let [answer (fun2)] 1.447 + (dosync (ref-set result answer))) 1.448 + (catch Exception _ nil))))]] 1.449 + 1.450 + (dorun (map #(.start %) threads)) 1.451 + (loop [] 1.452 + (if (!= (deref result) nil) 1.453 + (do (dorun (map #(.stop %) threads)) 1.454 + (deref result)) 1.455 + (recur))))) 1.456 + 1.457 + 1.458 + 1.459 + 1.460 + 1.461 + 1.462 + 1.463 +(defn make-date [year month day] (do (let [date (Calendar/getInstance)] (.set date year month day 0 0) date))) 1.464 + 1.465 +(def jan-1-1901 (make-date 1900 0 1)) 1.466 + 1.467 +(defn sunday? [#^java.util.Date date] (re-matches #"^Sun.*" (str date))) 1.468 + 1.469 +(count (filter sunday? (for [a (range 1 40000) date [(.getTime (make-date 1900 0 a)) ] :while (< (.getYear date) 100)] date ))) 1.470 + 1.471 + 1.472 + 1.473 + 1.474 +(comment 1.475 + 1.476 +;; ---------------------------------------------------------------------- 1.477 +;; Answers 1.478 +;; ---------------------------------------------------------------------- 1.479 + 1.480 +; Problem 1 1.481 +(+ (range-sum 0 1001 3) (range-sum 0 1001 5) (* -1 (range-sum 0 1001 15))) 1.482 + 1.483 +; Problem 2 1.484 +(reduce + (for [a (filter even? (fibs)) :while (<= a 4000000 )] a)) 1.485 + 1.486 +; Problem 3 1.487 +(apply max (prime-factors 600851475143)) 1.488 + 1.489 +; Problem 4 1.490 +(reduce max (for [a (range 100 1000) b (range 100 1000) :when (palindrome? (* a b))] (* a b))) 1.491 + 1.492 +; Problem 5 1.493 +(reduce lcm (range 1 21)) 1.494 + 1.495 +; Problem 6 1.496 +(- (expt (range-sum 101) 2) (range-sum-squares 101)) 1.497 + 1.498 +; Problem 7 1.499 +(nth primes 10000) 1.500 + 1.501 + 1.502 +; Problem 9 1.503 +(reduce * (first (for [a (range 1 1000) b (range 1 a) c [(sqrt (sum-squares [a b]))] 1.504 + :when (= (+ a b c) 1000)] [a b c]))) 1.505 + 1.506 +; Problem 10 1.507 +(reduce + (for [a primes :while (< a 2000000)] a)) 1.508 + 1.509 + 1.510 + 1.511 + 1.512 + 1.513 +; Problem 14 1.514 +(first (reduce (fn [a b] (if (> (count a) (count b)) a b)) [] (map collatz-seq (range 1 mil)))) 1.515 + 1.516 + 1.517 +; Problem 16 1.518 +(reduce + (map #(Character/getNumericValue %) (seq (str (expt 2 1000))))) 1.519 + 1.520 +; Problem 17 1.521 +(reduce + (map british-letter-count (range 1 1001))) 1.522 + 1.523 + 1.524 +; Problem 24 1.525 +(nth (lex-permutations [ 0 1 2 3 4 5 6 7 8 9]) (- mil 1)) 1.526 + 1.527 +; Problem 33 1.528 +(reduce * (for [num (range 1 10) 1.529 + den (range 1 10) 1.530 + weird (range 1 10) 1.531 + top [(+ num (* 10 weird))] 1.532 + bottom [(+ weird (* 10 den))] 1.533 + :when (and (> (/ top bottom) 1) (= (/ top bottom) (/ num den)))] 1.534 + (/ bottom top))) 1.535 + 1.536 +; Problem 35 1.537 +(count (filter circularly-prime? (primes-under-million))) 1.538 + 1.539 +; Problem 40 1.540 +(let [fff (apply str (take 1030000 naturals))] 1.541 + (reduce * (map #(Character/getNumericValue (nth fff %)) 1.542 + (map (fn [x] (expt 10 x)) (range 7)) ))) 1.543 + 1.544 + 1.545 + 1.546 + 1.547 + 1.548 + 1.549 +; Problem 79 1.550 +(reduce domain-expand-contract [""] logins) 1.551 + 1.552 +) 1.553 + 1.554 + 1.555 + 1.556 + 1.557 + 1.558 + 1.559 + 1.560 + 1.561 + 1.562 +