Last active
August 29, 2015 14:26
-
-
Save jcorbin/af23ca6d81f7ca8b70fe 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
// Inspired by http://blog.plover.com/prog/monad-search-2.html | |
// S E N D | |
// + M O R E | |
// ----------- | |
// M O N E Y | |
function toNumber(digits) { | |
var r = 0; | |
for (var i = 0; i < digits.length; i++) { | |
r += digits[i] * Math.pow(10, digits.length - i - 1); | |
} | |
return r; | |
} | |
function chooseADigit(digits, each) { | |
for (var i = 0; i < digits.length; i++) { | |
var digit = digits[i]; | |
var remain = digits.slice(0, i).concat(digits.slice(i + 1)); | |
each(remain, digit); | |
} | |
} | |
function chooseFilter(choice, filter, digits, each) { | |
choice(digits, function got(digits, digit) { | |
if (filter(digit)) { | |
each(digits, digit); | |
} | |
}); | |
} | |
function notZero(digit) { | |
return digit !== 0; | |
} | |
function chooseWaterfall(choices, digits, each) { | |
if (!choices.length) { | |
each(digits, []); | |
return; | |
} | |
firstChoice(digits, [], 0); | |
function firstChoice(digits, r, i) { | |
choices[i](digits, function got(digits, digit) { | |
var s = r.concat([digit]); | |
nextChoice(digits, s, 1); | |
}); | |
} | |
function nextChoice(digits, r, i) { | |
if (i >= choices.length) { | |
each(digits, r); | |
return; | |
} | |
choices[i](r, digits, function got(digits, digit) { | |
var s = r.concat([digit]); | |
nextChoice(digits, s, i + 1); | |
}); | |
} | |
} | |
function chooseSeries(choices, digits, each) { | |
nextChoice(digits, [], 0); | |
function nextChoice(digits, r, i) { | |
if (i >= choices.length) { | |
each(digits, r); | |
return; | |
} | |
choices[i](digits, function got(digits, digit) { | |
var s = r.concat([digit]); | |
nextChoice(digits, s, i + 1); | |
}); | |
} | |
} | |
var start = process.hrtime(); | |
function chooseThree(digits, next) { | |
return chooseSeries([ | |
chooseADigit, | |
chooseADigit, | |
chooseADigit | |
], digits, next); | |
} | |
function chooseTwo(digits, next) { | |
return chooseSeries([ | |
chooseADigit, | |
chooseADigit | |
], digits, next); | |
} | |
function chooseInitial(digits, next) { | |
chooseFilter(chooseADigit, notZero, digits, next); | |
} | |
function chooseTwoInitials(digits, next) { | |
chooseSeries([ | |
chooseInitial, | |
chooseInitial | |
], digits, next); | |
} | |
function chooseDEY(digits, next) { | |
chooseFilter(chooseThree, checkSum, digits, next); | |
} | |
function chooseNR(groups, digits, next) { | |
chooseFilter(chooseTwo, checkSecondSum, digits, next); | |
function checkSecondSum(nr) { | |
return checkSum(groups[0], nr); | |
} | |
} | |
function chooseO(groups, digits, next) { | |
chooseFilter(chooseADigit, checkThirdSum, digits, next); | |
function checkThirdSum(o) { | |
return checkSum(groups[0], groups[1], o); | |
} | |
} | |
function chooseSM(groups, digits, next) { | |
chooseFilter(chooseTwoInitials, function checkFourthSum(sm) { | |
return checkSum(groups[0], groups[1], groups[2], sm); | |
}, digits, next); | |
} | |
function checkSum(dey, nr, o, sm) { | |
var d = dey[0]; | |
var e = dey[1]; | |
var y = dey[2]; | |
if ((d + e) % 10 != y) return false; | |
if (nr === undefined) return true; | |
var rem1 = Math.floor((d + e) / 10); | |
var n = nr[0]; | |
var r = nr[1]; | |
if ((n + r + rem1) % 10 != e) return false; | |
if (o === undefined) return true; | |
var rem2 = Math.floor((n + r + rem1) / 10); | |
if ((e + o + rem2) % 10 != n) return false; | |
if (sm === undefined) return true; | |
var rem3 = Math.floor((e + o + rem2) / 10); | |
var s = sm[0]; | |
var m = sm[1]; | |
if ((s + m + rem3) % 10 !== o) return false; | |
var rem4 = Math.floor((s + m + rem3) / 10); | |
return rem4 === m; | |
} | |
chooseWaterfall([ | |
chooseDEY, | |
chooseNR, | |
chooseO, | |
chooseSM | |
], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], function process(digits, groups) { | |
var dey = groups[0]; | |
var d = dey[0]; | |
var e = dey[1]; | |
var y = dey[2]; | |
var nr = groups[1]; | |
var n = nr[0]; | |
var r = nr[1]; | |
var o = groups[2]; | |
var sm = groups[3]; | |
var s = sm[0]; | |
var m = sm[1]; | |
var send = toNumber([s, e, n, d]); | |
var more = toNumber([m, o, r, e]); | |
var money = toNumber([m, o, n, e, y]); | |
console.log('%s + %s = %s', send, more, money); | |
}); | |
var end = process.hrtime(); | |
var d = [ | |
end[0] - start[0], | |
end[1] - start[1] | |
]; | |
if (d[1] < 0) { | |
d[0]--; | |
d1 += 1e9; | |
} | |
console.log('took %sms', d[0] * 1e3 + d[1] / 1e6); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment