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

Commit

Permalink
Add change exercise (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikSchierboom authored May 6, 2023
1 parent 6fc89ae commit c05c504
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 2 deletions.
15 changes: 13 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@
"uuid": "c895c0f5-0fe5-4ce1-a3a9-b6cd911d9275",
"practices": [],
"prerequisites": [
"lists",
"lists",
"numbers",
"strings"
],
Expand Down Expand Up @@ -394,7 +394,7 @@
],
"difficulty": 2
},
{
{
"slug": "acronym",
"name": "Acronym",
"uuid": "e6147a0d-3000-4b3c-9a60-3f8800730691",
Expand Down Expand Up @@ -584,6 +584,17 @@
"conditionals"
],
"difficulty": 2
},
{
"slug": "change",
"name": "Change",
"uuid": "e1e76dc4-543f-4d1e-8727-a726ee5291ec",
"practices": [],
"prerequisites": [
"numbers",
"vectors"
],
"difficulty": 3
}
]
},
Expand Down
14 changes: 14 additions & 0 deletions exercises/practice/change/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Instructions

Correctly determine the fewest number of coins to be given to a customer such that the sum of the coins' value would equal the correct amount of change.

## For example

- An input of 15 with [1, 5, 10, 25, 100] should return one nickel (5) and one dime (10) or [5, 10]
- An input of 40 with [1, 5, 10, 25, 100] should return one nickel (5) and one dime (10) and one quarter (25) or [5, 10, 25]

## Edge cases

- Does your algorithm work for any given set of coins?
- Can you ask for negative change?
- Can you ask for a change value smaller than the smallest coin value?
19 changes: 19 additions & 0 deletions exercises/practice/change/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"ErikSchierboom"
],
"files": {
"solution": [
"src/change.cljs"
],
"test": [
"test/change_test.cljs"
],
"example": [
".meta/src/example.cljs"
]
},
"blurb": "Correctly determine change to be given using the least number of coins.",
"source": "Software Craftsmanship - Coin Change Kata",
"source_url": "https://web.archive.org/web/20130115115225/http://craftsmanship.sv.cmu.edu:80/exercises/coin-change-kata"
}
24 changes: 24 additions & 0 deletions exercises/practice/change/.meta/src/example.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
(ns change)

(def algo
(memoize (fn [amount coins]
(let [smaller (filter #(<= % amount) coins)]
(if (empty? smaller) [amount]
(apply min-key
count
; check if valid solution, i.e. the final amount was zero
(filter (comp zero? first)
(map
(fn [coin]
(concat
(algo (rem amount coin) smaller)
(repeat (quot amount coin) coin)))
smaller))))))))

(defn issue [amount coins]
(try
(let [[x & xs] (algo amount coins)]
(if (zero? x) xs
(throw (new js/Error "cannot change"))))
; thrown by apply min-key if we don't have the right coins to issue change
(catch clojure.lang.ArityException e (throw (new js/Error "cannot change")))))
36 changes: 36 additions & 0 deletions exercises/practice/change/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 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.

[36887bea-7f92-4a9c-b0cc-c0e886b3ecc8]
description = "single coin change"

[cef21ccc-0811-4e6e-af44-f011e7eab6c6]
description = "multiple coin change"

[d60952bc-0c1a-4571-bf0c-41be72690cb3]
description = "change with Lilliputian Coins"

[408390b9-fafa-4bb9-b608-ffe6036edb6c]
description = "change with Lower Elbonia Coins"

[7421a4cb-1c48-4bf9-99c7-7f049689132f]
description = "large target values"

[f79d2e9b-0ae3-4d6a-bb58-dc978b0dba28]
description = "possible change without unit coins available"

[9a166411-d35d-4f7f-a007-6724ac266178]
description = "another possible change without unit coins available"

[bbbcc154-e9e9-4209-a4db-dd6d81ec26bb]
description = "no coins make 0 change"

[c8b81d5a-49bd-4b61-af73-8ee5383a2ce1]
description = "error testing for change smaller than the smallest of coins"

[3c43e3e4-63f9-46ac-9476-a67516e98f68]
description = "error if no combination can add up to target"

[8fe1f076-9b2d-4f44-89fe-8a6ccd63c8f3]
description = "cannot find negative change values"
10 changes: 10 additions & 0 deletions exercises/practice/change/deps.edn
Original file line number Diff line number Diff line change
@@ -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"]}}}
5 changes: 5 additions & 0 deletions exercises/practice/change/src/change.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(ns change)

(defn issue [] ;; <- arglist goes here
;; your code goes here
)
38 changes: 38 additions & 0 deletions exercises/practice/change/test/change_test.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
(ns change-test
(:require [clojure.test :refer [deftest is]]
[change :refer [issue]]))

(deftest single-coin-change
(is (= (issue 25 #{1 5 10 25 100})
'(25))))

(deftest multiple-coin-change
(is (= (issue 15 #{1 5 10 25 100})
'(5 10))))

(deftest change-with-lilliputian-coins
(is (= (issue 23 #{1 4 15 20 50})
'(4 4 15))))

(deftest change-with-elbonia-coins
(is (= (issue 63 #{1 5 10 21 25})
'(21 21 21))))

(deftest large-target-values
(is (= (issue 999 #{1 2 5 10 20 50 100})
'(2 2 5 20 20 50 100 100 100 100 100 100 100 100 100))))

(deftest no-coins-make-zero-change
(is (empty? (issue 0 #{1, 5, 10, 21, 25}))))

(deftest error-testing-for-change-smallet-than-the-smallest-coin
(is (thrown? js/Error #"cannot change"
(issue 3 #{5 10}))))

(deftest cannot-find-negative-change-values
(is (thrown? js/Error #"cannot change"
(issue -5 #{1 2 5}))))

(deftest error-testing-for-no-valid-change
(is (thrown? js/Error #"cannot change"
(issue 10 #{20 8 3}))))

0 comments on commit c05c504

Please sign in to comment.