Refactor Intcode into a library
authorJack Kinsey <kinsey_john@bah.com>
Mon, 9 Dec 2019 21:06:32 +0000 (16:06 -0500)
committerJack Kinsey <kinsey_john@bah.com>
Mon, 9 Dec 2019 21:09:10 +0000 (16:09 -0500)
src/adventofcode2019/intcode.clj [new file with mode: 0644]
src/adventofcode2019/template.clj

diff --git a/src/adventofcode2019/intcode.clj b/src/adventofcode2019/intcode.clj
new file mode 100644 (file)
index 0000000..72fe618
--- /dev/null
@@ -0,0 +1,72 @@
+(ns adventofcode2019.intcode
+  [:require [adventofcode2019.lib :refer :all]])
+
+;; 0: function args&mem -> [mem (ctr -> ctr)]
+;; 1: number of args
+(defn- decode-op [opcode] 
+  (let [str-code (format "%05d" opcode)
+        flags (reverse (take 3 str-code))
+        op (vec (drop 3 str-code))
+        apply-flag (fn [flag arg]
+                     (case flag
+                       \0 (fn ([] arg) ([S] (get-in S [:memory arg])))
+                       \1 (constantly arg)
+                       \2 #(get-in % [:memory (+' arg (:relctr %))])))
+        with-flags (fn [f]
+                     (fn [S & args]
+                       (apply f S (map apply-flag flags args))))]
+    (with-flags 
+      (case op
+        [\0 \1] (fn [S a b c] ; ADD
+                  (-> S 
+                      (assoc-in [:memory (c)] (+' (a S) (b S)))
+                      (update :ctr + 4)))
+        [\0 \2] (fn [S a b c] ; MULT
+                  (-> S
+                      (assoc-in [:memory (c)] (*' (a S) (b S)))
+                      (update :ctr + 4)))
+        [\0 \3] (fn [S a _ _] ; IN
+                  (-> S
+                      (assoc-in [:memory (a)] (first (:input S)))
+                      (update :input subvec 1)
+                      (update :ctr + 2)))
+        [\0 \4] (fn [S a _ _] ; OUT
+                  (-> S
+                      (update :output conj (get-in S [:memory (a)]))
+                      (update :ctr + 2))) 
+        [\0 \5] (fn [S a b _] ; BNEQ
+                   (update S :ctr (if (not= (a S) 0) (constantly (b S)) #(+ % 3))))
+        [\0 \6] (fn [S a b _] ; BEQ
+                   (update S :ctr (if (= (a S) 0) (constantly (b S)) #(+ % 3))))
+        [\0 \7] (fn [S a b c] ; SLT
+                  (-> S
+                      (assoc-in [:memory (c)] (if (< (a S) (b S)) 1 0))
+                      (update :ctr + 4)))
+        [\0 \8] (fn [S a b c] ; SEQ
+                  (-> S
+                      (assoc-in [:memory (c)] (if (= (a S) (b S)) 1 0))
+                      (update :ctr + 4)))
+        [\0 \9] (fn [S a _ _] ; SREL
+                   (-> S
+                       (update :relctr + (a S))
+                       (update :ctr + 2)))
+        [\9 \9] (fn [S _ _ _] ; EXIT
+                   (assoc S :exit 1))))))
+
+(defn- perform-operation [{:keys [memory ctr] :as state}]
+  (let [operation (decode-op (memory ctr))
+        args (map memory [(+ 1 ctr) (+ 2 ctr) (+ 3 ctr)])]
+    (apply operation state args)))
+
+(defn build-state 
+  ([program]
+   (let [memory (into {} (map-indexed #(vector %1 %2) program))]
+     {:memory memory :ctr 0 :input [] :output [] :relctr 0}))
+  ([program settings]
+   (merge (build-state program) settings)))
+
+(defn intcode [{:as state :keys [memory output]}]
+   (cond ; quit if :exit, step and return state if :step, else loop
+       (get state :exit) {:memory memory :output output}
+       (get state :step) (perform-operation state)
+       :else (recur (perform-operation state))))
index c239cb5d8ad2b24848a4eeea2da62b177dd87754..dc96c3180f87c9c0696e2a4cf2c34774abdbc829 100644 (file)
@@ -1,5 +1,6 @@
 (ns adventofcode2019.day00
     [:require [adventofcode2019.lib :refer :all]
+              [adventofcode2019.intcode :as i]
               [clojure.string :as str]
               [clojure.core.match :refer [match]]
               [clojure.math.combinatorics :as combo]])