Skip to content

Instantly share code, notes, and snippets.

Created October 4, 2016 02:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/b4e66ee9a02255660dbbb399ef88ed03 to your computer and use it in GitHub Desktop.
Save anonymous/b4e66ee9a02255660dbbb399ef88ed03 to your computer and use it in GitHub Desktop.
Thrown-together solver for a geocaching puzzle
var magic = ["equals(caret(175.4, 203.9), caret(gt(37.8, 16.3), 19.5))",
"equals(equals(caret(gt(88.7, 66.4), 101.5), caret(72.3, 39.5)), 37.8)",
"equals(equals(equals(caret(22009.9, 10101.8), 7228.7), 368.7), gt(4138488.0, 4020319.0))",
"equals(caret(2066.8, 668.8), caret(12.9, gt(122.1, 8.4)))",
"equals(equals(caret(9999.9, 10375.2), caret(777.7, 37.9)), gt(96.8, 33.0))",
"equals(equals(equals(caret(98765.7, 3777.5), 667.7), 268.3), caret(586728.2, 412841.8))"];
// unambiguous "caret(22009.9, 10101.8) = 7228.7 = 368.7 = gt(4138488.0, 4020319.0)", ?
// "(98765.7 ^ 3777.5) = 667.7 = 268.3 = (586728.2 ^ 412841.8)" ?
function patch(arr, e) {
if (!Array.isArray(arr)) {
throw new Error("1st argument must be array");
}
for (i=0; i<arr.length; i++)
{
if (arr[i] === undefined) {
break;
}
}
arr[i] = e;
}
// function binaryDigit(num, digit) {
// return +((num >>> 0).toString(2)[digit]);
// }
function compoundFactory(seed, dump) {
var opSeedLimit = 6*5*4; // 6_choose_3
if (seed < 0 || seed >= (2*opSeedLimit*(2*2*2*2))) {
throw new Error("Seed outside of range");
}
var balanced = (seed % 2 === 1);
seed = Math.floor(seed / 2);
var opSeed = seed % opSeedLimit;
var ops;
if (dump) {
ops = chooseFromSet(STR_OPS_SYM, 3, opSeed);
} else {
ops = chooseFromSet(OPS_SYM, 3, opSeed);
}
seed = Math.floor(seed / opSeedLimit);
// build a selector function
var selections = seed.toString(2).split('').map(x => +x);
var v = (a,b,n) => selections[n]===1 ? a : b;
// left branching
if (!balanced) return (x, y) => ops[0]( ops[1]( ops[2](v(x,y,0), v(x,y,1)), v(x,y,2)), v(x,y,3));
// balanced
return (x,y) => ops[0](ops[1](v(x,y,0), v(x,y,1)), ops[2](v(x,y,2), v(x,y,3)));
}
var add = (a,b) => a+b;
var subtract = (a,b) => a-b;
var multiply = (a,b) => a*b;
var divide = (a,b) => a/b;
var backwards = (fn) => ((a,b) => fn(b,a));
var sadd = (a,b) => "("+a+"+"+b+")";
var ssubtract = (a,b) => "("+a+"-"+b+")";
var smultiply = (a,b) => "("+a+"*"+b+")";
var sdivide = (a,b) => "("+a+"/"+b+")";
var OPS = [add, subtract, multiply, divide];
var OPS_SYM = [add, subtract, multiply, divide, backwards(subtract), backwards(divide)];
// string forms for reading
var STR_OPS = [sadd, ssubtract, smultiply, sdivide];
var STR_OPS_SYM = [sadd, ssubtract, smultiply, sdivide, backwards(ssubtract), backwards(sdivide)];
function chooseFromSet(set, count, seed) {
var limit = 1;
for (i=0; i<count; i++) {
limit *= (set.length - i);
}
set = Array.from(set);
if (seed < 0 || seed >= limit)
{
throw new Error("Operation seed out of range");
}
var ops = [];
for (count; count > 0; count--) {
ops.push(set.splice(seed % set.length, 1)[0]);
seed = Math.floor(seed/set.length);
}
return ops;
}
var valueExp = function (seed, s, dump) {
var compoundSeedLimit = (2*(6*5*4)*(2*2*2*2));
var localChooseSeed = 3*4*3; // 3 * 4_choose_2
if (seed < 0 || seed > (compoundSeedLimit * localChooseSeed))
{
throw new Error("Trial seed out of range");
}
var compound = compoundFactory(seed % compoundSeedLimit, dump);
if (dump) {
console.info("compound function is ", compound("a", "b"));
}
seed = Math.floor(seed / compoundSeedLimit);
var ops=Array(3);
var compoundPos = seed % 3;
ops[compoundPos] = compound;
seed = Math.floor(seed / 3);
var normalOps;
if (dump) {
normalOps = chooseFromSet(STR_OPS, 2, seed);
} else {
normalOps = chooseFromSet(OPS, 2, seed);
}
patch(ops, normalOps[0]);
patch(ops, normalOps[1]);
if(dump) {
console.info("^ is ", ops[0]("a","b"));
console.info("= is ", ops[1]("a","b"));
console.info("> is ", ops[2]("a","b"));
}
var caret = ops[0];
var equals = ops[1];
var gt = ops[2];
return eval(s);
}
function search () {
for (z=0; z<(2*(6*5*4)*(2*2*2*2))*3*4*3; z++) {
var r1 = valueExp(z, magic[0]);
if (r1 > 36.9 && r1 < 37.1)
{
var r2 = valueExp(z, magic[3]);
if (r2 > 120.9 && r2 < 121.1) {
console.log("Found likely candidate at seed "+z+":");
valueExp(z, null, true);
break;
}
}
}
var out = magic.map((s) => valueExp(z, s));
console.log("Seed "+z+" produces values:", out);
var norm = out.map((x) => Math.round(x)).join(" ");
console.log("...normalized to "+norm);
}
search();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment