]> code.bitgloo.com Git - clyne/advent-of-code.git/commitdiff
add day 23
authorClyne Sullivan <clyne@bitgloo.com>
Thu, 23 Dec 2021 17:33:45 +0000 (12:33 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Thu, 23 Dec 2021 17:33:45 +0000 (12:33 -0500)
day23/core.clj [new file with mode: 0644]
day23/part1-done-by-hand [new file with mode: 0644]

diff --git a/day23/core.clj b/day23/core.clj
new file mode 100644 (file)
index 0000000..3459065
--- /dev/null
@@ -0,0 +1,108 @@
+;
+; Place in new leiningen 'app' template project
+;
+; Run with `java -Xmx8G -jar ...`
+;
+
+(ns hah.core
+  (:gen-class))
+
+(require '[clojure.core.reducers :as r])
+
+(def init-field
+  [nil
+   nil
+   (seq [:b :d :d :d])
+   nil
+   (seq [:b :c :b :a])
+   nil
+   (seq [:c :b :a :a])
+   nil
+   (seq [:d :a :c :c])
+   nil
+   nil])
+
+(defn do-slot [[field q s] idx]
+  (let [slot (get field idx)]
+    (cond
+      ; Moving value out of a room
+      (and (seq? slot) (not (empty? slot)) (not (every? #(= % ({2 :a 4 :b 6 :c 8 :d} idx)) slot)))
+      (let [open-slots
+            (filterv
+              #(contains? #{0 1 3 5 7 9 10} %)
+              (concat
+                (for [i (reverse (range 0 idx)) :while (or (nil? (get field i)) (seq? (get field i)))] i)
+                (for [i (range idx (count field)) :while (or (nil? (get field i)) (seq? (get field i)))] i)))]
+        (when-not (empty? open-slots)
+          (map
+            (fn [os]
+              [(-> field
+                   (assoc os (first slot))
+                   (update idx rest))
+               (conj q [idx os])
+               (+ s (* ({:a 1 :b 10 :c 100 :d 1000} (first slot)) (+ (inc (- 4 (count slot))) (Math/abs (- os idx)))))])
+            open-slots)))
+      ; Moving value into a room
+      (and (not (seq? slot)) (some? slot))
+      (let [our-room ({:a 2 :b 4 :c 6 :d 8} slot)]
+        (if (every? #(or (nil? (get field %)) (seq? (get field %)))
+                    (range (inc (min our-room idx)) (max our-room idx)))
+          (let [room (get field our-room)]
+            (when (or (empty? room) (every? #(= slot %) room))
+              [(-> field
+                   (assoc idx nil)
+                   (update our-room conj slot))
+               (conj q [idx our-room])
+               (+ s (* ({:a 1 :b 10 :c 100 :d 1000} slot) (+ (Math/abs (- idx our-room)) (- 4 (count room)))))])))))))
+
+(defn winner? [[field q s]]
+  (= field
+    [nil
+     nil
+     (seq [:a :a :a :a])
+     nil
+     (seq [:b :b :b :b])
+     nil
+     (seq [:c :c :c :c])
+     nil
+     (seq [:d :d :d :d])
+     nil
+     nil]))
+
+(defn do-turns [fields]
+  (into []
+    (r/fold
+      1024
+      r/cat
+      #(if-let [t (apply do-slot %2)]
+         (if (seq? t)
+           (reduce r/append! %1 t)
+           (r/append! %1 t))
+         %1)
+      (into [] (for [f fields i (range 0 11)] [f i])))))
+
+(def wins (atom #{}))
+
+(defn play-games [turns tc]
+  (println "Games:" (count turns) "Turn:" tc)
+  (if (< 500000 (count turns))
+    (do
+      (println "Splitting...")
+      (doseq [p (partition 100000 turns)
+              :let [r (play-games (into [] p) tc)]] nil))
+    (do
+      (let [new-turns (do-turns turns)
+            winners (filter winner? new-turns)]
+        (if (pos? (count winners))
+          (do
+            (println "Winner! Turns:" tc)
+            (swap! wins #(reduce conj % (map last winners))))
+          (when (pos? (count new-turns))
+            (recur new-turns (inc tc))))))))
+
+(defn -main
+  "I don't do a whole lot ... yet."
+  [& args]
+  (play-games [[init-field [] 0]] 0)
+  (println (first (sort @wins))))
+
diff --git a/day23/part1-done-by-hand b/day23/part1-done-by-hand
new file mode 100644 (file)
index 0000000..e69de29