Company logo
  • Empleos
  • Bootcamp
  • Acerca de nosotros
  • Para profesionales
    • Inicio
    • Empleos
    • Cursos y retos
    • Preguntas
    • Profesores
    • Bootcamp
  • Para empresas
    • Inicio
    • Nuestro proceso
    • Planes
    • Pruebas
    • Nómina
    • Blog
    • Calculadora

0

37
Vistas
Infinite loop on recursive call Javascript

This is a basic calculator function. It only does addition, subtraction, multiplication, division and parentheses.

I'm having an infinite loop on recursive call in while section which is checking the string whether has a parentheses or not. If i would've send a string with 2 or more parentheses to the function, it has been stucking in loop. I couldn't figure out what I have done wrong.

const operators = ['+', '-', '*', '/', '(', ')'];
const numbers = [];
let arr;
const array = [];
function Calculate(string) {
  string.split('').map(char => {
    if (!operators.includes(char)) {
      numbers.push(char);
    } else {
      arr = numbers.join('');
      numbers.splice(0);
      array.push(arr, char);
    }
  });
  arr = numbers.join('');
  const str = array.filter(char => char !== '').concat(arr);

  while (str.includes('(')) {  // Checking parentheses
    let indexOpen = str.findIndex(char => char === '(');
    let indexClose = indexOpen + 1;
    let count = 1;

    while (count !== 0) {
      if (str[indexClose] === '(') {
        count++;
      } else if (str[indexClose] === ')') {
        count--;
      }
      indexClose++;
    }

    if (
      !operators.includes(str[indexOpen - 1])
      // str[indexOpen - 1] !== '+' &&
      // str[indexOpen - 1] !== '-' &&
      // str[indexOpen - 1] !== '*' &&
      // str[indexOpen - 1] !== '/'
    ) {
      str.splice(indexOpen, 0, '*');
      indexOpen++;
      indexClose++;
    }

    const strPara = str
      .filter((_, i) => i < indexClose - 1 && i > indexOpen)
      .join('');
    str.splice(indexOpen, indexClose - indexOpen, Calculate(strPara));
  }

  let indexMul;  // Multiplication and division
  let indexDiv;
  while (str.includes('*') || str.includes('/')) {
    indexMul =
      str.findIndex(char => char === '*') === -1
        ? str.length
        : str.findIndex(char => char === '*');
    indexDiv =
      str.findIndex(char => char === '/') === -1
        ? str.length
        : str.findIndex(char => char === '/');
    if (indexMul < indexDiv) {
      str.splice(indexMul - 1, 3, +str[indexMul - 1] * +str[indexMul + 1] + '');
    } else if (indexDiv < indexMul) {
      str.splice(
        indexDiv - 1,
        3,
        Math.trunc(+str[indexDiv - 1] / +str[indexDiv + 1]) + ''
      );
    }
  }

  while (str.length !== 1) { // Addition and subtraction
    if (str[1] === '+') {
      str.splice(0, 3, +str[0] + +str[2] + '');
    }
    if (str[1] === '-') {
      str.splice(0, 3, +str[0] - +str[2] + '');
    }
  }

  return str;
}

console.log(Calculate('3(16-(10-4)+2)/2(4*2)+1'));

7 months ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

I did this.
Be careful, this code does the calculations one after the other without managing operators precedence

The recursive way :

let strCalc = '3(16-(10-4)+2)/2(4*2)+1'
document.write(`${ strCalc } = ${ Calculate(strCalc) }`)
document.write(`<br><br>`)

strCalc = '5 ( -18.4 + 2 ) / ( -2 ( 4 * -.5 )) + 1'
document.write(`${ strCalc } = ${ Calculate(strCalc) }`)

function Calculate(str)
  {
  const ops = str
    .match(/[\(\)\+\-\*\/]|((\d+\.?\d*)|(\.\d+))/g)
    .reduce((r,v)=>
    {
    if (isNaN(v))
      {
      if (!r.opPrev || v==='(') 
        {
        r.res.push(v)
        r.opPrev = ( v!==')' )
        }
      else if (v==='-')   // check negatives values
        r.sign='-';
      }
    else
      {
      r.res.push(Number(`${r.sign}${v}`))
      r.sign   = ''
      r.opPrev = false
      }
    return r  
    }, { res:[], opPrev:true, sign:'' }).res  
    ;
  let Pos = 0
    ;
  return makeCalc()
    ;
  function makeCalc()
    {
    let result  = 0
      , operand = '+'
      , val
      ;
    while  ( Pos < ops.length  &&  ops[Pos] !== ')' )
      {
      val = ops[Pos]
        ;
      if ( val === '(' )
        {
        operand ??= '*'        // nullish assignement operator
        Pos++
        val = makeCalc()       // recurvive call
        }
      if ( isNaN(val) )
        operand = val
        ;
      else
        {
        switch (operand)
          {
          case '+' : result += val;  break; 
          case '-' : result -= val;  break; 
          case '/' : result /= val;  break;  // may do 0 divide! 
          case '*' : result *= val;  break; 
          }
        operand = null
        }
      Pos++
      }
    return result
    }
  }

7 months ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar empleo Planes Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2023 PeakU Inc. All Rights Reserved.