From e55c6650b99a4832fa3f6df851f86bae0778e6f3 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Fri, 24 Jan 2025 16:57:36 +0100 Subject: [PATCH 01/17] finished 1 --- spec/euler/level1/problem001_spec.clj | 12 +++++++++++- src/euler/level1/problem001.clj | 8 +++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/spec/euler/level1/problem001_spec.clj b/spec/euler/level1/problem001_spec.clj index 83421ee..1bbb24d 100644 --- a/spec/euler/level1/problem001_spec.clj +++ b/spec/euler/level1/problem001_spec.clj @@ -7,9 +7,19 @@ (describe "Euler Problem #1" + (it "finds multiples of 3 and 5" + (should= false (multiple-of-3-or-5? 1)) + (should= true (multiple-of-3-or-5? 3)) + (should= true (multiple-of-3-or-5? 10)) + ) + (it "Solves #1" (should= 23 (euler-1 10)) - (should= -1 (euler-1 1000))) + (should= 3 (euler-1 4)) + (should= 8 (euler-1 6)) + (should= 33 (euler-1 11)) + ;(should= -1 (euler-1 1000)) + ) ) (run-specs) diff --git a/src/euler/level1/problem001.clj b/src/euler/level1/problem001.clj index 9458aa3..95759b0 100644 --- a/src/euler/level1/problem001.clj +++ b/src/euler/level1/problem001.clj @@ -1,4 +1,10 @@ (ns euler.level1.problem001) -(defn euler-1 [n] +(defn multiple-of-3-or-5? [n] + (or (zero? (mod n 3)) (zero? (mod n 5))) ) + +(defn euler-1 [n] + (->> (range n) + (filter multiple-of-3-or-5?) + (apply +))) From d68d93ac2fee24fc15e9f4bbf764b3074791ac32 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Mon, 27 Jan 2025 10:26:16 +0100 Subject: [PATCH 02/17] first 3 --- spec/euler/level1/problem001_spec.clj | 2 +- spec/euler/level1/problem002_spec.clj | 20 ++++++++++++++++++++ spec/euler/level1/problem003_spec.clj | 16 ++++++++++++++++ src/euler/level1/problem002.clj | 8 ++++++++ src/euler/level1/problem003.clj | 22 ++++++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 spec/euler/level1/problem002_spec.clj create mode 100644 spec/euler/level1/problem003_spec.clj create mode 100644 src/euler/level1/problem002.clj create mode 100644 src/euler/level1/problem003.clj diff --git a/spec/euler/level1/problem001_spec.clj b/spec/euler/level1/problem001_spec.clj index 1bbb24d..3a28486 100644 --- a/spec/euler/level1/problem001_spec.clj +++ b/spec/euler/level1/problem001_spec.clj @@ -18,7 +18,7 @@ (should= 3 (euler-1 4)) (should= 8 (euler-1 6)) (should= 33 (euler-1 11)) - ;(should= -1 (euler-1 1000)) + (should= 233168 (euler-1 1000)) ) ) diff --git a/spec/euler/level1/problem002_spec.clj b/spec/euler/level1/problem002_spec.clj new file mode 100644 index 0000000..f7bf111 --- /dev/null +++ b/spec/euler/level1/problem002_spec.clj @@ -0,0 +1,20 @@ +(ns euler.level1.problem002-spec + (:require + [speclj.core :refer :all] + [euler.level1.problem002 :refer :all])) + +; https://projecteuler.net/problem=2 + +(describe "Euler Problem #2" + + (it "Solves #2" + (should= 1 (euler-2 1)) + (should= 2 (euler-2 2)) + (should= 3 (euler-2 3)) + (should= 5 (euler-2 4)) + (should= 13 (euler-2 6)) + (should= 89 (euler-2 10)) + ) + ) + +(run-specs) diff --git a/spec/euler/level1/problem003_spec.clj b/spec/euler/level1/problem003_spec.clj new file mode 100644 index 0000000..6e81004 --- /dev/null +++ b/spec/euler/level1/problem003_spec.clj @@ -0,0 +1,16 @@ +(ns euler.level1.problem003-spec + (:require + [speclj.core :refer :all] + [euler.level1.problem003 :refer :all])) + +; https://projecteuler.net/problem=3 + +(describe "Euler Problem #3" + + (it "Solves #3" + (should= 7 (euler-3 7)) + (should= 29 (euler-3 13195)) + ) + ) + +(run-specs) diff --git a/src/euler/level1/problem002.clj b/src/euler/level1/problem002.clj new file mode 100644 index 0000000..0e578f2 --- /dev/null +++ b/src/euler/level1/problem002.clj @@ -0,0 +1,8 @@ +(ns euler.level1.problem002) + +(defn euler-2 [n] + (if (>= 2 n) + n + (+ (euler-2 (- n 2)) (euler-2 (- n 1))) + ) + ) diff --git a/src/euler/level1/problem003.clj b/src/euler/level1/problem003.clj new file mode 100644 index 0000000..9d5a577 --- /dev/null +++ b/src/euler/level1/problem003.clj @@ -0,0 +1,22 @@ +(ns euler.level1.problem003) + +(defn smallest-factor [n] + ( + first (filter + (fn[x] (= (mod n x) 0)) + (iterate inc 2)) + ) + ) + +(defn factorize [n] + (let [other (/ n (smallest-factor n))] + (if (= other 1) + n + (factorize other) + ) + ) + ) + +(defn euler-3 [n] + (factorize n) + ) From 9b1f16f5b5426e4108c8c18980dffbfdc8456c7e Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Mon, 27 Jan 2025 12:46:14 +0100 Subject: [PATCH 03/17] 4 --- spec/euler/level1/problem004_spec.clj | 19 +++++++++++ src/euler/level1/problem004.clj | 46 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 spec/euler/level1/problem004_spec.clj create mode 100644 src/euler/level1/problem004.clj diff --git a/spec/euler/level1/problem004_spec.clj b/spec/euler/level1/problem004_spec.clj new file mode 100644 index 0000000..bfd27eb --- /dev/null +++ b/spec/euler/level1/problem004_spec.clj @@ -0,0 +1,19 @@ +(ns euler.level1.problem004-spec + (:require + [speclj.core :refer :all] + [euler.level1.problem004 :refer :all])) + +; https://projecteuler.net/problem=4 + +(describe "Euler Problem #4" + + (it "Solves #4" + (should= false (is-palindrome "21")) + (should= true (is-palindrome "1")) + (should= true (is-palindrome "121")) + (should= 9009 (euler-4 2)) + (should= 906609 (euler-4 3)) + ) + ) + +(run-specs) diff --git a/src/euler/level1/problem004.clj b/src/euler/level1/problem004.clj new file mode 100644 index 0000000..733b01b --- /dev/null +++ b/src/euler/level1/problem004.clj @@ -0,0 +1,46 @@ +(ns euler.level1.problem004) + +(defn is-palindrome [s] + (let [len (count s) + last (dec len)] + (if (<= len 1) + true + (and + (= (get s 0) (get s last)) + (is-palindrome (subs s 1 last)) + ) + ) + ) +) + +(defn products-of-n-digit-numbers [n] + (let [ + n-digit-nos + (range + (int (Math/pow 10 (- n 1))) + (int (Math/pow 10 n)))] + (flatten + (map (fn [x] + (map (fn [y] (* x y)) n-digit-nos) + ) n-digit-nos) + ) + ) + ) + +(defn euler-4 [n] + (let [ + n-digit-nos + (range + (int (Math/pow 10 (- n 1))) + (int (Math/pow 10 n)))] + (reduce + max + (filter + (fn [n] + (is-palindrome (str n)) + ) + (products-of-n-digit-numbers n) + ) + ) + ) +) From c5155c0c6fed51b6e0930d54bb23675ee960f488 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Mon, 27 Jan 2025 13:39:25 +0100 Subject: [PATCH 04/17] 5 --- spec/euler/level1/problem005_spec.clj | 18 ++++++++++++++++++ src/euler/level1/problem005.clj | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 spec/euler/level1/problem005_spec.clj create mode 100644 src/euler/level1/problem005.clj diff --git a/spec/euler/level1/problem005_spec.clj b/spec/euler/level1/problem005_spec.clj new file mode 100644 index 0000000..a738a01 --- /dev/null +++ b/spec/euler/level1/problem005_spec.clj @@ -0,0 +1,18 @@ +(ns euler.level1.problem005-spec + (:require + [speclj.core :refer :all] + [euler.level1.problem005 :refer :all])) + +; https://projecteuler.net/problem=5 + +(describe "Euler Problem #5" + + (it "Solves #5" + (should= true (divisible 10 [2 5])) + (should= false (divisible 10 [3 5])) + (should= true (divisible 2520 [2 3 4 5 6 7 8 9 10])) + (should= 2520 (euler-5 10)) + ) + ) + +(run-specs) diff --git a/src/euler/level1/problem005.clj b/src/euler/level1/problem005.clj new file mode 100644 index 0000000..0507ad3 --- /dev/null +++ b/src/euler/level1/problem005.clj @@ -0,0 +1,25 @@ +(ns euler.level1.problem005) + +(defn divisible [o divisors] + (= + (count divisors) + (count + (filter + zero? + (map + (fn [divisor] + (mod o divisor)) divisors) + ) + ) + ) + ) + + +(defn euler-5 [n] + (let [divisors (range 1 (+ n 1)) + largest (reduce * divisors)] + (inc (last + (take-while (fn [n] (not (divisible n divisors))) (iterate inc 1)) + ) + )) + ) From b02566b397fbec2ddff8a11855890294deda9fba Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Mon, 27 Jan 2025 18:13:19 +0100 Subject: [PATCH 05/17] perf improvement --- spec/euler/level1/problem005_spec.clj | 1 + src/euler/level1/problem005.clj | 44 ++++++++++++++++++--------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/spec/euler/level1/problem005_spec.clj b/spec/euler/level1/problem005_spec.clj index a738a01..c5a1340 100644 --- a/spec/euler/level1/problem005_spec.clj +++ b/spec/euler/level1/problem005_spec.clj @@ -12,6 +12,7 @@ (should= false (divisible 10 [3 5])) (should= true (divisible 2520 [2 3 4 5 6 7 8 9 10])) (should= 2520 (euler-5 10)) + (should= 232792560 (euler-5 20)) ) ) diff --git a/src/euler/level1/problem005.clj b/src/euler/level1/problem005.clj index 0507ad3..4861191 100644 --- a/src/euler/level1/problem005.clj +++ b/src/euler/level1/problem005.clj @@ -1,25 +1,41 @@ (ns euler.level1.problem005) +(defn take-until + "Returns a lazy sequence of successive items from coll until + (pred item) returns true, including that item. pred must be + free of side-effects." + [pred coll] + (lazy-seq + (when-let [s (seq coll)] + (if (pred (first s)) + (cons (first s) nil) + (cons (first s) (take-until pred (rest s))))))) + (defn divisible [o divisors] - (= - (count divisors) - (count - (filter - zero? - (map - (fn [divisor] - (mod o divisor)) divisors) + (if (= o 0) + false + (= + (count divisors) + (count + (filter + zero? + (map + (fn [divisor] + (mod o divisor)) divisors) + ) ) ) - ) + ) ) (defn euler-5 [n] - (let [divisors (range 1 (+ n 1)) - largest (reduce * divisors)] - (inc (last - (take-while (fn [n] (not (divisible n divisors))) (iterate inc 1)) + (let [divisors (range 1 (+ n 1))] + (last + (take-until + (fn [n] + (divisible n divisors)) + (iterate (fn [x] (+ x 210)) 0)) ) - )) + ) ) From a8481f0ba504f736f4cb9655914f57d19ef48315 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Tue, 28 Jan 2025 09:23:49 +0100 Subject: [PATCH 06/17] 7 --- spec/euler/level1/problem006_spec.clj | 15 ++++++++++++ spec/euler/level1/problem007_spec.clj | 26 ++++++++++++++++++++ src/euler/level1/problem006.clj | 16 +++++++++++++ src/euler/level1/problem007.clj | 34 +++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 spec/euler/level1/problem006_spec.clj create mode 100644 spec/euler/level1/problem007_spec.clj create mode 100644 src/euler/level1/problem006.clj create mode 100644 src/euler/level1/problem007.clj diff --git a/spec/euler/level1/problem006_spec.clj b/spec/euler/level1/problem006_spec.clj new file mode 100644 index 0000000..d5ced06 --- /dev/null +++ b/spec/euler/level1/problem006_spec.clj @@ -0,0 +1,15 @@ +(ns euler.level1.problem006-spec + (:require + [speclj.core :refer :all] + [euler.level1.problem006 :refer :all])) + +; https://projecteuler.net/problem=6 + +(describe "Euler Problem #6" + + (it "Solves #6" + (should= 2640 (euler-6 10)) + (should= 25164150 (euler-6 100))) + ) + +(run-specs) diff --git a/spec/euler/level1/problem007_spec.clj b/spec/euler/level1/problem007_spec.clj new file mode 100644 index 0000000..3e43993 --- /dev/null +++ b/spec/euler/level1/problem007_spec.clj @@ -0,0 +1,26 @@ +(ns euler.level1.problem007-spec + (:require + [speclj.core :refer :all] + [euler.level1.problem007 :refer :all])) + +; https://projecteuler.net/problem=7 + +(describe "Euler Problem #7" + + (it "Solves #7" + (should= true (is-prime 1)) + (should= true (is-prime 2)) + (should= true (is-prime 3)) + (should= false (is-prime 4)) + (should= false (is-prime 6)) + (should= false (is-prime 9)) + (should= 7 (next-prime 5)) + (should= 3 (next-prime 2)) + (should= 11 (next-prime 7)) + (should= 13 (euler-7 6)) + (should= 104743 (euler-7 10001)) + ) + + ) + +(run-specs) diff --git a/src/euler/level1/problem006.clj b/src/euler/level1/problem006.clj new file mode 100644 index 0000000..33c2faf --- /dev/null +++ b/src/euler/level1/problem006.clj @@ -0,0 +1,16 @@ +(ns euler.level1.problem006) + + + +(defn euler-6 [n] + (let [r (map inc (range n))] + (int (- + (Math/pow ; square of + (reduce + r) ; sum + 2) + (reduce + ;sum of + (map (fn [n] (Math/pow n 2)) r); squares + ) + ) + )) + ) diff --git a/src/euler/level1/problem007.clj b/src/euler/level1/problem007.clj new file mode 100644 index 0000000..6f34f0d --- /dev/null +++ b/src/euler/level1/problem007.clj @@ -0,0 +1,34 @@ +(ns euler.level1.problem007 + (:require + [euler.level1.problem005 :refer :all]) + ) + +(defn is-prime [n] + (let [divisors (range 2 n)] + (empty? + (filter + zero? + (map + (fn [divisor] + (mod n divisor)) divisors) + ) + ) + ) + ) + +(defn next-prime [n] + (inc + (or + (last + (take-while (fn [n] (not (is-prime n))) + (iterate inc (inc n))) + ) + n + ) + ) + ) + +(defn euler-7 [n] + (last (take n (iterate + next-prime 2))) + ) From 1a931b980e0c6c7b6aa5007a6f7d02fb0619476f Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Tue, 28 Jan 2025 13:26:04 +0100 Subject: [PATCH 07/17] 8 --- spec/euler/level1/problem008_spec.clj | 20 +++++++++++ src/euler/level1/problem008.clj | 48 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 spec/euler/level1/problem008_spec.clj create mode 100644 src/euler/level1/problem008.clj diff --git a/spec/euler/level1/problem008_spec.clj b/spec/euler/level1/problem008_spec.clj new file mode 100644 index 0000000..0e06632 --- /dev/null +++ b/spec/euler/level1/problem008_spec.clj @@ -0,0 +1,20 @@ +(ns euler.level1.problem008-spec + (:require + [speclj.core :refer :all] + [euler.level1.problem008 :refer :all])) + +; https://projecteuler.net/problem=8 + +(describe "Euler Problem #8" + + (it "Solves #8" + (should= "7316" (first (segment-by-digits 4))) + (should= "3167" (second (segment-by-digits 4))) + (should= "3450" (last (segment-by-digits 4))) + (should= (* 2 3 4) (digits-product 234)) + (should= 5832 (euler-8 4)) + (should= 23514624000 (euler-8 13)) + ) + ) + +(run-specs) diff --git a/src/euler/level1/problem008.clj b/src/euler/level1/problem008.clj new file mode 100644 index 0000000..029aed6 --- /dev/null +++ b/src/euler/level1/problem008.clj @@ -0,0 +1,48 @@ +(ns euler.level1.problem008 + (:require [clojure.string :as string])) + +(def the-number (string/replace "73167176531330624919225119674426574742355349194934 + 96983520312774506326239578318016984801869478851843 + 85861560789112949495459501737958331952853208805511 + 12540698747158523863050715693290963295227443043557 + 66896648950445244523161731856403098711121722383113 + 62229893423380308135336276614282806444486645238749 + 30358907296290491560440772390713810515859307960866 + 70172427121883998797908792274921901699720888093776 + 65727333001053367881220235421809751254540594752243 + 52584907711670556013604839586446706324415722155397 + 53697817977846174064955149290862569321978468622482 + 83972241375657056057490261407972968652414535100474 + 82166370484403199890008895243450658541227588666881 + 16427171479924442928230863465674813919123162824586 + 17866458359124566529476545682848912883142607690042 + 24219022671055626321111109370544217506941658960408 + 07198403850962455444362981230987879927244284909188 + 84580156166097919133875499200524063689912560717606 + 05886116467109405077541002256983155200055935729725 + 71636269561882670428252483600823257530420752963450" #"\r\n|\n|\r| " "")) + +(defn segment-by-digits [n] + (map + (fn [i] + (subs the-number (- i n) i)) + (range n (inc (count the-number)))) + ) + +(defn digits-product [n] + (reduce + (fn [cum char] + (* (- (int char) (int \0)) cum)) + 1 + (str n)) + ) + +(defn euler-8 [n] + (first + (sort > + (map + digits-product + (segment-by-digits n)) + ) + ) + ) From 27600322d77bb3bd4edaddab7f4178fd31288f3f Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Tue, 28 Jan 2025 19:20:52 +0100 Subject: [PATCH 08/17] review --- spec/euler/level1/problem002_spec.clj | 22 ++++++++++----- spec/euler/level1/problem003_spec.clj | 1 + spec/euler/level1/problem004_spec.clj | 8 ++++-- spec/euler/level1/problem005_spec.clj | 9 ++++-- spec/euler/level1/problem007_spec.clj | 20 +++++++++----- spec/euler/level1/problem008_spec.clj | 8 +++++- src/euler/level1/problem002.clj | 13 ++++++--- src/euler/level1/problem003.clj | 16 ++++------- src/euler/level1/problem004.clj | 40 +++++++-------------------- src/euler/level1/problem005.clj | 4 +-- src/euler/level1/problem006.clj | 12 ++++---- src/euler/level1/problem007.clj | 4 +-- 12 files changed, 81 insertions(+), 76 deletions(-) diff --git a/spec/euler/level1/problem002_spec.clj b/spec/euler/level1/problem002_spec.clj index f7bf111..0b555de 100644 --- a/spec/euler/level1/problem002_spec.clj +++ b/spec/euler/level1/problem002_spec.clj @@ -7,14 +7,22 @@ (describe "Euler Problem #2" - (it "Solves #2" - (should= 1 (euler-2 1)) - (should= 2 (euler-2 2)) - (should= 3 (euler-2 3)) - (should= 5 (euler-2 4)) - (should= 13 (euler-2 6)) - (should= 89 (euler-2 10)) + (it "fib" + (should= '(1) (fib 1)) + (should= '(1 2) (fib 2)) + (should= '(1 2 3) (fib 3)) + (should= '(1 2 3 5) (fib 4)) + (should= '(1 2 3 5 8 13) (fib 6)) + (should= 3524578 (last (fib 32))) + (should= 5702887 (last (fib 33))) ) + + (it "euler-2" + (should= 4613732 (euler-2 32)) + ) + ) + + (run-specs) diff --git a/spec/euler/level1/problem003_spec.clj b/spec/euler/level1/problem003_spec.clj index 6e81004..617e520 100644 --- a/spec/euler/level1/problem003_spec.clj +++ b/spec/euler/level1/problem003_spec.clj @@ -10,6 +10,7 @@ (it "Solves #3" (should= 7 (euler-3 7)) (should= 29 (euler-3 13195)) + (should= 6857 (euler-3 600851475143)) ) ) diff --git a/spec/euler/level1/problem004_spec.clj b/spec/euler/level1/problem004_spec.clj index bfd27eb..5064ef7 100644 --- a/spec/euler/level1/problem004_spec.clj +++ b/spec/euler/level1/problem004_spec.clj @@ -7,10 +7,12 @@ (describe "Euler Problem #4" + (it "palindrome?" + (should= false (palindrome? 21)) + (should= true (palindrome? 1)) + (should= true (palindrome? 121))) + (it "Solves #4" - (should= false (is-palindrome "21")) - (should= true (is-palindrome "1")) - (should= true (is-palindrome "121")) (should= 9009 (euler-4 2)) (should= 906609 (euler-4 3)) ) diff --git a/spec/euler/level1/problem005_spec.clj b/spec/euler/level1/problem005_spec.clj index c5a1340..3bcc2d3 100644 --- a/spec/euler/level1/problem005_spec.clj +++ b/spec/euler/level1/problem005_spec.clj @@ -7,10 +7,13 @@ (describe "Euler Problem #5" + (it "divisible" + (should= true (divisible? 10 [2 5])) + (should= false (divisible? 10 [3 5])) + (should= true (divisible? 2520 [2 3 4 5 6 7 8 9 10])) + ) + (it "Solves #5" - (should= true (divisible 10 [2 5])) - (should= false (divisible 10 [3 5])) - (should= true (divisible 2520 [2 3 4 5 6 7 8 9 10])) (should= 2520 (euler-5 10)) (should= 232792560 (euler-5 20)) ) diff --git a/spec/euler/level1/problem007_spec.clj b/spec/euler/level1/problem007_spec.clj index 3e43993..531498d 100644 --- a/spec/euler/level1/problem007_spec.clj +++ b/spec/euler/level1/problem007_spec.clj @@ -7,16 +7,22 @@ (describe "Euler Problem #7" - (it "Solves #7" - (should= true (is-prime 1)) - (should= true (is-prime 2)) - (should= true (is-prime 3)) - (should= false (is-prime 4)) - (should= false (is-prime 6)) - (should= false (is-prime 9)) + (it "prime" + (should= true (prime? 1)) + (should= true (prime? 2)) + (should= true (prime? 3)) + (should= false (prime? 4)) + (should= false (prime? 6)) + (should= false (prime? 9)) + ) + + (it "next-prime" (should= 7 (next-prime 5)) (should= 3 (next-prime 2)) (should= 11 (next-prime 7)) + ) + + (it "Solves #7" (should= 13 (euler-7 6)) (should= 104743 (euler-7 10001)) ) diff --git a/spec/euler/level1/problem008_spec.clj b/spec/euler/level1/problem008_spec.clj index 0e06632..55a2134 100644 --- a/spec/euler/level1/problem008_spec.clj +++ b/spec/euler/level1/problem008_spec.clj @@ -7,11 +7,17 @@ (describe "Euler Problem #8" - (it "Solves #8" + (it "segment-by-digits" (should= "7316" (first (segment-by-digits 4))) (should= "3167" (second (segment-by-digits 4))) (should= "3450" (last (segment-by-digits 4))) + ) + + (it "digits-product" (should= (* 2 3 4) (digits-product 234)) + ) + + (it "Solves #8" (should= 5832 (euler-8 4)) (should= 23514624000 (euler-8 13)) ) diff --git a/src/euler/level1/problem002.clj b/src/euler/level1/problem002.clj index 0e578f2..d509772 100644 --- a/src/euler/level1/problem002.clj +++ b/src/euler/level1/problem002.clj @@ -1,8 +1,13 @@ (ns euler.level1.problem002) + +(defn fib [n] + (->> [0 1] + (iterate (fn [[a b]] [b (+ a b)])) + (map first) + (drop 2) + (take n))) + (defn euler-2 [n] - (if (>= 2 n) - n - (+ (euler-2 (- n 2)) (euler-2 (- n 1))) - ) + (reduce + (filter even? (fib n))) ) diff --git a/src/euler/level1/problem003.clj b/src/euler/level1/problem003.clj index 9d5a577..27b75f5 100644 --- a/src/euler/level1/problem003.clj +++ b/src/euler/level1/problem003.clj @@ -1,22 +1,16 @@ (ns euler.level1.problem003) (defn smallest-factor [n] - ( - first (filter + (first (filter (fn[x] (= (mod n x) 0)) - (iterate inc 2)) - ) - ) + ;#(= (mod n %) 0) + (iterate inc 2)))) (defn factorize [n] (let [other (/ n (smallest-factor n))] (if (= other 1) n - (factorize other) - ) - ) - ) + (factorize other)))) (defn euler-3 [n] - (factorize n) - ) + (factorize n)) diff --git a/src/euler/level1/problem004.clj b/src/euler/level1/problem004.clj index 733b01b..c051b8c 100644 --- a/src/euler/level1/problem004.clj +++ b/src/euler/level1/problem004.clj @@ -1,46 +1,26 @@ (ns euler.level1.problem004) -(defn is-palindrome [s] - (let [len (count s) +(defn palindrome? [s] + (let [s (str s) + len (count s) last (dec len)] + ;(= (seq s) (reverse s)) (if (<= len 1) true (and (= (get s 0) (get s last)) - (is-palindrome (subs s 1 last)) - ) - ) - ) -) + (palindrome? (subs s 1 last)))))) (defn products-of-n-digit-numbers [n] - (let [ - n-digit-nos + (let [n-digit-nos (range (int (Math/pow 10 (- n 1))) (int (Math/pow 10 n)))] (flatten (map (fn [x] - (map (fn [y] (* x y)) n-digit-nos) - ) n-digit-nos) - ) - ) - ) + (map (fn [y] (* x y)) n-digit-nos)) n-digit-nos)))) (defn euler-4 [n] - (let [ - n-digit-nos - (range - (int (Math/pow 10 (- n 1))) - (int (Math/pow 10 n)))] - (reduce - max - (filter - (fn [n] - (is-palindrome (str n)) - ) - (products-of-n-digit-numbers n) - ) - ) - ) -) + (reduce + max + (filter palindrome? (products-of-n-digit-numbers n)))) diff --git a/src/euler/level1/problem005.clj b/src/euler/level1/problem005.clj index 4861191..94a1da4 100644 --- a/src/euler/level1/problem005.clj +++ b/src/euler/level1/problem005.clj @@ -11,7 +11,7 @@ (cons (first s) nil) (cons (first s) (take-until pred (rest s))))))) -(defn divisible [o divisors] +(defn divisible? [o divisors] (if (= o 0) false (= @@ -34,7 +34,7 @@ (last (take-until (fn [n] - (divisible n divisors)) + (divisible? n divisors)) (iterate (fn [x] (+ x 210)) 0)) ) ) diff --git a/src/euler/level1/problem006.clj b/src/euler/level1/problem006.clj index 33c2faf..e33a047 100644 --- a/src/euler/level1/problem006.clj +++ b/src/euler/level1/problem006.clj @@ -1,15 +1,15 @@ (ns euler.level1.problem006) - +(defn square [n] + (Math/pow n 2)) (defn euler-6 [n] (let [r (map inc (range n))] (int (- - (Math/pow ; square of - (reduce + r) ; sum - 2) - (reduce + ;sum of - (map (fn [n] (Math/pow n 2)) r); squares + (square + (reduce + r)) + (reduce + + (map square r) ) ) )) diff --git a/src/euler/level1/problem007.clj b/src/euler/level1/problem007.clj index 6f34f0d..668d309 100644 --- a/src/euler/level1/problem007.clj +++ b/src/euler/level1/problem007.clj @@ -3,7 +3,7 @@ [euler.level1.problem005 :refer :all]) ) -(defn is-prime [n] +(defn prime? [n] (let [divisors (range 2 n)] (empty? (filter @@ -20,7 +20,7 @@ (inc (or (last - (take-while (fn [n] (not (is-prime n))) + (take-while (fn [n] (not (prime? n))) (iterate inc (inc n))) ) n From 47cf5ca9c701a162a9938d98eac000f4bda68212 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Thu, 30 Jan 2025 11:37:56 +0100 Subject: [PATCH 09/17] checkpoint --- spec/euler/level1/bowling_spec.clj | 15 +++++++++++++++ src/euler/level1/bowling.clj | 14 ++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 spec/euler/level1/bowling_spec.clj create mode 100644 src/euler/level1/bowling.clj diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj new file mode 100644 index 0000000..9a37b6a --- /dev/null +++ b/spec/euler/level1/bowling_spec.clj @@ -0,0 +1,15 @@ +(ns euler.level1.bowling-spec + (:use + [speclj.core] + [euler.level1.bowling]) + (:import (euler.level1.bowling Game))) + +(describe "Bowling Game" + + (it "finds multiples of 3 and 5" + (should= false (multiple-of-3-or-5? 1)) + (should= 7 (get-pins (Game.))) + ) + ) + +(run-specs) diff --git a/src/euler/level1/bowling.clj b/src/euler/level1/bowling.clj new file mode 100644 index 0000000..b536a67 --- /dev/null +++ b/src/euler/level1/bowling.clj @@ -0,0 +1,14 @@ +(ns euler.level1.bowling) + +(defn multiple-of-3-or-5? [n] + (or (zero? (mod n 3)) (zero? (mod n 5))) + ) + +(defn euler-1 [n] + (->> (range n) + (filter multiple-of-3-or-5?) + (apply +))) + +(defrecord Game []) +(defmulti get-pins class) +(defmethod get-pins Game [game] 7) \ No newline at end of file From 6f0298965c2c6bf4cb01ce026a21edb9b4a483ec Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Fri, 31 Jan 2025 07:50:55 +0100 Subject: [PATCH 10/17] next step --- spec/euler/level1/bowling_spec.clj | 10 +++++-- src/euler/level1/bowling.clj | 45 ++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj index 9a37b6a..2f73952 100644 --- a/spec/euler/level1/bowling_spec.clj +++ b/spec/euler/level1/bowling_spec.clj @@ -6,9 +6,13 @@ (describe "Bowling Game" - (it "finds multiples of 3 and 5" - (should= false (multiple-of-3-or-5? 1)) - (should= 7 (get-pins (Game.))) + (it "Plays Game" + (let [game (Game.) + bowlingGame (BowlingGame 1 2)] + (should= 7 (score game)) + (roll "bar" "baz") + (roll bowlingGame 8) + ) ) ) diff --git a/src/euler/level1/bowling.clj b/src/euler/level1/bowling.clj index b536a67..bcff5f3 100644 --- a/src/euler/level1/bowling.clj +++ b/src/euler/level1/bowling.clj @@ -1,14 +1,35 @@ (ns euler.level1.bowling) -(defn multiple-of-3-or-5? [n] - (or (zero? (mod n 3)) (zero? (mod n 5))) - ) - -(defn euler-1 [n] - (->> (range n) - (filter multiple-of-3-or-5?) - (apply +))) - -(defrecord Game []) -(defmulti get-pins class) -(defmethod get-pins Game [game] 7) \ No newline at end of file + +(deftype Foo [a]) +(defrecord Bar [c]) + +(def f (Foo. 1)) +(.-a f) + +(def b (Bar. 1)) +(:c b) + +(defprotocol BowlingGame + (roll [pins])) + +(defrecord Game [frames] + BowlingGame + (roll [pins] (println "roll"))) +(deftype Frame [rolls]) +(deftype Roll [ball-1 ball-2]) +(defmulti score class) +(defmethod score Game [game] 7) + +(defn BowlingGame [x y] + [(class x) (class y)]) + +(def foo (fn [])) +(defn foo []) +(def a 1) + +(defn roll [a b] + (println a b)) + +(def roll [Long Long] [a b] + (println (+ a b))) \ No newline at end of file From 442f9f1cd1023aeb3d7a6716e1d6460660062eed Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Fri, 31 Jan 2025 08:05:10 +0100 Subject: [PATCH 11/17] another --- spec/euler/level1/bowling_spec.clj | 13 +++++------ src/euler/level1/bowling.clj | 36 +++++------------------------- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj index 2f73952..78fc3e1 100644 --- a/spec/euler/level1/bowling_spec.clj +++ b/spec/euler/level1/bowling_spec.clj @@ -2,17 +2,14 @@ (:use [speclj.core] [euler.level1.bowling]) - (:import (euler.level1.bowling Game))) + (:import (euler.level1.bowling Game)) + (:import (euler.level1.bowling Frame))) (describe "Bowling Game" - (it "Plays Game" - (let [game (Game.) - bowlingGame (BowlingGame 1 2)] - (should= 7 (score game)) - (roll "bar" "baz") - (roll bowlingGame 8) - ) + (it "Calculates Score" + (should= 0 (score (new-game))) + (should= 3 (score (Game. [(Frame. 1) (Frame. 2)]))) ) ) diff --git a/src/euler/level1/bowling.clj b/src/euler/level1/bowling.clj index bcff5f3..bd87709 100644 --- a/src/euler/level1/bowling.clj +++ b/src/euler/level1/bowling.clj @@ -1,35 +1,9 @@ (ns euler.level1.bowling) +(defrecord Frame [score]) -(deftype Foo [a]) -(defrecord Bar [c]) +(defrecord Game [frames]) +(defn new-game [] (Game. [])) -(def f (Foo. 1)) -(.-a f) - -(def b (Bar. 1)) -(:c b) - -(defprotocol BowlingGame - (roll [pins])) - -(defrecord Game [frames] - BowlingGame - (roll [pins] (println "roll"))) -(deftype Frame [rolls]) -(deftype Roll [ball-1 ball-2]) -(defmulti score class) -(defmethod score Game [game] 7) - -(defn BowlingGame [x y] - [(class x) (class y)]) - -(def foo (fn [])) -(defn foo []) -(def a 1) - -(defn roll [a b] - (println a b)) - -(def roll [Long Long] [a b] - (println (+ a b))) \ No newline at end of file +(defn frame-score [frame] (:score frame)) +(defn score [game] (reduce + (map frame-score (:frames game)))) \ No newline at end of file From 50a86cc64a816aab0e4911fa7cdeba495476486b Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Fri, 31 Jan 2025 08:26:33 +0100 Subject: [PATCH 12/17] rolls --- spec/euler/level1/bowling_spec.clj | 15 ++++++++++++++- src/euler/level1/bowling.clj | 8 ++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj index 78fc3e1..0fd2742 100644 --- a/spec/euler/level1/bowling_spec.clj +++ b/spec/euler/level1/bowling_spec.clj @@ -7,10 +7,23 @@ (describe "Bowling Game" - (it "Calculates Score" + (it "The score function must iterate through all the frames, and calculate all their scores." (should= 0 (score (new-game))) (should= 3 (score (Game. [(Frame. 1) (Frame. 2)]))) ) + + (it "rolls all zeroes" + (let [game (reduce (fn [cum _] (roll cum 0) (new-game)) (range 20))] + (should= 0 (score game)) + ) + ) + + (it "rolls all ones" + (let [game (reduce (fn [cum _] (roll cum 1) (new-game)) (range 20))] + (should= 0 (score game)) + ) + ) + ) (run-specs) diff --git a/src/euler/level1/bowling.clj b/src/euler/level1/bowling.clj index bd87709..7059988 100644 --- a/src/euler/level1/bowling.clj +++ b/src/euler/level1/bowling.clj @@ -5,5 +5,9 @@ (defrecord Game [frames]) (defn new-game [] (Game. [])) -(defn frame-score [frame] (:score frame)) -(defn score [game] (reduce + (map frame-score (:frames game)))) \ No newline at end of file +(defn frame-score [frame] (:score frame)) ; little sad that there can't be typed based function overloading https://github.com/ertugrulcetin/overload-fn +(defn score [game] (reduce + (map frame-score (:frames game)))) + +(defn roll [game pins] + (conj (:frames game) (Frame. pins)) + ) \ No newline at end of file From 30b1de03d695b214d4ffe92cb9d4f4e2ae6d0a41 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Fri, 31 Jan 2025 08:42:33 +0100 Subject: [PATCH 13/17] all ones --- spec/euler/level1/bowling_spec.clj | 10 +++++++--- src/euler/level1/bowling.clj | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj index 0fd2742..9f2611d 100644 --- a/spec/euler/level1/bowling_spec.clj +++ b/spec/euler/level1/bowling_spec.clj @@ -5,6 +5,10 @@ (:import (euler.level1.bowling Game)) (:import (euler.level1.bowling Frame))) +(defn roll-many [game iterations pins] + (reduce (fn [cum _] (roll cum pins)) game (range iterations)) + ) + (describe "Bowling Game" (it "The score function must iterate through all the frames, and calculate all their scores." @@ -13,14 +17,14 @@ ) (it "rolls all zeroes" - (let [game (reduce (fn [cum _] (roll cum 0) (new-game)) (range 20))] + (let [game (roll-many (new-game) 20 0)] (should= 0 (score game)) ) ) (it "rolls all ones" - (let [game (reduce (fn [cum _] (roll cum 1) (new-game)) (range 20))] - (should= 0 (score game)) + (let [game (roll-many (new-game) 20 1)] + (should= 20 (score game)) ) ) diff --git a/src/euler/level1/bowling.clj b/src/euler/level1/bowling.clj index 7059988..18cd495 100644 --- a/src/euler/level1/bowling.clj +++ b/src/euler/level1/bowling.clj @@ -9,5 +9,5 @@ (defn score [game] (reduce + (map frame-score (:frames game)))) (defn roll [game pins] - (conj (:frames game) (Frame. pins)) + (Game. (conj (:frames game) (Frame. pins))) ) \ No newline at end of file From 860e98ab90ef4e76fbcfda63a0810a00fb8b641b Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Fri, 31 Jan 2025 09:12:05 +0100 Subject: [PATCH 14/17] slide 34 --- spec/euler/level1/bowling_spec.clj | 20 +++++++++++++------- src/euler/level1/bowling.clj | 22 ++++++++++++++++++---- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj index 9f2611d..154af73 100644 --- a/spec/euler/level1/bowling_spec.clj +++ b/spec/euler/level1/bowling_spec.clj @@ -1,9 +1,7 @@ (ns euler.level1.bowling-spec (:use [speclj.core] - [euler.level1.bowling]) - (:import (euler.level1.bowling Game)) - (:import (euler.level1.bowling Frame))) + [euler.level1.bowling])) (defn roll-many [game iterations pins] (reduce (fn [cum _] (roll cum pins)) game (range iterations)) @@ -11,10 +9,6 @@ (describe "Bowling Game" - (it "The score function must iterate through all the frames, and calculate all their scores." - (should= 0 (score (new-game))) - (should= 3 (score (Game. [(Frame. 1) (Frame. 2)]))) - ) (it "rolls all zeroes" (let [game (roll-many (new-game) 20 0)] @@ -28,6 +22,18 @@ ) ) + ;(it "one spare" + ; (let [game + ; (-> (new-game) + ; (roll 5) + ; (roll 5) + ; (roll 3) + ; (roll-many 17 0) + ; )] + ; (should= 16 (score game)) + ; ) + ; ) + ) (run-specs) diff --git a/src/euler/level1/bowling.clj b/src/euler/level1/bowling.clj index 18cd495..c7d0366 100644 --- a/src/euler/level1/bowling.clj +++ b/src/euler/level1/bowling.clj @@ -2,12 +2,26 @@ (defrecord Frame [score]) -(defrecord Game [frames]) -(defn new-game [] (Game. [])) +(defrecord Game [frames current-roll]) +(defn new-game [] + (Game. + (vec + (map + (fn [_] (Frame. 0)) + (range 21))) + 0)) (defn frame-score [frame] (:score frame)) ; little sad that there can't be typed based function overloading https://github.com/ertugrulcetin/overload-fn -(defn score [game] (reduce + (map frame-score (:frames game)))) +(defn score [game] + (reduce + (map frame-score (:frames game)))) (defn roll [game pins] - (Game. (conj (:frames game) (Frame. pins))) + (Game. + (map-indexed + (fn [i frame] + (if (= (:current-roll game) i) + (Frame. (+ pins (:score frame))) + frame + )) (:frames game)), + (inc (:current-roll game))) ) \ No newline at end of file From dc06d3581ce1bdb0cd541fb56792b1663f3242c5 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Fri, 31 Jan 2025 09:23:45 +0100 Subject: [PATCH 15/17] one spare --- spec/euler/level1/bowling_spec.clj | 22 +++++++++++----------- src/euler/level1/bowling.clj | 19 +++++++++++++------ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj index 154af73..b4c6573 100644 --- a/spec/euler/level1/bowling_spec.clj +++ b/spec/euler/level1/bowling_spec.clj @@ -22,17 +22,17 @@ ) ) - ;(it "one spare" - ; (let [game - ; (-> (new-game) - ; (roll 5) - ; (roll 5) - ; (roll 3) - ; (roll-many 17 0) - ; )] - ; (should= 16 (score game)) - ; ) - ; ) + (it "one spare" + (let [game + (-> (new-game) + (roll 5) + (roll 5) + (roll 3) + (roll-many 17 0) + )] + (should= 16 (score game)) + ) + ) ) diff --git a/src/euler/level1/bowling.clj b/src/euler/level1/bowling.clj index c7d0366..46dfe10 100644 --- a/src/euler/level1/bowling.clj +++ b/src/euler/level1/bowling.clj @@ -1,26 +1,33 @@ (ns euler.level1.bowling) -(defrecord Frame [score]) - (defrecord Game [frames current-roll]) (defn new-game [] (Game. (vec (map - (fn [_] (Frame. 0)) + (fn [_] 0) (range 21))) 0)) -(defn frame-score [frame] (:score frame)) ; little sad that there can't be typed based function overloading https://github.com/ertugrulcetin/overload-fn +(defn iteration-score [frames i] + (let [consecutive-sum (+ (nth frames i) (nth frames (+ i 1)))] + (if (= consecutive-sum 10) + (+ 10 (nth frames (+ i 2))) + consecutive-sum + ) + ) + ) (defn score [game] - (reduce + (map frame-score (:frames game)))) + (reduce + + + (map (fn [i] (iteration-score (:frames game) (* 2 i))) (range 10)))) (defn roll [game pins] (Game. (map-indexed (fn [i frame] (if (= (:current-roll game) i) - (Frame. (+ pins (:score frame))) + (+ pins frame) frame )) (:frames game)), (inc (:current-roll game))) From 33c3ba8d0ec9b22bceb3a321f26b0dc580403278 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Fri, 31 Jan 2025 09:30:34 +0100 Subject: [PATCH 16/17] one spare --- spec/euler/level1/bowling_spec.clj | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj index b4c6573..faa188c 100644 --- a/spec/euler/level1/bowling_spec.clj +++ b/spec/euler/level1/bowling_spec.clj @@ -7,6 +7,13 @@ (reduce (fn [cum _] (roll cum pins)) game (range iterations)) ) +(defn roll-spare [game] + (-> game + (roll 5) + (roll 5) + ) + ) + (describe "Bowling Game" @@ -25,8 +32,7 @@ (it "one spare" (let [game (-> (new-game) - (roll 5) - (roll 5) + (roll-spare) (roll 3) (roll-many 17 0) )] From 5f5dd621ff705dc37487009c065228e5fdd8a599 Mon Sep 17 00:00:00 2001 From: Remek Zajac Date: Wed, 5 Feb 2025 14:08:48 +0100 Subject: [PATCH 17/17] problem 9 --- spec/euler/level1/bowling_spec.clj | 48 +++++++++---------------- spec/euler/level1/problem007_spec.clj | 2 +- src/euler/level1/bowling.clj | 50 +++++++++++---------------- 3 files changed, 38 insertions(+), 62 deletions(-) diff --git a/spec/euler/level1/bowling_spec.clj b/spec/euler/level1/bowling_spec.clj index faa188c..75c43e7 100644 --- a/spec/euler/level1/bowling_spec.clj +++ b/spec/euler/level1/bowling_spec.clj @@ -3,43 +3,29 @@ [speclj.core] [euler.level1.bowling])) -(defn roll-many [game iterations pins] - (reduce (fn [cum _] (roll cum pins)) game (range iterations)) - ) - -(defn roll-spare [game] - (-> game - (roll 5) - (roll 5) - ) - ) +(describe "Bowling Game " -(describe "Bowling Game" + (it "gutter game - no pins scores 0" + (should= 0 (score (repeat 0)))) + (it "all 1s - score is sum of pins" + (should= 20 (score (repeat 1)))) - (it "rolls all zeroes" - (let [game (roll-many (new-game) 20 0)] - (should= 0 (score game)) - ) - ) + (it "spare adds the next roll" + (should= 16 (score [4 6 3]))) - (it "rolls all ones" - (let [game (roll-many (new-game) 20 1)] - (should= 20 (score game)) - ) - ) + (it "strike add next two rolls" + (should= 16 (score [10 1 2]))) - (it "one spare" - (let [game - (-> (new-game) - (roll-spare) - (roll 3) - (roll-many 17 0) - )] - (should= 16 (score game)) - ) - ) + (it "perfect game - all strikes" + (should= 300 (score (repeat 10)))) + (it "->frames" + (should= [] (->frames [])) + (should= [[1]] (->frames [1])) + (should= [[1 2][3 4]] (->frames [1 2 3 4])) + (should= [[4 6 3][3]] (->frames [4 6 3])) + (should= [[10 1 2][1 2]] (->frames [10 1 2]))) ) (run-specs) diff --git a/spec/euler/level1/problem007_spec.clj b/spec/euler/level1/problem007_spec.clj index 531498d..1d44baf 100644 --- a/spec/euler/level1/problem007_spec.clj +++ b/spec/euler/level1/problem007_spec.clj @@ -24,7 +24,7 @@ (it "Solves #7" (should= 13 (euler-7 6)) - (should= 104743 (euler-7 10001)) + ;(should= 104743 (euler-7 10001)) ) ) diff --git a/src/euler/level1/bowling.clj b/src/euler/level1/bowling.clj index 46dfe10..4e49116 100644 --- a/src/euler/level1/bowling.clj +++ b/src/euler/level1/bowling.clj @@ -1,34 +1,24 @@ (ns euler.level1.bowling) -(defrecord Game [frames current-roll]) -(defn new-game [] - (Game. - (vec - (map - (fn [_] 0) - (range 21))) - 0)) +(defn sum [nums] + (reduce + nums)) -(defn iteration-score [frames i] - (let [consecutive-sum (+ (nth frames i) (nth frames (+ i 1)))] - (if (= consecutive-sum 10) - (+ 10 (nth frames (+ i 2))) - consecutive-sum - ) - ) - ) -(defn score [game] - (reduce - + - (map (fn [i] (iteration-score (:frames game) (* 2 i))) (range 10)))) +(defn spare? [rolls] + (= (sum (take 2 rolls)) 10)) -(defn roll [game pins] - (Game. - (map-indexed - (fn [i frame] - (if (= (:current-roll game) i) - (+ pins frame) - frame - )) (:frames game)), - (inc (:current-roll game))) - ) \ No newline at end of file +(defn strike? [rolls] + (= (first rolls) 10)) + +(defn ->frames [rolls] + (if (empty? rolls) + [] + (cons + (if (or (spare? rolls) (strike? rolls)) + (take 3 rolls) + (take 2 rolls)) + (lazy-seq (->frames (if (strike? rolls) + (drop 1 rolls) + (drop 2 rolls))))))) + +(defn score [rolls] + (sum (flatten (take 10 (->frames rolls))))) \ No newline at end of file