Double '+' signs messing with !NaN in JS

131 views Asked by At

Working a evaluator for Polish Notation and I was adding a way to distinguish if the string I got was a number or not using the isNaN function. This works fine, until you add + + to the string.

function cuttingString(list) {
    let adjustArr = list.split(' ')
    let topper = []
    for (let i = 0; i < adjustArr.length; i++) {
        if (!isNaN(adjustArr[i])) {
            topper.push(adjustArr[i])
            console.log(topper)
        } else {
            let j = topper.pop()
            let k = topper.pop()

            if (adjustArr[i] === '+') {
                topper.push(parseInt(j) + parseInt(k))
            }
        }
    }
}

console.log(cuttingString('* 1 2 30 +'))

works as expected with '* 1 2 30 +' it outputs [1,2,30] However, when I start moving around the operators, is when I get a NaN in the beginning of my arrays [NaN, 1,2,30] which is incredibly frustrating. Any ideas on how to fix this problem or other work arounds?

1

There are 1 answers

0
trincot On

Your code seems to implement reverse Polish notation, and so you cannot expect it to work correctly if you don't provide arguments before any of the binary operators. So you cannot randomly move the + around in the expression. A binary operator can only occur if there are at least two numbers available on the stack. If not, the call to pop will return undefined and parseInt(undefined) is NaN. Although you did not implement multiplication yet, it is problematic that the * occurs at a time when the stack is still empty.

It would make sense to have your function return the result, as your console.log will currently only output undefined and so you don't actually see the result of the calculation.

If indeed, your idea was to implement an evaluator for reverse Polish notation, then here is what I would adapt to your code:

function cuttingString(list) {
    // Allow multiple spaces, also at start/end:
    let adjustArr = list.match(/\S+/g); 
    let topper = [];
    // Use for..of loop
    for (let token of adjustArr) {
        if (!isNaN(token)) {
            // Why not convert to number here...
            //   and allow decimals. Use unary plus
            topper.push(+token);
        } else if (topper.length < 2) {
            // Show error message when not enough arguments
            throw "not enough arguments for " + token;
        } else {
            let j = topper.pop();
            let k = topper.pop();
            if (token === '+') {
                topper.push(j + k);
            }
        }
    }
    // Verify that the evaluation is complete
    if (topper.length !== 1) {
        throw "Evaluation did not yield one value but " + topper.length;
    }
    // Return the value 
    return topper.pop();
}

console.log(cuttingString('1 2 30 + +')); // 33
console.log(cuttingString('1 2 + 30 +')); // 33

The two examples in this code are the only places where you can move the + operator to. For instance, neither of the following is valid:

console.log(cuttingString('1 2 + + 30'));
console.log(cuttingString('1 + 2 30 +'));

In either case, there arises a situation where the stack does not have enough arguments for a binary operator. The code above will provide a specific error message for that.