Skip to content

Instantly share code, notes, and snippets.

@boutell
Last active July 13, 2016 12:20
Show Gist options
  • Save boutell/b6c9c5e7d406703ab2d6e6fd8c620fb9 to your computer and use it in GitHub Desktop.
Save boutell/b6c9c5e7d406703ab2d6e6fd8c620fb9 to your computer and use it in GitHub Desktop.
// JavaScript solver for http://blog.plover.com/math/17-puzzle.html
// (Cheesy yet flexible exhaustive search with recursion and eval)
var numbers = [ 6, 6, 5, 2 ];
var operators = [ '*', '/', '+', '-' ];
var goal = 17;
combine(numbers, function(numberSeries) {
if (count(operators, numbers.length - 1, function(operatorSeries) {
var expression = numberSeries[0].toString();
for (var i = 0; (i < operatorSeries.length); i++) {
expression = '(' + expression + ' ' + operatorSeries[i] + ' ' + numberSeries[i + 1].toString() + ')';
}
if (eval(expression) === goal) {
console.log(expression);
return false;
}
}) === false) {
return false;
}
});
// This works correctly if all the numbers are different, but since
// two of the numbers are the same, it will invoke iterator twice
// for each possible combination
function combine(numbers, iterator) {
for (var i = 0; (i < numbers.length); i++) {
var remainder = numbers.concat();
remainder.splice(i, 1);
if (remainder.length) {
if (combine(remainder, function(series) {
if (iterator([ numbers[i] ].concat(series)) === false) {
return false;
}
}) === false) {
return false;
}
} else {
if (iterator([ numbers[i] ]) === false) {
return false;
}
}
}
}
// The operators need not all be used and can be used more than once.
// In other words they are digits in a number of base (number of operators).
// Just count through the possibilities. This will break like a twig
// if digits.length ^ places is greater than the largest integer
// JavaScript can represent without loss of accuracy
function count(digits, places, iterator) {
var total = Math.pow(digits.length, places);
var series;
var i, j, n;
for (i = 0; (i < total); i++) {
n = i;
series = [];
for (j = 0; (j < places); j++) {
series.push(digits[n % digits.length]);
n = Math.floor(n / digits.length);
}
if (iterator(series) === false) {
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment