From c0464c3a851108571d3cf763dfc3906bbe93a50a Mon Sep 17 00:00:00 2001 From: Jack Kinsey Date: Mon, 9 Dec 2019 16:06:32 -0500 Subject: [PATCH] Refactor Intcode into a library --- src/adventofcode2019/intcode.clj | 72 +++++++++++++++++++++++++++++++ src/adventofcode2019/template.clj | 1 + 2 files changed, 73 insertions(+) create mode 100644 src/adventofcode2019/intcode.clj diff --git a/src/adventofcode2019/intcode.clj b/src/adventofcode2019/intcode.clj new file mode 100644 index 0000000..72fe618 --- /dev/null +++ b/src/adventofcode2019/intcode.clj @@ -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)))) diff --git a/src/adventofcode2019/template.clj b/src/adventofcode2019/template.clj index c239cb5..dc96c31 100644 --- a/src/adventofcode2019/template.clj +++ b/src/adventofcode2019/template.clj @@ -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]]) -- 2.38.5