aboutsummaryrefslogtreecommitdiffstats
path: root/day23/core.clj
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2021-12-23 12:33:45 -0500
committerClyne Sullivan <clyne@bitgloo.com>2021-12-23 12:33:45 -0500
commitd13c4e6b075afefe98b6629ca9b1230fc2eaa81e (patch)
treee7da5f3297f75b849d011f5c7d3d941db73d57b1 /day23/core.clj
parentf89005009a1c8dbaf12a793e10534e5149bc45dd (diff)
add day 23
Diffstat (limited to 'day23/core.clj')
-rw-r--r--day23/core.clj108
1 files changed, 108 insertions, 0 deletions
diff --git a/day23/core.clj b/day23/core.clj
new file mode 100644
index 0000000..3459065
--- /dev/null
+++ b/day23/core.clj
@@ -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))))
+