Mittwoch, 6. Juni 2012

Reverse Polish Notation in Clojure - Version 2

Ein weiterer Kollege von mir hat ebenfalls in Clojure eine Lösung für die RPN geschrieben (zu finden hier). Nicht zu verwechseln mit der Scala Lösung von letztem mal (auch hier noch mal der Link ;-)). Ich habe mich auch nochmal dran gesetzt, um weitere Lösungsmöglichkeiten auszuprobieren. Hier ist eine davon. Diese Lösung erstellt eine unendliche Sequnce der einzelen Schritte, in der die RPN aufgelöst wird, dar. Einfach mal selber testen. Denkt bitte daran, die Sequence ist unendlich groß. Also immer nur einen Teil rausholen (zum Beispiel mit range, take oder nth).
(defn calc-next-step [input]
  (if (= 1 (count input)) input
    (loop [[x y] input
           [op & rest-input] (nthnext input 2)
           output ''()]
      (if (number? op)
        (recur [y op] rest-input (concat output (list x)))
        (concat output `(~(op x y)) rest-input )))))

(defn rpn-seq [input]
  (iterate (fn [n] (calc-next-step n)) input))
Der Output kann folgendermaßen aussehen. Ich habe aus Lesbarkeitsgründen die Ausgabe formatiert, und die Clojure-Operatoren durch Zeichen ersetzt, die man dann auch lesen kann ;-). Ansonsten würde der Multiplikator folgendermaßen aussehen:
#<core$_STAR_ clojure.core$_STAR_@3e2f1b1a>

Java toString halt ;-)
Hier die formatierte Ausgabe

(take 5 (rpn-seq (calc-next-step [12 2 3 + 2 * 5 / -])))
((12 5 2 * 5 / -)
(12 10 5 / -)
(12 2 -)
(10)
(10))
Mir ist gerade später aufgefallen, dass der innere Aufruf unnötig ist. Der kann natürlich weggelassen werden ;-). Dann sieht das alles so aus:
(take 5 (rpn-seq [12 2 3 + 2 * 5 / -]))
((12 2 3 + 2 * 5 / -)
(12 5 2 * 5 / -)
(12 10 5 / -)
(12 2 -)
(10))

Keine Kommentare:

Kommentar veröffentlichen