Codewars Lösung | Reverse polish notation calculator


coden
Codewars. Achieve mastery through challenge.
Daniel Kaser|29. Mai 2024
3 min.

Inhalt

  1. Die Fakten
  2. Beschreibung
  3. Lösung
    1. Pseudo-Code
    2. Code
  4. Feedback

Die Fakten:

Plattform:codewars.com
Name:Reverse polish notation calculator
Level:6 kyu
Sprache:TypeScript

Beschreibung:

Your job is to create a calculator which evaluates expressions in Reverse Polish notation.

For example expression 5 1 2 + 4 * + 3 - (which is equivalent to 5 + ((1 + 2) * 4) - 3 in normal notation) should evaluate to 14.

For your convenience, the input is formatted such that a space is provided between every token.

Empty expression should evaluate to 0.

Valid operations are +, -, *, /.

You may assume that there won't be exceptional situations (like stack underflow or division by zero).

Quelle: codewars.com

Lösung

Pseudo-Code

Wie immer gibt's reichlich Varianten, hier ist eine meiner.

Erst die Lösungsschritte in Pseudo-Code. Los geht’s:

Lösungsschritte
Schritt 1

Als Erstes wandeln wir den Input-String in ein Array um und loopen.

Schritt 2

Wir brauchen einen inneren und einen äußeren Loop.

Schritt 3

Außen loopen wir solange, wie unser Array mehr als 1 Element hat.

Schritt 4

Innen loopen wir durch jedes Element und suchen das nächste Element das keine Zahl ist.

Schritt 5

Wenn das aktuelle Element keine Zahl ist,

Schritt 6

schnappen wir uns das aktuelle und die beiden Elemente davor

Schritt 7

und basteln uns daraus unsere mathematische Operation.

Schritt 8

Dann stecken wir das Ergebnis der Operation wieder zurück ins Array.

Schritt 9

Und loopen nochmal durch das verbleibende Array (wir fahren fort mit dem äußeren Loop).

Schritt 10

Wenn nur noch 1 Element im Array ist, geben wir das zurück.

Code

Geil. Übersetzen wir unseren Pseudo-Code in TypeScript:

Lösungsschritte
Meine erste Zeile:
export function calc(expr: string): number {
Input-String in ein Array umwandeln:
const arr = expr.split(" ");
Jetzt der äußere Loop (solange wie das Array mehr als 1 Element hat):
  while (arr.length > 1) {
Dann der innere Loop durch jedes Element (das noch im Array ist):
    for (let i = 0; i < arr.length; i++) {
Wir prüfen, ob das aktuelle Element eine Zahl ist:
      if (!Number(arr[i])) {
Wenn es keine Zahl ist, extrahieren wir das aktuelle Element und die beiden Elemente davor:
const [first, second, operator] = arr.splice(i - 2, 3);

Hier dekonstruiere ich die 3 Elemente direkt. So haben sie gleich Namen.

Dann führen wir die aktuelle Rechenoperation aus und speichern das Ergebnis:
const currResult = eval(`${first} ${operator} ${second}`);

Ich verwende hier eval(). eval() sollte man unbedingt mit Vorsicht genießen. Vor allem, wenn man mit Nutzereingaben arbeitet.

Dann fügen wir das Ergebnis wieder in unser Array ein:
arr.splice(i - 2, 0, currResult);

Das geht z.B. mit .splice(). Wenn man ein drittes Argument angibt, wird dieses am Index des erstes Argumentes eingefügt.

Dann können wir den aktuellen Schleifendurchlauf abbrechen und wieder zur while-Schleife hochspringen:
        break;
      }
    }
  }
Nach beiden Loops - wenn wir nur noch 1 Element in unserem Array haben (unser Ergebnis) - geben wir dieses als Zahl zurück:
  return Number(arr[0]);
}
Voilá! 💪

Fragen?

Komplettlösung
export function calc(expr: string): number {
  const arr = expr.split(" ");

  while (arr.length > 1) {
    for (let i = 0; i < arr.length; i++) {
      if (!Number(arr[i])) {
        const [first, second, operator] = arr.splice(i - 2, 3);
        const currResult = eval(`${first} ${operator} ${second}`);
        arr.splice(i - 2, 0, currResult);
        break;
      }
    }
  }

  return Number(arr[0]);
}

Feedback

Schreib mir!