Last active
July 13, 2016 12:20
-
-
Save boutell/b6c9c5e7d406703ab2d6e6fd8c620fb9 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
// 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