Last active
August 29, 2015 14:04
-
-
Save remydagostino/f03113c6852bfaa1ad31 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Functional Programming makes you look like a mad man | |
* Exhibit A. | |
* I define 23 helper functions so that I can write my solution point-free style | |
* - Remy D'Agostino | |
*/ | |
// :: a -> b -> bool | |
var eq = autocurry(function(a, b) { return a === b; }); | |
// :: a -> b -> bool | |
var and = autocurry(function(a, b) { return a && b; }); | |
// :: a -> a | |
var id = function(a) { return a; }; | |
// :: num -> num -> bool | |
var gte = autocurry(function(a, b) { return b >= a; }); | |
// :: num -> num -> num | |
var add = autocurry(function(a, b) { return a + b; }); | |
// :: num -> num -> num | |
var subtract = autocurry(function(a, b) { return a - b; }); | |
// :: num -> num -> num | |
var modulo = autocurry(function(a, b) { return b % a; }); | |
// :: a -> (-> a) | |
var constant = id.bind.bind(null, null); | |
// :: string -> object -> a | |
var dot = autocurry(function(k, v) { return v[k]; }); | |
// :: object -> string -> a | |
var lookup = autocurry(function(v, k) { return v[k]; }); | |
// :: (a -> b -> a) -> a -> [b] -> [a] | |
var reduce = autocurry(function(f, v, a) { | |
return a.reduce(function(m, x) { return f(m,x); }, v); | |
}); | |
// :: (a -> b) -> [a] -> [b] | |
var map = autocurry(function(f, a) { return a.map(function(v) { return f(v); }); }); | |
// :: [a] -> int | |
var arrLength = dot('length'); | |
// :: [a] -> int | |
var max = function(arr) { return reduce(Math.max, 0, arr); }; | |
// :: (a -> bool) -> [a] -> bool | |
var every = autocurry(function(f, a) { | |
return reduce(function(m, v) { return m && f(v); }, true, a); | |
}); | |
// :: (b -> c) -> (a -> b) -> (a -> c) | |
var compose = autocurry(function(f1, f2) { | |
return function(v) { | |
return f1(f2(v)); | |
}; | |
}); | |
// :: a -> int -> [a] -> [a] | |
var padLeft = autocurry(function(item, length, arr) { | |
return arrayRepeat(item, length - arr.length).concat(arr); | |
}); | |
// :: a -> [a] -> [a] | |
var trimLeft = autocurry(function(item, arr) { | |
if (arr[0] !== item) { | |
return arr; | |
} | |
return trimLeft(item, arr.slice(1)); | |
}); | |
// :: a -> int -> [a] | |
var arrayRepeat = autocurry(function(item, length) { | |
if (length <= 0) { return []; } | |
return [item].concat(arrayRepeat(item, length - 1)); | |
}); | |
// :: [a] -> [a] -> (a -> a -> b) -> [b] | |
var zipWith = autocurry(function(fn, first, second) { | |
return first.reduce(function(memo, v, i) { | |
return memo.concat(fn(v, second[i])); | |
}, []); | |
}); | |
// :: num -> num -> num -> {num, num} | |
var sumWithCarry = autocurry(function(base, a, b) { | |
return { | |
sum : (a + b) % base, | |
carry: (a + b) >= base ? 1 : 0 | |
}; | |
}); | |
/// CURRY | |
function curry(fn) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
return function () { | |
return fn.apply(fn, args.concat(Array.prototype.slice.call(arguments))); | |
}; | |
} | |
function autocurry(fn, numArgs) { | |
var expectedArgs = numArgs || fn.length; | |
return function () { | |
if (arguments.length < expectedArgs) { | |
// A curried version of fn | |
var curried = curry.apply(this, [fn].concat(Array.prototype.slice.call(arguments))); | |
var rem = numArgs - arguments.length; | |
// If we still don't have the expected number of arguments then return | |
return expectedArgs - arguments.length > 0 ? autocurry(curried, rem) : curried; | |
} | |
else { | |
return fn.apply(this, arguments); | |
} | |
}; | |
} | |
/** | |
* Add Array Numbers | |
* | |
* 654 + 59 = 713 | |
* addArrayNumbers([6, 5, 4], [5, 9]) // [7, 1, 3]; | |
* | |
* @param {Array} first | |
* @param {Array} second | |
* @return {Array} | |
*/ | |
function addArrayNumbers(first, second) { | |
var pair, padded, zipped, carry, result; | |
if (every(eq(0), second)) { | |
return first; | |
} | |
pair = map(trimLeft(0), [first, second]); | |
padded = map(padLeft(0, max(map(arrLength, pair))), pair); | |
zipped = zipWith(sumWithCarry(10), padded[0], padded[1]); | |
result = map(dot('sum'), zipped); | |
carry = map(dot('carry'), zipped).concat([0]); | |
return addArrayNumbers(result, carry); | |
}; | |
if (module && module.exports) { | |
module.exports = addArrayNumbers; | |
} | |
else { | |
window.addArrayNumbers = addArrayNumbers; | |
} | |
console.info(addArrayNumbers([6, 5, 4], [5, 9])); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment