Last active
December 22, 2015 10:09
-
-
Save igorw/6456447 to your computer and use it in GitHub Desktop.
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 igorw.brainfuck) | |
; limitations: | |
; * does not support nested loops | |
(defn- iter [code {:keys [ip tape p in out]}] | |
(condp = (get code ip) | |
\> {:p (inc p)} | |
\< {:p (dec p)} | |
\+ {:tape (update-in tape [p] inc)} | |
\- {:tape (update-in tape [p] dec)} | |
\. {:out (conj out (char (get tape p)))} | |
\, (let [input-char (int (or (first in) 0))] | |
{:tape (assoc tape p input-char) :in (rest in)}) | |
\[ (if (zero? (get tape p)) | |
(let [code-segment (subs code (+ ip 1)) | |
ip-offset (count (take-while #(not= % \]) code-segment)) | |
ip (+ ip ip-offset 2)] ; hop over the ] bracket | |
{:ip ip}) | |
{}) | |
\] (let [code-segment (reverse (subs code 0 ip)) | |
ip-offset (count (take-while #(not= % \[) code-segment)) | |
ip (- ip ip-offset 1)] ; hop onto the [ bracket | |
{:ip ip}) | |
{})) | |
(defn execute [code input] | |
(loop [state {:ip 0 | |
:tape (vec (repeat 30000 0)) | |
:p 0 | |
:in input | |
:out []}] | |
; (prn ip (get code ip) (take 10 tape) p in out) | |
(let [{:keys [ip out]} state] | |
(if (= ip (count code)) | |
(apply str out) | |
(recur (merge state | |
{:ip (inc ip)} | |
(iter code state))))))) | |
; hello world | |
(prn (execute ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+." "")) | |
; cat | |
(prn (execute ",[.,]" "foobar")) |
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 igorw.brainfuck) | |
; limitations: | |
; * does not support nested loops | |
(defn execute [code input] | |
(loop [ip 0 | |
tape (vec (repeat 30000 0)) | |
p 0 | |
in input | |
out []] | |
; (prn ip (get code ip) (take 10 tape) p in out) | |
(if (= ip (count code)) | |
(apply str out) | |
(condp = (get code ip) | |
\> (recur (inc ip) tape (inc p) in out) | |
\< (recur (inc ip) tape (dec p) in out) | |
\+ (recur (inc ip) (update-in tape [p] inc) p in out) | |
\- (recur (inc ip) (update-in tape [p] dec) p in out) | |
\. (recur (inc ip) tape p in (conj out (char (get tape p)))) | |
\, (let [input-char (int (or (first in) 0))] | |
(recur (inc ip) (assoc tape p input-char) p (rest in) out)) | |
\[ (if (zero? (get tape p)) | |
(let [code-segment (subs code (+ ip 1)) | |
ip-offset (count (take-while #(not= % \]) code-segment)) | |
ip (+ ip ip-offset 2)] ; hop over the ] bracket | |
(recur ip tape p in out)) | |
(recur (inc ip) tape p in out)) | |
\] (let [code-segment (reverse (subs code 0 ip)) | |
ip-offset (count (take-while #(not= % \[) code-segment)) | |
ip (- ip ip-offset 1)] ; hop onto the [ bracket | |
(recur ip tape p in out)) | |
(recur (inc ip) tape p in out))))) | |
; hello world | |
(prn (execute ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+." "")) | |
; cat | |
(prn (execute ",[.,]" "foobar")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment