Skip to content

Instantly share code, notes, and snippets.

@atcruice
Forked from rjchatfield/change_problem.coffee
Last active August 29, 2015 14:10
Show Gist options
  • Save atcruice/799a13854c1d97dd673d to your computer and use it in GitHub Desktop.
Save atcruice/799a13854c1d97dd673d to your computer and use it in GitHub Desktop.
#
# FP solve the Change Problem
# eg. myChange = calcChange(cost, myPayment)
#
# Used in fold() to build change object
# Should be nested in calcChange, but is lifted for cleanliness
coinAccStructure = (acc, coinValue) ->
amountRemaining = acc["remaining"]
acc[coinValue] = Math.floor(amountRemaining / coinValue)
acc["remaining"] = amountRemaining - (acc[coinValue] * coinValue)
acc
# Curried calculator
calcChange = (coins) -> (cost, payment) ->
coins.reduce(coinAccStructure, {"remaining": payment - cost})
AUDinCents = (AUDamount) ->
Math.floor(AUDamount * 100)
# Initalisated calculator for Australian coins
AUDCoinsAsCents = (AUDinCents(coin) for coin in [2, 1, .5, .2, .1, .05])
calcAUDChange = calcChange(AUDCoinsAsCents)
# Use
cost = 5.20
payment = 10.00
AUDcost = AUDinCents cost
AUDpayment = AUDinCents payment
change = calcAUDChange(AUDcost, AUDpayment) if AUDcost <= AUDpayment
delete change.remaining if change?
@atcruice
Copy link
Author

atcruice commented Dec 7, 2014

In general I avoid floating-point math as much as possible.

Further ideas:

  • I dislike how the coinValue keys are in cents that only has meaning when understood as AUD, calls for a cleaner currency abstraction that would behave like a lens over integer values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment