Skip to content

Instantly share code, notes, and snippets.

@tabruhn
Last active January 20, 2016 17:29
Show Gist options
  • Select an option

  • Save tabruhn/66b9e54572430e4ad15c to your computer and use it in GitHub Desktop.

Select an option

Save tabruhn/66b9e54572430e4ad15c to your computer and use it in GitHub Desktop.
Function to get correct change from a register.
/**
* Airbnb Style Guide refactor
* - set of pure composable functions for returning change of an amount from a register
* - all functions are pure, self-containing, side-effect free... enforcing the Airbnb immutable rule
* - each function is referential transparent, testable, parallelizable, cacheable
*/
/**
* takes an amount, an initial list, and a list of coins
* returns the list of change coins
* > getChange(20,[],[25,10,10,5]) // [10,10]
* > getChange(20,[],convertRegisterToList([{25:1},{10:2},{5:1}])) //[10,10]
*/
function getChange(amount, list, coins) {
if (!coins.length || !amount) {
return list;
}
const [head, ...tail] = coins;
if (head > amount) {
return getChange(amount, list, tail);
} else {
return getChange(amount - head, list.concat([head]), tail);
}
}
/**
* takes an array of coin objects and returns an array of coin values
* > converstRegisterToList([{value:25,amount:2},{value:10,amount:2},{value:5,amount:1}]) // [25,25,10,10,5]
*/
function convertRegisterToList(register){
return flatten(register.map(getCoinsList));
}
/**
* takes a list of values and returns an array of objects with counts of those values
* > getCoinObjects([25,25,10,10,5]) // [{value:25,amount:2},{value:10,amount:2},{value:5,amount:1}]
*/
function getCoinObjects(list){
return getUnique(list).map((item) => {
return {
'value' : item,
'amount': list.filter(x => x === item).length
};
});
}
/**
* > getCoinsList({value:25,amount:2}) // [25,25]
*/
function getCoinsList(coin) {
function addItemsToList(amount, item, list) {
if(amount > 0){
return addItemsToList(amount - 1, item, list.concat([item]));
} else {
return list;
}
}
// Destructure a coin object value and amount
const {value, amount} = coin;
return addItemsToList(amount, value, []);
}
/**
* Takes a list of nested lists and flattens it
* > flatten([[25,25], [10,10], [1]]) // [25,25,10,10,1]
*/
function flatten(list) {
return [].concat.apply([], list);
}
/**
* Takes two lists, the second list being a subset of the first
* returns a new list containing the difference of the two lists
* > diff([25,25,25,10,10], [25,10]) // [25,25,10]
*/
function diff(list1,list2){
if (!list2.length) {
return list1;
}
const [head, ...tail] = list2;
return diff(pluck(list1, head), tail);
}
/**
* > pluck([1,2,3],1)); //[2,3]
*/
function pluck(array, value) {
const index = array.indexOf(value);
if (index !== -1) {
return [...array.slice(0, index), ...array.slice(index + 1)];
}
return array;
}
/**
* Takes a list and returns only the unique values of that list
* > getUnique([25,25,10,10,5]) // [25,10,5]
*/
function getUnique (list) {
return [...new Set(list)];
}
/**
* sums a set of numbers
* > sum([25,25,10,10,5]) //75
*/
function sum (list) {
return list.reduce((previous, current) => {
return previous + current;
}, 0);
}
/**
* Example usage
*/
// add values to the register
const register = [{value:25, amount:2},{value:10, amount:2},{value:5, amount:5}];
// amount to return in change
const amt = 55;
console.log('Return coins of value ',amt,'from',JSON.stringify(register));
const change = getChange(amt,[],convertRegisterToList(register));
console.log('Coins returned:', JSON.stringify(getCoinObjects(change)));
console.log('Remaining register:', JSON.stringify(getCoinObjects(diff(convertRegisterToList(register), change))));
console.log('Registers remaining value:', sum(diff(convertRegisterToList(register), change)));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment