Last active
August 4, 2022 03:03
-
-
Save technomancy/e6bf7910ab0c53ba59cac76c1e32bf4e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; For this, please write a program which takes in a CLI arg for a string | |
;; expression such as “1 + 2 - 3” and have it interpret the expression | |
;; and print the result to stdout. Only support for + and - is needed, to | |
;; avoid precedence. | |
(fn evaluate [input] | |
;; first for regularity, we prepend a + to the input string; this way we end | |
;; up just looping thru a series of operator/number pairs instead of having | |
;; numbers with operators between them. | |
(let [input (.. "+ " input)] | |
;; the accumulate macro works the same way reduce would in most languages | |
;; with two important differences: one is that it's a macro, so instead of | |
;; accepting a reducer function, the body of the macro runs with the | |
;; bindings set up in the square brackets. our accumulator sum starts at | |
;; zero, while the op and n values are bound to successive matches to the | |
;; two things found by the regex. | |
(accumulate [sum 0 | |
;; the other difference is that instead of iterating over a | |
;; list, it accepts an iterator, which makes it easy to use | |
;; with tables but also easy to swap in things like gmatch | |
;; which yields successive hits to a regex across a string. | |
op n (input:gmatch "([-+%*/]) ([^ ]+)")] | |
;; we do a pattern match on the operator from the string match. pattern | |
;; matching can do a lot more than what we're doing here which could be | |
;; accomplished with "case" in conventional languages, but for this | |
;; problem that's all we need. | |
(match op | |
;; the requirements say we only need to support + and -, but we might as | |
;; well extend it to multiplication and division and throw operator | |
;; precedence out the window, because operator precedence is bogus. | |
:- (- sum (tonumber n)) | |
:+ (+ sum (tonumber n)) | |
:* (* sum (tonumber n)) | |
:/ (/ sum (tonumber n)))))) | |
(evaluate "1 + 2 - 3") ; -> 0 | |
(evaluate "6 / 2 * 4 - 2 + 99.2") ; -> 109.2 | |
(evaluate "0 + 0 + 1 + 0") ; -> 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment