Skip to content
This repository has been archived by the owner on May 30, 2023. It is now read-only.

Add Practise Exercise Largest Series Product. #74

Closed
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions exercises/practice/dominoes/.docs/instructions.md
@@ -0,0 +1,15 @@
# Instructions

Make a chain of dominoes.

Compute a way to order a given set of dominoes in such a way that they form a
correct domino chain (the dots on one half of a stone match the dots on the
neighbouring half of an adjacent stone) and that dots on the halves of the
stones which don't have a neighbour (the first and last stone) match each other.

For example given the stones `[2|1]`, `[2|3]` and `[1|3]` you should compute something
like `[1|2] [2|3] [3|1]` or `[3|2] [2|1] [1|3]` or `[1|3] [3|2] [2|1]` etc, where the first and last numbers are the same.

For stones `[1|2]`, `[4|1]` and `[2|3]` the resulting chain is not valid: `[4|1] [1|2] [2|3]`'s first and last numbers are not the same. 4 != 3

Some test cases may use duplicate stones in a chain solution, assume that multiple Domino sets are being used.
19 changes: 19 additions & 0 deletions exercises/practice/dominoes/.meta/config.json
@@ -0,0 +1,19 @@
{
"blurb": "Make a chain of dominoes.",
"authors": [
"LeaveNhA"
],
"contributors": [
],
"files": {
"solution": [
"src/dominoes.cljs"
],
"test": [
"test/dominoes_test.cljs"
],
"example": [
".meta/src/example.cljs"
]
}
}
20 changes: 20 additions & 0 deletions exercises/practice/dominoes/.meta/src/example.cljs
@@ -0,0 +1,20 @@
(ns dominoes)

(defn rm [xs x]
(let [i (.indexOf xs x)]
(if (= -1 i) xs (vec (concat (take i xs) (drop (inc i) xs))))))

(defn connects [[a b] [c d]]
(cond (= b c) [c d]
(= b d) [d c]
:else nil))

(defn backtrack [rem chain]
(or (and (empty? rem) (= (ffirst chain) (second (peek chain))))
(and (not (empty? rem))
(some #(let [c (connects (peek chain) %)]
(and c (backtrack (rm rem %) (conj chain c))))
rem))))

(defn can-chain? [xs]
(or (empty? xs) (some #(backtrack (rm xs %) [%]) xs)))
39 changes: 39 additions & 0 deletions exercises/practice/dominoes/.meta/tests.toml
@@ -0,0 +1,39 @@
# This is an auto-generated file. Regular comments will be removed when this
# file is regenerated. Regenerating will not touch any manually added keys,
# so comments can be added in a "comment" key.

[31a673f2-5e54-49fe-bd79-1c1dae476c9c]
description = "empty input = empty output"

[4f99b933-367b-404b-8c6d-36d5923ee476]
description = "singleton input = singleton output"

[91122d10-5ec7-47cb-b759-033756375869]
description = "singleton that can't be chained"

[be8bc26b-fd3d-440b-8e9f-d698a0623be3]
description = "three elements"

[99e615c6-c059-401c-9e87-ad7af11fea5c]
description = "can reverse dominoes"

[51f0c291-5d43-40c5-b316-0429069528c9]
description = "can't be chained"

[9a75e078-a025-4c23-8c3a-238553657f39]
description = "disconnected - simple"

[0da0c7fe-d492-445d-b9ef-1f111f07a301]
description = "disconnected - double loop"

[b6087ff0-f555-4ea0-a71c-f9d707c5994a]
description = "disconnected - single isolated"

[2174fbdc-8b48-4bac-9914-8090d06ef978]
description = "need backtrack"

[167bb480-dfd1-4318-a20d-4f90adb4a09f]
description = "separate loops"

[cd061538-6046-45a7-ace9-6708fe8f6504]
description = "nine elements"
10 changes: 10 additions & 0 deletions exercises/practice/dominoes/deps.edn
@@ -0,0 +1,10 @@
{:deps
{org.clojure/clojure {:mvn/version "1.10.1"}
org.clojure/clojurescript {:mvn/version "1.10.773"}}

:aliases
{:test
{:extra-paths ["test"]
:extra-deps
{olical/cljs-test-runner {:mvn/version "3.8.0"}}
:main-opts ["-m" "cljs-test-runner.main"]}}}
3 changes: 3 additions & 0 deletions exercises/practice/dominoes/src/dominoes.cljs
@@ -0,0 +1,3 @@
(ns dominoes)

(defn can-chain? [])
39 changes: 39 additions & 0 deletions exercises/practice/dominoes/test/dominoes_test.cljs
@@ -0,0 +1,39 @@
(ns dominoes-test
(:require [dominoes :refer [can-chain?]]
[cljs.test :refer [deftest testing is] :as t :include-macros true]))

(deftest empty-input-empty-output
(is (can-chain? [])))

(deftest singleton-input-singleton-output
(is (can-chain? [[1 1]])))

(deftest singleton-that-cant-be-chained
(is ((comp not can-chain?) [[1 2]])))

(deftest three-elements
(is (can-chain? [[1 2] [3 1] [2 3]])))

(deftest can-reverse-dominoes
(is (can-chain? [[1 2] [1 3] [2 3]])))

(deftest cant-be-chained
(is ((comp not can-chain?) [[1 2] [4 1] [2 3]])))

(deftest disconnected-simple
(is ((comp not can-chain?) [[1 1] [2 2]])))

(deftest disconnected-double-loop
(is ((comp not can-chain?) [[1 2] [2 1] [3 4] [4 3]])))

(deftest disconnected-single-isolated
(is ((comp not can-chain?) [[1 2] [2 3] [3 1] [4 4]])))

(deftest need-backtrack
(is (can-chain? [[1 2] [2 3] [3 1] [2 4] [2 4]])))

(deftest separate-loops
(is (can-chain? [[1 2] [2 3] [3 1] [1 1] [2 2] [3 3]])))

(deftest nine-elements
(is (can-chain? [[1 2] [5 3] [3 1] [1 2] [2 4] [1 6] [2 3] [3 4] [5 6]])))
14 changes: 14 additions & 0 deletions exercises/practice/largest-series-product/.docs/instructions.md
@@ -0,0 +1,14 @@
# Instructions

Given a string of digits, calculate the largest product for a contiguous
substring of digits of length n.

For example, for the input `'1027839564'`, the largest product for a
series of 3 digits is 270 (9 * 5 * 6), and the largest product for a
series of 5 digits is 7560 (7 * 8 * 3 * 9 * 5).

Note that these series are only required to occupy *adjacent positions*
in the input; the digits need not be *numerically consecutive*.

For the input `'73167176531330624919225119674426574742355349194934'`,
the largest product for a series of 6 digits is 23520.
21 changes: 21 additions & 0 deletions exercises/practice/largest-series-product/.meta/config.json
@@ -0,0 +1,21 @@
{
"blurb": "Given a string of digits, calculate the largest product for a contiguous substring of digits of length n.",
"authors": [
"LeaveNhA"
],
"contributors": [
],
"files": {
"solution": [
"src/largest_series_product.cljs"
],
"test": [
"test/largest_series_product_test.cljs"
],
"example": [
".meta/src/example.cljs"
]
},
"source": "A variation on Problem 8 at Project Euler",
"source_url": "http://projecteuler.net/problem=8"
}
20 changes: 20 additions & 0 deletions exercises/practice/largest-series-product/.meta/src/example.cljs
@@ -0,0 +1,20 @@
(ns largest-series-product)

(defn- digits->numbers
[digits]
(map int digits))

(defn- slices [n ds] (partition n 1 (digits->numbers ds)))

(def valid (into #{} "0123456789"))

(defn largest-product [size ds]
{:pre [(not (neg? size))
(>= (count ds) size)
(every? #(valid %) ds)]}
(cond
(and (pos? size)
(empty? ds)) (throw (new js/Error "Empty string is not allowed."))
(zero? size) 1
(> size (count ds)) (throw (new js/Error "Span must not exceed length."))
:else (apply max (map (partial apply *) (slices size ds)))))
10 changes: 10 additions & 0 deletions exercises/practice/largest-series-product/deps.edn
@@ -0,0 +1,10 @@
{:deps
{org.clojure/clojure {:mvn/version "1.10.1"}
org.clojure/clojurescript {:mvn/version "1.10.773"}}

:aliases
{:test
{:extra-paths ["test"]
:extra-deps
{olical/cljs-test-runner {:mvn/version "3.8.0"}}
:main-opts ["-m" "cljs-test-runner.main"]}}}
@@ -0,0 +1,3 @@
(ns largest-series-product)

(defn largest-product [])
@@ -0,0 +1,45 @@
(ns largest-series-product-test
(:require [largest-series-product :as lsp]
[cljs.test :refer [deftest testing is] :as t :include-macros true]))

(deftest largest-series-tests
(testing "can find the largest product of 2 with numbers in order"
(is (= 72 (lsp/largest-product 2 "0123456789"))))
(testing "can find the largest product of 2"
(is (= 48 (lsp/largest-product 2 "576802143"))))
(testing "finds the largest product if span equals length"
(is (= 18 (lsp/largest-product 2 "29"))))
(testing "can find the largest product of 3 with numbers in order"
(is (= 504 (lsp/largest-product 3 "0123456789"))))
(testing "can find the largest product of 3"
(is (= 270 (lsp/largest-product 3 "1027839564"))))
(testing "can find the largest product of 5 with numbers in order"
(is (= 15120 (lsp/largest-product 5 "0123456789"))))
(testing "can get the largest product of a big number"
(is (= 23520
(let [ds "73167176531330624919225119674426574742355349194934"]
(lsp/largest-product 6 ds)))))
(testing "can get the largest product of a big number II"
(is (= 28350
(let [ds "52677741234314237566414902593461595376319419139427"]
(lsp/largest-product 6 ds)))))
(testing "can get the largest product of a big number (Project Euler)"
(is (= 23514624000
(let [ds "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"]
(lsp/largest-product 13 ds)))))
(testing "reports zero if the only digits are zero"
(is (= 0 (lsp/largest-product 2 "0000"))))
(testing "reports zero if all spans include zero"
(is (= 0 (lsp/largest-product 3 "99099"))))
(testing "rejects span longer than string length"
(is (thrown? js/Error (lsp/largest-product 4 "123"))))
(testing "reports 1 for empty string and empty product (0 span)"
(is (= 1 (lsp/largest-product 0 ""))))
(testing "reports 1 for nonempty string and empty product (0 span)"
(is (= 1 (lsp/largest-product 0 "123"))))
(testing "rejects empty string and nonzero span"
(is (thrown? js/Error (lsp/largest-product 1 ""))))
(testing "rejects invalid character in digits"
(is (thrown? js/Error (lsp/largest-product 2 "1234a5"))))
(testing "rejects negative span"
(is (thrown? js/Error (lsp/largest-product -1 "12345")))))