0
var toyProblem = function () {
  var sol= 0;
  var operators = ['+','-','*','/'];
  console.log(sol)

    for(var i in arguments){
      for(var j in operators){
        sol = eval(sol + (operators[j]) + arguments[i]);
      }
    }

  return sol;

 }

 toyProblem(6, 0, 10, 3); //6 + 0 - 10 * 3 === -12)

I'm trying to loop through 4 math operators for an unknown number of input values. I'm thinking of using eval in a nest for loop as a way of going through both the unknown number of arguments while also changing the math operator. At the bottom is the solution that I want to arrive at. Is this a good way of going about this problem or am I barking up the wrong tree?

Brayheart
  • 11
  • 2

5 Answers5

0

Nesting the 2 loops will result in doing 6 + 6 - 6 * 6 / 6 + 0 - 0 * 0 / 0 + 10 - 10 * 10 / 10 + 3 - 3 * 3 / 3

I didn't find a way to do this without eval as looping through operations one by one would modify the operators priority so this is what I propose : Building an operation 'query' to be eval'd and returned.

Hope this helps

var toyProblem = function () {
  var operation = '';
  var operators = ['+','-','*','/'];
  var args = Array.from(arguments);

    args.forEach(function (arg, index) {
      if (index > 0) {
        operation += operators[index - 1];
      }
      operation += arg;
    });

  return eval(operation);

}
console.log(6 + 0 - 10 * 3);
console.log(toyProblem(6, 0, 10, 3)); //6 + 0 - 10 * 3 === -24)
3Dos
  • 3,210
  • 3
  • 24
  • 37
0

Let's decompose the problem. You have a variadic function that accepts unknown number of arguments and applies an operator to each next argument depending on the index of that element.

Because the number of arguments can be greater than the number of operators, it's appropriate to use modulo operator to infinitely loop through the array of operators while going once through the list of arguments.

The eval operation takes a string, evaluates it, and returns the result of evaluation of the expression that string represents. So you're on the right track. But because eval function takes a string as the first argument, I'd recommend using template literals, it's supported in almost all browsers natively and doesn't need to be transpiled into good old ES5.

The function then would look like this:

function toyProblem(first = 0, ...args) {
  const operators = ['+', '-', '*', '/'];
  let sol = first;

  for (let i in args) {
    sol = eval(`${sol} ${operators[i % operators.length]} ${args[i]}`);
  }

  return sol;
}

However, as there is recommended in the comments, using eval isn't something you'd like to ship to users. Instead, I'd suggest using functions. Functions in Javascript are first-class citizens, so you can pass them as an argument.

Imagine that you have a function (a, b) => a + b instead of just a string "+". The code would then look like this:

function toyProblem(first = 0, ...args) {
  const operations = [
    (a, b) => a + b,
    (a, b) => a - b,
    (a, b) => a * b,
    (a, b) => a / b,
  ];
  let sol = first;

  for (let i in args) {
    sol = operations[i](sol, args[i]);
  }

  return sol;
}

You could go even further and make the function universal in terms of possible operations. Have fun!

rishat
  • 8,206
  • 4
  • 44
  • 69
0

Since you are hard coding the names of the operators you might as well hard code the functions and avoid eval. You put the functions into an array that will let you loop through. Then you can just reduce through the arguments with a simple one-liner, which will handle any amount of arguments:

const op = [
    (a, b)  => a + b,
    (a, b)  => a - b,
    (a, b)  => a * b,
    (a, b)  => a / b
]

function prob(...args){
    return args.reduce((curr, acc, idx) =>  op[(idx - 1) % op.length](curr, acc))
}
console.log(prob(6, 0, 10, 3))
console.log(prob(6, 0, 10, 3, 20, 11, 15, 100))
Mark
  • 90,562
  • 7
  • 108
  • 148
0

To get product -12 the first three parts of the expression need to be evaluated within parentheses, else the result will be -24. You can use String.prototype.replace() to replace "," characters after calling .toString() on input array, replace the "," with the operator, return the expression (6 + 0 - 10) * 3 from Function() constructor

var toyProblem = function () {
  var operators = ['+','-','*'];
  var opts = operators.slice(0);
  var n = [...arguments];
  var res = n.toString().replace(/,/g, () => opts.shift());
  var index = res.indexOf(operators[operators.length -1]);
  return new Function(`return (${res.slice(0, index)})${res.slice(index)}`)();
 }

var product = toyProblem(6, 0, 10, 3);

console.log(product);
guest271314
  • 1
  • 15
  • 104
  • 177
0

var toyProblem = function () {
  var sol_str='';
  var operators = ['+','-','*','/'];
    for(var i in operators){
     var prev_operator=(i-1);
     if(sol_str!=''){sol_str+=operators[prev_operator];}
        sol_str +=arguments[i];
    }
    console.log(sol_str);
    return eval(sol_str);

 }


 console.log(toyProblem(6, 0, 10, 3));
mscdeveloper
  • 2,749
  • 1
  • 10
  • 17