Last active
July 2, 2022 02:27
-
-
Save mzhr/0ff92f789f0bd0ffb8a7c60698d69fa4 to your computer and use it in GitHub Desktop.
Clojure Brainf Interpreter (Codewars challenge https://www.codewars.com/kata/526156943dfe7ce06200063e)
This file contains 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
(ns brainf) | |
(defn exec [instruction params] | |
(let [{:keys [source postsource data input pointer output]} params | |
current-data (nth data pointer)] | |
(case instruction | |
\> (assoc params :pointer (inc pointer)) | |
\< (assoc params :pointer (dec pointer)) | |
\+ (assoc params :data (concat (take pointer data) | |
(list (if (= 255 current-data) 0 (inc current-data))) | |
(nthrest data (inc pointer)))) | |
\- (assoc params :data (concat (take pointer data) | |
(list (if (= 0 current-data) 255 (dec current-data))) | |
(nthrest data (inc pointer)))) | |
\. (assoc params :output (str output (char current-data))) | |
\, (assoc params | |
:input (if (nil? (first input)) input (rest input)) | |
:data (concat (take pointer data) | |
(list (if (nil? (first input)) current-data (int (first input)))) | |
(nthrest data (inc pointer)))) | |
\[ (if (not (= 0 current-data)) params | |
(loop [p params m 0] | |
(let [{:keys [source postsource data input pointer output]} p | |
next (assoc p | |
:source (rest source) | |
:postsource (conj postsource (first source)))] | |
(if (and (= \] (first source)) (= m 0)) next | |
(recur next (cond (= \] (first source)) (dec m) | |
(= \[ (first source)) (inc m) | |
:else m)))))) | |
\] (if (= 0 current-data) params | |
(loop [prev (assoc params | |
:source (conj source (first postsource)) | |
:postsource (rest postsource)) | |
m 0] | |
(let [{:keys [source postsource data input pointer output]} prev] | |
(if (and (= \[ (first postsource)) (= m 0)) prev | |
(recur(assoc params | |
:source (conj source (first postsource)) | |
:postsource (rest postsource)) | |
(cond (= \[ (first postsource)) (dec m) | |
(= \] (first postsource)) (inc m) | |
:else m))))))))) | |
(defn execute-string | |
"Evaluate the Brainff source code in `source` using `input` as a source of | |
characters for the `,` input command. | |
Either returns a sequence of output characters, or `nil` if there was | |
insufficient input." | |
[source input] | |
(loop [params {:source source | |
:postsource '() | |
:input input | |
:data (repeat 0) | |
:pointer 0 | |
:output ""}] | |
(cond | |
(nil? (first (params :source))) | |
(params :output) | |
(and (= \, (first (params :source))) (= 0 (count (params :input)))) | |
nil | |
:else | |
(recur | |
(exec (first (params :source)) | |
(assoc params | |
:source (rest (params :source)) | |
:postsource (conj (params :postsource) (first (params :source))))))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment