aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2021-12-26 08:41:42 -0500
committerClyne Sullivan <clyne@bitgloo.com>2021-12-26 08:41:42 -0500
commit66ed0b9d27850dc653abc8baa75884f3de311bfa (patch)
tree7a8fca0ad3e1ee4abc5b5e920df3e26efe9b678f
parent7a78309cf5492a1aeae7cd551ceb9906026e938b (diff)
day24: solve using code
-rw-r--r--day24/checker.clj47
-rw-r--r--day24/partboth.clj74
2 files changed, 81 insertions, 40 deletions
diff --git a/day24/checker.clj b/day24/checker.clj
new file mode 100644
index 0000000..4874f62
--- /dev/null
+++ b/day24/checker.clj
@@ -0,0 +1,47 @@
+(require '[clojure.string :as str])
+
+(defn alu-parse-argument [arg]
+ (if (contains? #{\w \x \y \z} (first arg))
+ (str/join ["@" arg])
+ (read-string arg)))
+
+(defn alu-parse-instruction [[ins arg1 arg2]]
+ (let [arg2-parsed (if (some? arg2) (alu-parse-argument arg2) 0)]
+ (case ins
+ "inp"
+ (str/join ["(reset! " arg1 " (- (int (get input (swap! index inc))) 48))\n"])
+ "add"
+ (str/join ["(swap! " arg1 " +' " arg2-parsed ")\n"])
+ "mul"
+ (str/join ["(swap! " arg1 " *' " arg2-parsed ")\n"])
+ "div"
+ (str/join ["(swap! " arg1 " quot " arg2-parsed ")\n"])
+ "mod"
+ (str/join ["(swap! " arg1 " rem " arg2-parsed ")\n"])
+ "eql"
+ (str/join ["(swap! " arg1 " #(if (= % " arg2-parsed ") 1 0))\n"]))))
+
+(def alu-program-header
+ "(defn alu-program [input]
+ (let [index (atom -1) w (atom 0) x (atom 0) y (atom 0) z (atom 0)]\n")
+
+(defn alu-compile-program [instructions]
+ (let [parsed-ins (mapv alu-parse-instruction instructions)]
+ (eval (read-string
+ (str/join [alu-program-header
+ (str/join parsed-ins)
+ "@z))"])))))
+
+(def program (->> (slurp "./in")
+ str/split-lines
+ (map #(str/split % #"\s+"))
+ (alu-compile-program)))
+
+; to split by `inp w`s:
+; (partition 18)
+; (reverse)
+; (mapv alu-compile-program)))
+
+(println "Part 1:" (program "16181111641521"))
+(println "Part 2:" (program "59692994994998"))
+
diff --git a/day24/partboth.clj b/day24/partboth.clj
index 4874f62..9548ec3 100644
--- a/day24/partboth.clj
+++ b/day24/partboth.clj
@@ -1,47 +1,41 @@
(require '[clojure.string :as str])
-(defn alu-parse-argument [arg]
- (if (contains? #{\w \x \y \z} (first arg))
- (str/join ["@" arg])
- (read-string arg)))
-
-(defn alu-parse-instruction [[ins arg1 arg2]]
- (let [arg2-parsed (if (some? arg2) (alu-parse-argument arg2) 0)]
- (case ins
- "inp"
- (str/join ["(reset! " arg1 " (- (int (get input (swap! index inc))) 48))\n"])
- "add"
- (str/join ["(swap! " arg1 " +' " arg2-parsed ")\n"])
- "mul"
- (str/join ["(swap! " arg1 " *' " arg2-parsed ")\n"])
- "div"
- (str/join ["(swap! " arg1 " quot " arg2-parsed ")\n"])
- "mod"
- (str/join ["(swap! " arg1 " rem " arg2-parsed ")\n"])
- "eql"
- (str/join ["(swap! " arg1 " #(if (= % " arg2-parsed ") 1 0))\n"]))))
-
-(def alu-program-header
- "(defn alu-program [input]
- (let [index (atom -1) w (atom 0) x (atom 0) y (atom 0) z (atom 0)]\n")
-
-(defn alu-compile-program [instructions]
- (let [parsed-ins (mapv alu-parse-instruction instructions)]
- (eval (read-string
- (str/join [alu-program-header
- (str/join parsed-ins)
- "@z))"])))))
+; The given program operates on a base-26 stack, either pushing or
+; (conditionally) popping values. This code extracts those operations
+; from the input, then works through them to determine the highest
+; and lowest values that produce an output of zero.
+; See the .md file in this directory for more info.
(def program (->> (slurp "./in")
str/split-lines
(map #(str/split % #"\s+"))
- (alu-compile-program)))
-
-; to split by `inp w`s:
-; (partition 18)
-; (reverse)
-; (mapv alu-compile-program)))
-
-(println "Part 1:" (program "16181111641521"))
-(println "Part 2:" (program "59692994994998"))
+ (partition 18)
+ (map (fn [step]
+ (if (= "1" (last (nth step 4)))
+ [:push (read-string (last (nth step 15)))]
+ [:pop (read-string (last (nth step 5)))])
+ ))))
+
+(defn program-index [prog] (- 14 (count prog)))
+
+(loop [numbers (vec (repeat 2 (vec (repeat 14 0))))
+ stack '()
+ prog program]
+ (if-let [step (first prog)]
+ (if (= :push (first step))
+ (recur numbers
+ (conj stack [(program-index prog) (second step)])
+ (rest prog))
+ (let [i2 (program-index prog)
+ [i1 v] (first stack)
+ diff (+ v (second step))]
+ (recur
+ [(if (neg? diff)
+ (-> (first numbers) (assoc i1 9) (assoc i2 (+ 9 diff)))
+ (-> (first numbers) (assoc i2 9) (assoc i1 (- 9 diff))))
+ (if (neg? diff)
+ (-> (second numbers) (assoc i2 1) (assoc i1 (- 1 diff)))
+ (-> (second numbers) (assoc i1 1) (assoc i2 (+ 1 diff))))]
+ (rest stack) (rest prog))))
+ (println (map str/join numbers))))