Skip to content

Instantly share code, notes, and snippets.

@piratefsh
Created July 4, 2015 15:19
Show Gist options
  • Save piratefsh/91e76ebad9cdc0786930 to your computer and use it in GitHub Desktop.
Save piratefsh/91e76ebad9cdc0786930 to your computer and use it in GitHub Desktop.
Cryptoarithmetic Solver
article
header
.container
h1 Cryptoarithmetic Solver
section
.container
h2 Puzzle
form#puzzle-form
.form-group
input#puzzle.form-control(type="text", placeholder="Puzzle", value="ODD+ODD==EVEN")
.form-group
input.pull-left.btn.btn-primary.btn-solve(type="submit")
section.solution
.container
h2 Solution
.well
ul#solutions
$(function(){
var $solutionsContainer = $('.solution').hide();
var $btn = $('.btn-solve');
var $solutions = $('#solutions').html("");
$('#puzzle-form').submit(function(event){
event.preventDefault();
var puzzle = $('#puzzle', event.target).val();
$btn.val('Solving...');
// solve
var solutions = solve(puzzle);
$btn.val("Submit");
// display results
$solutionsContainer.show();
$solutions.html("");
for(var s of solutions){
$solutions.append('<li>' + s + '</li>');
}
if(solutions.length == 0){
$solutions.html('No solution')
}
});
});
function solve(puzzle){
var chars = uniqueChars(puzzle).join("");
var combinations = Combinatorics.permutation([0,1,2,3,4,5,6,7,8,9], chars.length);
var results = [];
var compiled = compile(puzzle);
if(!compiled){
return [];
}
while(c = combinations.next()){
if(compiled.apply(null, c)){
var filled = replace(puzzle, chars, c.join(""));
results.push(filled);
}
}
console.log(results);
return results;
}
// returns unique alphabets in text
function uniqueChars(text){
var set = new Set(text.match(/[A-Z]/g)).values();
var arr = [];
for (s of set){ arr.push(s)}
return arr;
}
// compile puzzle
function compile(puzzle){
var params = uniqueChars(puzzle).join(",");
// get leading digits
var leadingPattern = /\b([A-Z])[A-Z]/g;
var leadingDigits = [];
while((results = leadingPattern.exec(puzzle))){
leadingDigits.push(results[1]);
}
var leadingDigitsStr = "[" + leadingDigits.join(",") + "]"
// compile expression
var tokens = puzzle.split(/([A-Z]+)/g);
var exp = tokens.map(compileWord).join(" ");
// put together function
var func = "(function f(" + params
+ "){ if(" + leadingDigitsStr + ".indexOf(0) == -1){ "
+ "return " + exp + "} "
+ "else {return false}})";
var fn;
// catch eval errors
try{
fn = eval(func);
}
catch(err){
alert(err.message);
return false;
}
return fn;
}
function compileWord(word){
if(/[A-Z]/g.test(word)){
var digits = [];
for(var i = 0; i < word.length; i++){
var zeroes = Math.pow(10, word.length - 1 - i)
var digit = word[i] + '*' + zeroes;
digits.push(digit);
}
return "(" + digits.join('+') + ")";
}
else{
return word;
}
}
// replaces chars in intab with chars in outtab
function replace(text, intab, outtab){
intab = intab.split(""); outtab = outtab.split("");
var table = {};
for(var i in intab){
table[intab[i]] = outtab[i];
}
var translated = text.split("");
translated.map(function(curr, index, arr){
if(curr in table) arr[index] = table[curr];
});
return translated.join("");
}
function test(){
console.log(replace('ODD+ODD==EVEN', 'ODEVN', '12345'));
var f = compile('ODD+ODD==EVEN');
console.log(f(0, 1, 2, 3, 4));
var g = compile('MEE+YOU==OKAY');
console.log(g(0, 1, 2, 3, 4));
}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://rawgit.com/dankogai/js-combinatorics/master/combinatorics.js"></script>
$space: 20px
header, section
margin-bottom: $space
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment