0

so I have a problem. A string has either a number, DUP, POP, +, or -. if it's a number, the number is pushed to a stack. if DUP, the last number is duplicated and pushed. If POP, the last number is popped. if +, the last 2 numbers are added and popped and the sum is pushed to stack. If -, the last popped num - second popped num is pushed to stack. I'm having problem with my logic. I'm getting NaN when I did the case for DUP for some reason. For "3 DUP" i'm getting NaN.

function solution(S){
  let arr = S.split(" ");
  let stack = [];
  for(let i = 0; i < arr.length; i++){
    if(typeof parseInt(arr[i]) == "number") {
      stack.push(parseInt(arr[i]));
      continue;
    } if (arr[i] == "DUP") {
      let len = stack.length;
      console.log(len)
      let lastNum = stack[stack.length-1]
      stack.push(parseInt(lastNum));
      console.log(stack)
    }
  }
  return stack.pop();
}
Happy Epicurean
  • 101
  • 1
  • 9

2 Answers2

0

You need a different check for a number. By using a conversion to number you get type of number (NaN is a number, but not a valid value in the sense of the function).

Instead take a check if you got a finite number (isFinite) and push a number to the array.

function solution(S) {
    let arr = S.split(" ");
    let stack = [];
    for (let i = 0; i < arr.length; i++) {
        if (isFinite(arr[i])) {
            stack.push(+arr[i]);
            continue;
        }

        if (arr[i] == "DUP") {
            let len = stack.length;
            console.log(len);
            let lastNum = stack[stack.length - 1];
            stack.push(lastNum);                   // without conversion!
            console.log(stack);
        }
    }
    return stack;
}

console.log(solution('3 DUP'));

Another solution is to move the check with known strings at top and interpret unknown strings as number.

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • To be clear, `typeof NaN === 'number'`, but `NaN` is not a number, by definition. See [Why does typeof NaN return 'number'?](https://stackoverflow.com/q/2801601/215552). Basically, `NaN` is a numeric type. You can use the global `isNaN` to check if the string you receive can be safely coerced to a number. – Heretic Monkey Oct 05 '20 at 19:28
0

I'd suggest a significantly different approach. If we make the operations simple functions and store them in an object keyed by name, we can make this much easier to extend.

const words = {
  'DUP':  (a) => [a, a],
  'POP':  (a) => [],  // aka DROP
  '+':    (a, b) => [a + b],
  '-':    (a, b) => [a - b],
}

const applyOp = (stack, op) =>
  [
    ... (stack .slice (0, -(op .length))), 
    ... op (... stack .slice (-op .length))
  ]

const process = (input) => 
  input .reduce (
    (stack, word) => word in words ? applyOp (stack, words [word]) : [...stack, word], 
    []
  )

const peek = (array) =>
  array [array.length - 1]

const solution = (str) =>
  peek (process (
    str .split (' ') .map (w => isFinite (w) ? Number (w) : w)
  ))

console .log (
  solution ('3 5 DUP + + 2 -') 
  //=> 11  (3 + (5 + 5) - 2)
)

Here the main function is process which, using the words dictionary and the applyOp helper, takes an array of words such as 3, + or DUP and builds the appropriate stack, returning it at the end. We use it like this:

process ([3, 5, 'DUP', '+', '+', 2, '-']) 
//=> //=> 11  (3 + (5 + 5) - 2)

We build solution on top of this by splitting your input string, converting numeric strings to numbers and calling process on that array, finally returning the top of the stack (using the peek helper which looks at the top value but doesn't remove it.)

The important thing here is words. Each entry in the dictionary is keyed by the word used in your input. Each value is the corresponding function. We used its length to determine how many words to pull off the stack, then we add to the stack all the values in the array it returns.

With this style, we can now easily add new operations:

  '*':  (a, b) => a * b,
  '/':  (a, b) => a / b,
  SWAP: (a, b) => [b, a],
  ROT:  (a, b, c) => [b, c, a],

I think this gives you a great deal of flexibility.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103