Skip to content

Commit b546023

Browse files
authored
Add change (#345)
1 parent f02c21a commit b546023

File tree

8 files changed

+236
-0
lines changed

8 files changed

+236
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,14 @@
635635
"strings"
636636
]
637637
},
638+
{
639+
"slug": "change",
640+
"name": "Change",
641+
"uuid": "25347375-b351-4206-9f6e-bb0e28dd1fb9",
642+
"practices": [],
643+
"prerequisites": [],
644+
"difficulty": 5
645+
},
638646
{
639647
"slug": "circular-buffer",
640648
"name": "Circular Buffer",
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Instructions
2+
3+
Determine the fewest number of coins to give a customer so that the sum of their values equals the correct amount of change.
4+
5+
## Examples
6+
7+
- An amount of 15 with available coin values [1, 5, 10, 25, 100] should return one coin of value 5 and one coin of value 10, or [5, 10].
8+
- An amount of 40 with available coin values [1, 5, 10, 25, 100] should return one coin of value 5, one coin of value 10, and one coin of value 25, or [5, 10, 25].
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Introduction
2+
3+
In the mystical village of Coinholt, you stand behind the counter of your bakery, arranging a fresh batch of pastries.
4+
The door creaks open, and in walks Denara, a skilled merchant with a keen eye for quality goods.
5+
After a quick meal, she slides a shimmering coin across the counter, representing a value of 100 units.
6+
7+
You smile, taking the coin, and glance at the total cost of the meal: 88 units.
8+
That means you need to return 12 units in change.
9+
10+
Denara holds out her hand expectantly.
11+
"Just give me the fewest coins," she says with a smile.
12+
"My pouch is already full, and I don't want to risk losing them on the road."
13+
14+
You know you have a few options.
15+
"We have Lumis (worth 10 units), Viras (worth 5 units), and Zenth (worth 2 units) available for change."
16+
17+
You quickly calculate the possibilities in your head:
18+
19+
- one Lumis (1 × 10 units) + one Zenth (1 × 2 units) = 2 coins total
20+
- two Viras (2 × 5 units) + one Zenth (1 × 2 units) = 3 coins total
21+
- six Zenth (6 × 2 units) = 6 coins total
22+
23+
"The best choice is two coins: one Lumis and one Zenth," you say, handing her the change.
24+
25+
Denara smiles, clearly impressed.
26+
"As always, you've got it right."
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"BNAndras"
4+
],
5+
"files": {
6+
"solution": [
7+
"change.vim"
8+
],
9+
"test": [
10+
"change.vader"
11+
],
12+
"example": [
13+
".meta/example.vim"
14+
]
15+
},
16+
"blurb": "Correctly determine change to be given using the least number of coins.",
17+
"source": "Software Craftsmanship - Coin Change Kata",
18+
"source_url": "https://web.archive.org/web/20130115115225/http://craftsmanship.sv.cmu.edu:80/exercises/coin-change-kata"
19+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
function! FindFewestCoins(coins, target_balance) abort
2+
if a:target_balance < 0
3+
throw "target can't be negative"
4+
endif
5+
6+
if a:target_balance == 0
7+
return []
8+
endif
9+
10+
let l:available_coins = sort(a:coins, {a, b -> b - a})
11+
12+
let l:queue = [0]
13+
let l:visited = {0: []}
14+
15+
while !empty(l:queue)
16+
let l:starting_balance = remove(l:queue, 0)
17+
18+
for l:coin in l:available_coins
19+
let l:updated_balance = l:starting_balance + l:coin
20+
21+
if l:updated_balance > a:target_balance || has_key(l:visited, l:updated_balance)
22+
continue
23+
endif
24+
25+
let l:used_coins = copy(l:visited[l:starting_balance])
26+
call add(l:used_coins, l:coin)
27+
call sort(l:used_coins, {a, b -> b - a})
28+
29+
if l:updated_balance == a:target_balance
30+
return sort(l:used_coins, 'n')
31+
endif
32+
33+
let l:visited[l:updated_balance] = l:used_coins
34+
35+
call add(l:queue, l:updated_balance)
36+
endfor
37+
endwhile
38+
39+
throw "can't make target with given coins"
40+
endfunction
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[d0ebd0e1-9d27-4609-a654-df5c0ba1d83a]
13+
description = "change for 1 cent"
14+
15+
[36887bea-7f92-4a9c-b0cc-c0e886b3ecc8]
16+
description = "single coin change"
17+
18+
[cef21ccc-0811-4e6e-af44-f011e7eab6c6]
19+
description = "multiple coin change"
20+
21+
[d60952bc-0c1a-4571-bf0c-41be72690cb3]
22+
description = "change with Lilliputian Coins"
23+
24+
[408390b9-fafa-4bb9-b608-ffe6036edb6c]
25+
description = "change with Lower Elbonia Coins"
26+
27+
[7421a4cb-1c48-4bf9-99c7-7f049689132f]
28+
description = "large target values"
29+
30+
[f79d2e9b-0ae3-4d6a-bb58-dc978b0dba28]
31+
description = "possible change without unit coins available"
32+
33+
[9a166411-d35d-4f7f-a007-6724ac266178]
34+
description = "another possible change without unit coins available"
35+
36+
[ce0f80d5-51c3-469d-818c-3e69dbd25f75]
37+
description = "a greedy approach is not optimal"
38+
39+
[bbbcc154-e9e9-4209-a4db-dd6d81ec26bb]
40+
description = "no coins make 0 change"
41+
42+
[c8b81d5a-49bd-4b61-af73-8ee5383a2ce1]
43+
description = "error testing for change smaller than the smallest of coins"
44+
45+
[3c43e3e4-63f9-46ac-9476-a67516e98f68]
46+
description = "error if no combination can add up to target"
47+
48+
[8fe1f076-9b2d-4f44-89fe-8a6ccd63c8f3]
49+
description = "cannot find negative change values"
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
Execute (change for 1 cent):
2+
let g:coins = [1, 5, 10, 25]
3+
let g:target = 1
4+
let g:expected = [1]
5+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
6+
7+
Execute (single coin change):
8+
let g:coins = [1, 5, 10, 25, 100]
9+
let g:target = 25
10+
let g:expected = [25]
11+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
12+
13+
Execute (multiple coin change):
14+
let g:coins = [1, 5, 10, 25, 100]
15+
let g:target = 15
16+
let g:expected = [5, 10]
17+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
18+
19+
Execute (change with Lilliputian Coins):
20+
let g:coins = [1, 4, 15, 20, 50]
21+
let g:target = 23
22+
let g:expected = [4, 4, 15]
23+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
24+
25+
Execute (change with Lower Elbonia Coins):
26+
let g:coins = [1, 5, 10, 21, 25]
27+
let g:target = 63
28+
let g:expected = [21, 21, 21]
29+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
30+
31+
Execute (large target values):
32+
let g:coins = [1, 2, 5, 10, 20, 50, 100]
33+
let g:target = 999
34+
let g:expected = [2, 2, 5, 20, 20, 50, 100, 100, 100, 100, 100, 100, 100, 100, 100]
35+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
36+
37+
Execute (possible change without unit coins available):
38+
let g:coins = [2, 5, 10, 20, 50]
39+
let g:target = 21
40+
let g:expected = [2, 2, 2, 5, 10]
41+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
42+
43+
Execute (another possible change without unit coins available):
44+
let g:coins = [4, 5]
45+
let g:target = 27
46+
let g:expected = [4, 4, 4, 5, 5, 5]
47+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
48+
49+
Execute (a greedy approach is not optimal):
50+
let g:coins = [1, 10, 11]
51+
let g:target = 20
52+
let g:expected = [10, 10]
53+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
54+
55+
Execute (no coins make 0 change):
56+
let g:coins = [1, 5, 10, 21, 25]
57+
let g:target = 0
58+
let g:expected = []
59+
AssertEqual g:expected, FindFewestCoins(g:coins, g:target)
60+
61+
Execute (error testing for change smaller than the smallest of coins):
62+
let g:coins = [5, 10]
63+
let g:target = 3
64+
let g:expected = "can't make target with given coins"
65+
AssertThrows call FindFewestCoins(g:coins, g:target)
66+
AssertEqual g:expected, g:vader_exception
67+
68+
Execute (error if no combination can add up to target):
69+
let g:coins = [5, 10]
70+
let g:target = 94
71+
let g:expected = "can't make target with given coins"
72+
AssertThrows call FindFewestCoins(g:coins, g:target)
73+
AssertEqual g:expected, g:vader_exception
74+
75+
Execute (cannot find negative change values):
76+
let g:coins = [1, 2, 5]
77+
let g:target = -5
78+
let g:expected = "target can't be negative"
79+
AssertThrows call FindFewestCoins(g:coins, g:target)
80+
AssertEqual g:expected, g:vader_exception

exercises/practice/change/change.vim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"
2+
" Return the fewest number of available coins needed to equal the target.
3+
"
4+
function! FindFewestCoins(coins, target) abort
5+
" your solution goes here
6+
endfunction

0 commit comments

Comments
 (0)