Skip to content

Instantly share code, notes, and snippets.

@caelifer caelifer/change.go
Last active Dec 10, 2019

Embed
What would you like to do?
Calculate change from available pool of coins simulating automatic cash register.
package main
import (
"fmt"
"log"
"strings"
)
func main() {
b := NewBank(map[Coin]int{
Penny: 100,
Nickle: 20,
Dime: 10,
Quater: 2,
})
fmt.Printf("Started with money in the bank: %v\n", b)
fmt.Println("Start dispensing change")
fmt.Println()
for _, v := range []int{3, 5, 10, 17, 23, 25, 41, 91, 99, 50} {
fmt.Printf("Requesting change of %d cents\n", v)
fmt.Printf("Dispensed coins: %s\n", b.DispenseCoins(v))
fmt.Printf("Money in the bank: %s\n", b)
fmt.Println()
}
}
type Coin int
const (
Penny Coin = 1
Nickle = 5
Dime = 10
Quater = 25
)
func (c Coin) singular() string {
switch c {
case Penny:
return "penny"
case Nickle:
return "nickle"
case Dime:
return "dime"
case Quater:
return "quater"
}
return "unknown coin"
}
func (c Coin) plural() string {
switch c {
case Penny:
return "pennies"
default:
return c.singular() + "s"
}
}
type CoinStack struct {
Type Coin
Count int
}
func (cs CoinStack) Value() int {
return int(cs.Type) * cs.Count
}
func (cs *CoinStack) Get(amount int) (*CoinStack, int) {
needCoins := amount / int(cs.Type)
balance := amount % int(cs.Type)
if needCoins > cs.Count {
defficit := needCoins - cs.Count
balance += defficit * int(cs.Type)
needCoins, cs.Count = cs.Count, 0
} else {
cs.Count -= needCoins
}
if cs.Count == 0 {
log.Printf("out of %s", cs.Type.plural())
}
return &CoinStack{Type: cs.Type, Count: needCoins}, balance
}
func (cs CoinStack) String() string {
denom := cs.Type.plural
if cs.Count == 1 {
denom = cs.Type.singular
}
return fmt.Sprintf("%d %s", cs.Count, denom())
}
type Bank struct {
Store [4]*CoinStack
}
func NewBank(money map[Coin]int) *Bank {
bank := new(Bank)
// Transfer coins into bank
for i, c := range []Coin{Quater, Dime, Nickle, Penny} {
if count, ok := money[c]; ok {
bank.Store[i] = &CoinStack{Type: c, Count: count}
}
}
return bank
}
func (b *Bank) DispenseCoins(amount int) string {
res := make([]string, 0, 4)
for _, cs := range b.Store[:] {
if cs.Count == 0 {
continue
}
var coins *CoinStack
coins, amount = cs.Get(amount)
if coins.Count > 0 {
res = append(res, coins.String())
}
if amount == 0 {
break
}
}
if amount > 0 {
log.Fatalf("Not enough coins to make change on %d cents balance", amount)
}
return strings.Join(res, ", ")
}
func (b Bank) String() string {
res := make([]string, 0, 4)
val := 0
for _, cs := range b.Store[:] {
val += cs.Value()
res = append(res, cs.String())
}
return fmt.Sprintf("%.2f dollars [%v]", float64(val)/100, strings.Join(res, ", "))
}
@caelifer

This comment has been minimized.

Copy link
Owner Author

caelifer commented Dec 10, 2019

Live code - https://play.golang.org/p/SrQkFRmRzgC

Output:

Started with money in the bank: 3.50 dollars [2 quaters, 10 dimes, 20 nickles, 100 pennies]
Start dispensing change

Requesting change of 3 cents
Dispensed coins: 3 pennies
Money in the bank: 3.47 dollars [2 quaters, 10 dimes, 20 nickles, 97 pennies]

Requesting change of 5 cents
Dispensed coins: 1 nickle
Money in the bank: 3.42 dollars [2 quaters, 10 dimes, 19 nickles, 97 pennies]

Requesting change of 10 cents
Dispensed coins: 1 dime
Money in the bank: 3.32 dollars [2 quaters, 9 dimes, 19 nickles, 97 pennies]

Requesting change of 17 cents
Dispensed coins: 1 dime, 1 nickle, 2 pennies
Money in the bank: 3.15 dollars [2 quaters, 8 dimes, 18 nickles, 95 pennies]

Requesting change of 23 cents
Dispensed coins: 2 dimes, 3 pennies
Money in the bank: 2.92 dollars [2 quaters, 6 dimes, 18 nickles, 92 pennies]

Requesting change of 25 cents
Dispensed coins: 1 quater
Money in the bank: 2.67 dollars [1 quater, 6 dimes, 18 nickles, 92 pennies]

Requesting change of 41 cents
2009/11/10 23:00:00 out of quaters
Dispensed coins: 1 quater, 1 dime, 1 nickle, 1 penny
Money in the bank: 2.26 dollars [0 quaters, 5 dimes, 17 nickles, 91 pennies]

Requesting change of 91 cents
2009/11/10 23:00:00 out of dimes
Dispensed coins: 5 dimes, 8 nickles, 1 penny
Money in the bank: 1.35 dollars [0 quaters, 0 dimes, 9 nickles, 90 pennies]

Requesting change of 99 cents
2009/11/10 23:00:00 out of nickles
Dispensed coins: 9 nickles, 54 pennies
Money in the bank: 0.36 dollars [0 quaters, 0 dimes, 0 nickles, 36 pennies]

Requesting change of 50 cents
2009/11/10 23:00:00 out of pennies
2009/11/10 23:00:00 Not enough coins to make change on 14 cents balance
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.