Solution to Rosetta Code Challenge - 24 game

What is your hint or solution suggestion?

Summary
function solve24 (numStr) {

    var operands = numStr.split('').sort((a, b) => {return b - a});

    var operators = ['+', '-', '/', '*'];

    var perms = [];

    var perms0 = operands.map((n) => {return [n, parseInt(n)];});

    var perms2 = [];

    for(var i = 0; i < 4; i++){

      for(var j = i+1; j < 4; j++){

        for(var k =  0; k < 4; k++){

          perms.push(evaluate(operands[i], operators[k], operands[j]));

        }

      }

    }

    perms = perms.sort((a, b) => {return b[1] - a[1];});

    for(var i = 0; i < perms.length; i++){

      for(var j = 0; j < 4; j++){

        for(var k =  0; k < 4; k++){

          if(perms[i][1] > operands[j])

            {perms2.push(evaluate2(perms[i], operators[k], operands[j]));}

          else

            {perms2.push(evaluate2(operands[j], operators[k], perms[i]));}

        }

      }

    }

    //check 1 = (exp1)op(exp2) 

    for(var i = 0; i < perms.length-1; i++){

      for(var j = i+1; j < perms.length; j++){

        numsarr = [perms[i][0].split('').filter((num) => {return !isNaN(num)})[0]*1, 

                    perms[i][0].split('').filter((num) => {return !isNaN(num)})[1]*1, 

                    perms[j][0].split('').filter((num) => {return !isNaN(num)})[0]*1, 

                    perms[j][0].split('').filter((num) => {return !isNaN(num)})[1]*1]

                  .sort((a, b) => {return b - a});

        if(numsarr.reduce((str, value) => { return str + '_' + value;}) == operands.reduce((str, value) => { return str + '_' + value;})){

          if(perms[i][1] * perms[j][1] == 24){

            return perms[i][0] + '*' + perms[j][0];

          }

          if((perms[i][1]*1) + (perms[j][1]*1) == 24){

            return perms[i][0] + '+' + perms[j][0];

          }

          if((perms[i][1]*1) / (perms[j][1]*1) == 24){

            return perms[i][0] + '/' + perms[j][0];

          }

          if((perms[j][1]*1) / (perms[i][1]*1) == 24){

            return perms[j][0] + '/' + perms[i][0];

          }

        }

      }

    }

    for(var i = 0; i < perms2.length; i++){

      for(var j = 0; j < perms0.length; j++){

        numsarr = [perms2[i][0].split('').filter((num) => {return !isNaN(num)})[0]*1, 

                    perms2[i][0].split('').filter((num) => {return !isNaN(num)})[1]*1,

                    perms2[i][0].split('').filter((num) => {return !isNaN(num)})[2]*1, 

                    perms0[j][0].split('')[0]*1]

                  .sort((a, b) => {return b - a});

        if(numsarr.reduce((str, value) => { return str + '_' + value;}) == operands.reduce((str, value) => { return str + '_' + value;})){

          if(perms2[i][1] * perms0[j][1] == 24){

            return '(' + perms2[i][0] + ')*' + perms0[j][0];

          }

          if((perms2[i][1]*1) + (perms0[j][1]*1) == 24){

            return '(' + perms2[i][0] + ')+' + perms0[j][0];

          }

          if((perms2[i][1]*1) / (perms0[j][1]*1) == 24){

            return '(' + perms2[i][0] + ')/' + perms0[j][0];

          }

          if((perms0[j][1]*1) / (perms2[i][1]*1) == 24){

            return perms0[j][0] + '/(' + perms2[i][0] + ')';

          }

        }

      }

    }

   return "no solution exists";

  }

  

  function evaluate(a, op, b){

    if(op == '+') return ["("+a+op+b+")", parseInt(a)+parseInt(b)];

    else if(op == '-') return ["("+a+op+b+")", a-b];

    else if(op == '/') return ["("+a+op+b+")", a/b];

    else if(op == '*') return ["("+a+op+b+")", a*b];

  }

  

  function evaluate2(a, op, b){

    if(op == '+') return [(Array.isArray(a)?a[0]:a)+op+(Array.isArray(b)?b[0]:b), parseInt((Array.isArray(a)?a[1]:a))+parseInt(Array.isArray(b)?b[1]:b)];

    else if(op == '-') return [(Array.isArray(a)?a[0]:a)+op+(Array.isArray(b)?b[0]:b), (Array.isArray(a)?a[1]:a)-(Array.isArray(b)?b[1]:b)];

    else if(op == '/') return [(Array.isArray(a)?a[0]:a)+op+(Array.isArray(b)?b[0]:b), (Array.isArray(a)?a[1]:a)/(Array.isArray(b)?b[1]:b)];

    else if(op == '*') return [(Array.isArray(a)?a[0]:a)+op+(Array.isArray(b)?b[0]:b), (Array.isArray(a)?a[1]:a)*(Array.isArray(b)?b[1]:b)];

  }

Challenge: 24 game

Link to the challenge:

Hello there.

Thank you, for your contribution. For future contributions, please wrap your solution within :

[details]
```
code goes here...
```
[/details]

Also, provide all of the necessary code to pass the challenge.

Also, when you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor ( </> ) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (’).

Ok, this code is very complicated. In its current form, it can’t be added as a guide post solution.

I have also done some readability edits, but this is still very hard to understand.

At a minimum, this solution needs comments and better variable names.

I’m not convinced this solution is fully complete and general.

Also, this appears to give valid answers (albeit, some with excessive ()s) that are not expected by the test suite, so that needs to be investigated.

Updated Solution
function solve24(numStr) {
  const digits = numStr.split('').sort((a, b) => b - a).map(a => parseInt(a));
  const operators = ['+', '-', '/', '*'];
  let permutations = [];
  const permutations0 = digits.map((n) => [n, parseInt(n)]);
  const permutations2 = [];

  // All permutations of all digits
  for (let i = 0; i < 4; i++) {
    for (let j = i + 1; j < 4; j++) {
      for (let k = 0; k < 4; k++) {
        permutations.push(evaluate(digits[i], operators[k], digits[j]));
      }
    }
  }
  permutations = permutations.sort((a, b) => b[1] - a[1]);

  for (let i = 0; i < permutations.length; i++) {
    for (let j = 0; j < 4; j++) {
      for (let k = 0; k < 4; k++) {
        if (permutations[i][1] > digits[j]) {
          permutations2.push(
            evaluateArray(permutations[i], operators[k], digits[j])
          );
        } else {
          permutations2.push(
            evaluateArray(digits[j], operators[k], permutations[i])
          );
        }
      }
    }
  }

  // check 1 = (exp1)op(exp2) 
  let numsarr = [];
  for (let i = 0; i < permutations.length - 1; i++) {
    for (let j = i + 1; j < permutations.length; j++) {
      numsarr = [
          permutations[i][0].split('').filter((num) => !isNaN(num))[0] * 1,
          permutations[i][0].split('').filter((num) => !isNaN(num))[1] * 1,
          permutations[j][0].split('').filter((num) => !isNaN(num))[0] * 1,
          permutations[j][0].split('').filter((num) => !isNaN(num))[1] * 1,
        ]
        .sort((a, b) => b - a);

      if (numsarr.reduce((str, value) => str + '_' + value) ==
        digits.reduce((str, value) => str + '_' + value)) {
        if (permutations[i][1] * permutations[j][1] == 24) {
          return permutations[i][0] + '*' + permutations[j][0];
        }
        if ((permutations[i][1] * 1) + (permutations[j][1] * 1) == 24) {
          return permutations[i][0] + '+' + permutations[j][0];
        }
        if ((permutations[i][1] * 1) / (permutations[j][1] * 1) == 24) {
          return permutations[i][0] + '/' + permutations[j][0];
        }
        if ((permutations[j][1] * 1) / (permutations[i][1] * 1) == 24) {
          return permutations[j][0] + '/' + permutations[i][0];
        }
      }
    }
  }

  for (let i = 0; i < permutations2.length; i++) {
    for (let j = 0; j < permutations0.length; j++) {
      numsarr = [
          permutations2[i][0].split('').filter((num) => !isNaN(num))[0] * 1,
          permutations2[i][0].split('').filter((num) => !isNaN(num))[1] * 1,
          permutations2[i][0].split('').filter((num) => !isNaN(num))[2] * 1,
          permutations0[j][0].split('')[0] * 1
        ]
        .sort((a, b) => b - a);
      if (numsarr.reduce((str, value) => str + '_' + value) ==
        digits.reduce((str, value) => str + '_' + value)) {
        if (permutations2[i][1] * permutations0[j][1] == 24) {
          return '(' + permutations2[i][0] + ')*' + permutations0[j][0];
        }
        if ((permutations2[i][1] * 1) + (permutations0[j][1] * 1) == 24) {
          return '(' + permutations2[i][0] + ')+' + permutations0[j][0];
        }
        if ((permutations2[i][1] * 1) / (permutations0[j][1] * 1) == 24) {
          return '(' + permutations2[i][0] + ')/' + permutations0[j][0];
        }
        if ((permutations0[j][1] * 1) / (permutations2[i][1] * 1) == 24) {
          return permutations0[j][0] + '/(' + permutations2[i][0] + ')';
        }
      }
    }
  }
  return "no solution exists";
}

function evaluate(a, op, b) {
  const opString = "(" + a + op + b + ")";
  switch (op) {
    case '+':
      return [opString, a + b];
    case '-':
      return [opString, a - b];
    case '*':
      return [opString, a * b];
    case '/':
      return [opString, a / b];
  }
}

function evaluateArray(a, op, b) {
  const a0Value = Array.isArray(a) ? a[0] : a;
  const a1Value = Array.isArray(a) ? a[1] : a;
  const b0Value = Array.isArray(b) ? b[0] : b;
  const b1Value = Array.isArray(b) ? b[1] : b;
  const opString = a0Value + op + b0Value;
  switch (op) {
    case '+':
      return [opString, a1Value + b1Value];
    case '-':
      return [opString, a1Value - b1Value];
    case '*':
      return [opString, a1Value * b1Value];
    case '/':
      return [opString, a1Value / b1Value];
  }
}

Hi Jeremy. Thanks for your response.
Please note that this solution, although generating valid answers, is not passing test cases for the challenge. I need to work on this solution.

I added this solution so it could serve as a starting point for further contributions towards some better solution. I’ll add notes to the solution as I get time, while working on a different approach.

1 Like