Loading

Number Symbol Puzzle

<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>Number Symbol Puzzle</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>
  <div id="puzzle"></div>
<div id="solution"></div>
<div id="n1" class="emj"></div>
<div id="n2" class="emj"></div>
<div id="n3" class="emj"></div>
<div id="n4" class="emj"></div>
<div id="n5" class="emj"></div>
<div id="n6" class="emj"></div>
<div id="n7" class="emj"></div>
<div id="n8" class="emj"></div>
<div id="n9" class="emj"></div>
<div id="o1" class="emj"></div>
<div id="o2" class="emj"></div>
<div id="o3" class="emj"></div>
<div id="o4" class="emj"></div>
<div id="o5" class="emj"></div>
<div id="o6" class="emj"></div>
<div id="e1" class="emj">=</div>
<div id="e2" class="emj">=</div>
<div id="e3" class="emj">=</div>
<div id="e4" class="emj">=</div>
<div id="e5" class="emj">=</div>
<div id="e6" class="emj">=</div>
  
    <script  src="js/index.js"></script>

</body>
</html>
/* Downloaded from https://ahoj.co.uk/ */


#solution
{
  font-family:Courier;
  margin:50px;
  float:left;
  font-size:2em;
  position: absolute;
  left:600px;
}

.emj{
  font-size:2em;
  text-align:right;
  width:200px;
  position:absolute;
  font-family:Verdana;
}

#n1{
  left:20px;
  top:20px;
}

#n2{
  left:190px;
  top:20px;
}

#n3{
  left:360px;
  top:20px;
}

#n4{
  left:20px;
  top:120px;
}

#n5{
  left:190px;
  top:120px;
}

#n6{
  left:360px;
  top:120px;
}

#n7{
  left:20px;
  top:220px;
}

#n8{
  left:190px;
  top:220px;
}

#n9{
  left:360px;
  top:220px;
}

#o1{
  left:50px;
  top:20px;
}
#o2{
  left:50px;
  top:120px;
}
#o3{
  left:50px;
  top:220px;
}

#o4{
  left:10px;
  top:70px;
}
#o5{
  left:180px;
  top:70px;
}
#o6{
  left:355px;
  top:70px;
}

#e1{
  left:230px;
  top:20px;
}
#e2{
  left:230px;
  top:120px;
}
#e3{
  left:230px;
  top:220px;
}
#e4{
  left:10px;
  top:170px;
}
#e5{
  left:180px;
  top:170px;
}
#e6{
  left:355px;
  top:170px;
}
/* Downloaded from https://ahoj.co.uk/ */
/*
var numbers = ["ABBA", "CDA", "EE",
  "EBFC", "FDD", "GGE",
  "DHGE", "EIHB", "GADE"
]

//0,1,2 = horizontal top to bottom
//3,4,5 = vertical left to right
var operations = ["/", "-", "-", "-", "+", "*"]

//------------------------------------------------

var numbers = ["ABC", "DA", "ED",
  "DFG", "DHE", "FI",
  "CGB", "DEF", "IIA"
]

//0,1,2 = horizontal top to bottom
//3,4,5 = vertical left to right
var operations = ["/", "-", "-", "-", "+", "*"]
  //------------------------------------------------

var numbers = ["AB", "BC", "DAD",
  "FC", "G", "G",
  "BCD", "E", "BBBA"
]

//0,1,2 = horizontal top to bottom
//3,4,5 = vertical left to right
var operations = ["*", "/", "*", "*", "/", "*"]

//------------------------------------------------
*/
var numbers
var operations



var emojis = shuffle(["🐀", "🐁", "🐂", "🐃", "🐄", "🐅", "🐆", "🐇", "🐈", "🐉", "🐊", "🐋", "🐏", "🐐", "🐓", "🐕", "🐖", "🐪"])

var letters = shuffle(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"])



var combinations = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8]
]
var sign2op = {
  '+': plus,
  '-': minus,
  '/': div,
  '*': mult
}
var zero = "A".charCodeAt(0)
var order = [0, 1, 2, 3, 4, 5]

var done;
var likely;
var baseLikely;

function swap(arr, n1, n2) {
  var c;
  c = arr[n1];
  arr[n1] = arr[n2];
  arr[n2] = c;
}


function prepare() {
  shuffle(letters);
  shuffle(emojis);
  var va, vb, vc, vd, ve, vf, vg, vh, vi;
vb = Math.floor(Math.random() * 389) + 10;
do {
  do {
    vc = Math.floor(((Math.random() * 3999) + 1000) / vb);
    va = vb * vc;
  } while ((va < 1000) || (vc < 10));
  do {
    vf = Math.floor(((Math.random() * 4999) + 5000) / vc);
    vi = vc * vf;
  } while (vi - va < 2000);
  ve = (vi - va - vb - vf) / 2;
} while (ve % 2 > 0);

numbers = [String(va), String(vb), String(vc), String(vf + ve), String(ve), String(vf), String(va + ve + vf), String(vb + ve), String(vi)];
operations = ['/', '-', '+', '+', '+', '*'];


if (Math.random() < 0.5) {
  swap(numbers, 0, 3);
  swap(numbers, 1, 4);
  swap(numbers, 2, 5);
  swap(operations, 0, 1);
}

if (Math.random() < 0.5) {
  swap(numbers, 1, 3);
  swap(numbers, 2, 6);
  swap(numbers, 5, 7);
  swap(operations, 0, 3);
  swap(operations, 1, 4);
  swap(operations, 2, 5);
}
if (Math.random() < 0.3) {
  swap(numbers, 0, 8);
  swap(numbers, 1, 5);
  swap(numbers, 3, 7);
  swap(operations, 0, 5);
  swap(operations, 1, 4);
  swap(operations, 2, 3);
  for (i = 0; i < 6; i++) {
    switch (operations[i]) {
      case '+':
        {
          operations[i] = '-';
          break;
        };
      case '+':
        {
          operations[i] = '+';
          break;
        };
      case '*':
        {
          operations[i] = '/';
          break;
        };
      case '/':
        {
          operations[i] = '*';
          break;
        };
    }
  }
}
  for (var i = 0; i < 9; i++) {
  var repl = ""
  for (var j = 0; j < numbers[i].length; j++) {
    repl += "" + letters[parseInt(numbers[i][j])]
  }
  numbers[i] = repl;
}
  
  done = {}
  likely = []

  for (var i = 0; i < 10; i++) {
    likely.push("0123456789")
  }

  //preparation:
  // step 1: leading numbers cannot be zero:
  for (var i = 0; i < 9; i++) {
    var notZero = numbers[i].charCodeAt(0) - zero
    likely[notZero] = likely[notZero].split("0").join("")
  }
  //console.log("after step 1",likely)
  /*
    //step 2: check for impossible numbers in sums and differences
    for (var i = 0; i < combinations.length; i++) {
      if (operations[i] == "+" &&
        numbers[combinations[i][0]].length == numbers[combinations[i][1]].length &&
        numbers[combinations[i][1]].length == numbers[combinations[i][2]].length &&
        numbers[combinations[i][0]][0] != numbers[combinations[i][1]][0]) {
        var not9 = numbers[combinations[i][0]].charCodeAt(0) - zero
        likely[not9] = likely[not9].split("9").join("")
        not9 = numbers[combinations[i][1]].charCodeAt(0) - zero
        likely[not9] = likely[not9].split("9").join("")
        var not1 = numbers[combinations[i][2]].charCodeAt(0) - zero
        likely[not1] = likely[not1].split("1").join("")
        var not2 = numbers[combinations[i][2]].charCodeAt(0) - zero
        likely[not2] = likely[not2].split("2").join("")
      }
      if (operations[i] == "-" &&
        numbers[combinations[i][0]].length == numbers[combinations[i][1]].length &&
        numbers[combinations[i][1]].length == numbers[combinations[i][2]].length &&
        numbers[combinations[i][0]][0] != numbers[combinations[i][1]][0]) {
        not1 = numbers[combinations[i][0]].charCodeAt(0) - zero
        likely[not1] = likely[not1].split("1").join("")
        not9 = numbers[combinations[i][1]].charCodeAt(0) - zero
        likely[not9] = likely[not9].split("9").join("")
        not9 = numbers[combinations[i][2]].charCodeAt(0) - zero
        likely[not9] = likely[not9].split("9").join("")
      }

    }
  */
  //console.log("after step 2",likely)

  //step 3: check for bigger smaller in sums and differences
  /*
  var change = true;

  while (change) {
    change = false;
    for (var i = 0; i < combinations.length; i++) {
      if (operations[i] == "-" &&
        numbers[combinations[i][0]].length == numbers[combinations[i][1]].length) {
        var smaller = numbers[combinations[i][0]].charCodeAt(0) - zero;
        var bigger = numbers[combinations[i][1]].charCodeAt(0) - zero;
        for (var j = 0; j < parseInt(likely[bigger][0]); j++) {
          if (likely[smaller].indexOf(j) > -1) {
            likely[smaller] = likely[smaller].split(j).join("")
            change = true;
          }
        }
        bigger = numbers[combinations[i][1]].charCodeAt(0) - zero
        smaller = numbers[combinations[i][0]].charCodeAt(0) - zero
        for (var j = 9; j > parseInt(likely[smaller][likely[smaller].length - 1]); j--) {
          if (likely[bigger].indexOf(j) > -1) {
            likely[bigger] = likely[bigger].split(j).join("");
            change = true;
          }
        }
      }
      //console.log("after step 3a",likely)

      if (operations[i] == "+" &&
        numbers[combinations[i][0]].length == numbers[combinations[i][1]].length &&
        numbers[combinations[i][1]].length == numbers[combinations[i][2]].length) {
        var smaller = numbers[combinations[i][0]].charCodeAt(0) - zero;
        var bigger = numbers[combinations[i][2]].charCodeAt(0) - zero;
        for (var j = 0; j <= parseInt(likely[bigger][0]); j++) {
          if (likely[smaller].indexOf(j) > -1) {
            likely[smaller] = likely[smaller].split(j).join("")
            change = true;
          }
        }
        var smaller = numbers[combinations[i][1]].charCodeAt(0) - zero;
        for (var j = 0; j <= parseInt(likely[bigger][0]); j++) {
          if (likely[smaller].indexOf(j) > -1) {
            likely[smaller] = likely[smaller].split(j).join("")
            change = true;
          }
        }

        bigger = numbers[combinations[i][2]].charCodeAt(0) - zero
        smaller = numbers[combinations[i][0]].charCodeAt(0) - zero
        for (var j = 9; j >= parseInt(likely[smaller][likely[smaller].length - 1]); j--) {
          if (likely[bigger].indexOf(j) > -1) {
            likely[bigger] = likely[bigger].split(j).join("");
            change = true;
          }
        }
        bigger = numbers[combinations[i][2]].charCodeAt(0) - zero
        smaller = numbers[combinations[i][1]].charCodeAt(0) - zero
        for (var j = 9; j >= parseInt(likely[smaller][likely[smaller].length - 1]); j--) {
          if (likely[bigger].indexOf(j) > -1) {
            likely[bigger] = likely[bigger].split(j).join("");
            change = true;
          }
        }

      }
      //console.log("after step 3b",likely)
    }
  }
  */
  baseLikely = likely.slice()
  showPuzzle()
  solved = false;
  iters = 0;
  solve()
}

function checkEquation(index, v) {
  return sign2op[operations[index]]([numbers[combinations[index][0]], numbers[combinations[index][1]], numbers[combinations[index][2]]], v)
}

function plus(p, v) {
  return parseNumber(p[0], v) + parseNumber(p[1], v) == parseNumber(p[2], v)
}

function minus(p, v) {
  return parseNumber(p[0], v) - parseNumber(p[1], v) == parseNumber(p[2], v)
}

function mult(p, v) {
  return parseNumber(p[0], v) * parseNumber(p[1], v) == parseNumber(p[2], v)
}

function div(p, v) {
  return parseNumber(p[2], v) * parseNumber(p[1], v) == parseNumber(p[0], v)
}

function parseNumber(n, v) {

  var f = Math.pow(10, n.length - 1)
  var sum = 0
  var i = 0
  while (i < n.length) {
    sum += f * v[(n.charCodeAt(i) - zero)]
    f /= 10
    i += 1
  }
  return sum | 0
}

function displayEquation(index, v) {
  var result = ""
  var e = numbers[combinations[index][0]] + operations[index] + numbers[combinations[index][1]] + "=" + numbers[combinations[index][2]];
  for (var i = 0; i < e.length; i++) {
    if (e[i] >= "A" && e[i] <= "J") {
      result += "" + v[e.charCodeAt(i) - zero]
    } else {
      result += e[i]
    }
  }
  return result;

}

function getRandomPermutation() {
  var failsafe = 0
  while (true && failsafe < 1000) {
    failsafe++;
    var result = []
    var used = []
    var o = shuffle([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    for (var i = 0; i < 10; i++) {
      var l = likely[o[i]]

      for (var j = 0; j < used.length; j++) {
        l = l.split(used[j]).join("")
      }
      if (l.length == 0) break;
      var digit = l[(Math.random() * l.length) | 0]
      used.push(digit)
      result[o[i]] = digit;

    }
    if (i < 10) continue;
    var id = result.join("")
    if (!done[id]) {
      done[id] = true;
      return result;
    }

  }
  console.log("failed")
  return false;
}

function learn(perm) {
  for (var i = 0; i < 10; i++) {
    if (likely[i].length < maxLikelyLength && likely[i].split(perm[i]).length / likely[i].length < maxLikelyhood) {
      likely[i] += "" + perm[i]
    }
  }
}

function shuffle(array) {
  var currentIndex = array.length,
    temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = (Math.random() * currentIndex) | 0;
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

function solve() {
  for (var i = 0; i < 1000; i++) {
    iters++;
    var perm = getRandomPermutation();
    if (perm) {
      shuffle(order)
      for (var j = 0; j < order.length; j++) {
        if (!checkEquation(order[j], perm)) {
          break;
        } else {
          learn(perm)
            //console.log(iters, perm, displayEquation(order[j], perm))
        }
      }
      if (j == order.length) {
        /*
        console.log("DONE",iters, "iterations", perm)
        for (var j = 0; j < order.length; j++) {
          console.log(displayEquation(j, perm))
        }
        */

        showSolution(perm)

        solved = true;
        setTimeout(prepare,15000)
        return;
      }
    } else {
      //console.log(likely)
      break;
    }
  }
  
  if (!solved) {
    document.getElementById("solution").innerHTML = iters + " Attempts";

    if (iters % 25000 == 0) {
      //console.log("restarted", likely);
      likely = baseLikely.slice();
    }
    if (iters > 400000)
      {
        setTimeout(prepare,500)
        return;
      }
    window.requestAnimationFrame(solve);
  }

}

function spacePad(n) {
  if (String(n).length == 1) return "&nbsp;&nbsp;&nbsp;" + n
  if (String(n).length == 2) return "&nbsp;&nbsp;" + n
  if (String(n).length == 3) return "&nbsp;" + n
  return n;
}

function toEmoji( t)
{
  return   t.split("A").join(emojis[0]).split("B").join(emojis[1]).split("C").join(emojis[2]).split("D").join(emojis[3]).split("E").join(emojis[4]).split("F").join(emojis[5]).split("G").join(emojis[6]).split("H").join(emojis[7]).split("I").join(emojis[8]).split("J").join(emojis[9])
}

function showPuzzle() {
  
  document.getElementById("n1").innerHTML = toEmoji(numbers[0])
  document.getElementById("n2").innerHTML = toEmoji(numbers[1])
  document.getElementById("n3").innerHTML = toEmoji(numbers[2])
  document.getElementById("n4").innerHTML = toEmoji(numbers[3])
  document.getElementById("n5").innerHTML = toEmoji(numbers[4])
  document.getElementById("n6").innerHTML = toEmoji(numbers[5])
  document.getElementById("n7").innerHTML = toEmoji(numbers[6])
  document.getElementById("n8").innerHTML = toEmoji(numbers[7])
  document.getElementById("n9").innerHTML = toEmoji(numbers[8])
  
  document.getElementById("o1").innerHTML =operations[0]
  document.getElementById("o2").innerHTML =operations[1]
  document.getElementById("o3").innerHTML =operations[2]
  document.getElementById("o4").innerHTML =operations[3]
  document.getElementById("o5").innerHTML =operations[4]
  document.getElementById("o6").innerHTML =operations[5]
  
  

}

function showSolution(perm) {
  document.getElementById("solution").innerHTML = [spacePad(parseNumber(numbers[0], perm)), operations[0], spacePad(parseNumber(numbers[1], perm)), "=", spacePad(parseNumber(numbers[2], perm))].join(" ") + "<br/>&nbsp;&nbsp;&nbsp;" + operations[3] + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + operations[4] + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + operations[5] + "<br/>" + [spacePad(parseNumber(numbers[3], perm)), operations[1], spacePad(parseNumber(numbers[4], perm)), "=", spacePad(parseNumber(numbers[5], perm))].join(" ") + "<br/>&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=<br/>" + [spacePad(parseNumber(numbers[6], perm)), operations[2], spacePad(parseNumber(numbers[7], perm)), "=", spacePad(parseNumber(numbers[8], perm))].join(" ")
}

var maxLikelyhood = 0.4;
var maxLikelyLength = 300;
var solved = false;
var iters = 0
prepare()

This awesome code is write by Mario Klingemann, you can se more from this user in the personal repository