about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--day212
-rw-r--r--day21.bqn19
-rw-r--r--day21.clj56
3 files changed, 77 insertions, 0 deletions
diff --git a/day21 b/day21
new file mode 100644
index 0000000..fc17973
--- /dev/null
+++ b/day21
@@ -0,0 +1,2 @@
+Player 1 starting position: 3
+Player 2 starting position: 10
diff --git a/day21.bqn b/day21.bqn
new file mode 100644
index 0000000..c19e7f3
--- /dev/null
+++ b/day21.bqn
@@ -0,0 +1,19 @@
+#start ← 4‿8
+start ← 3‿10
+
+scores ← +` {𝕩+10×𝕩=0} 10| start +` (+´)⎉1 200‿2‿3 ⥊ 1+↕100
+end ← ⊑ / (»⊸<∨`) «⥊scores≥1000
+loser ←  end ⊑ ⥊scores
+roll ← 3×2+ end
+•Show loser × roll
+
+Move ← { ⟨roll,player,⟨pos,score⟩⟩:
+  pos2 ← {1+10|roll+𝕩-1}⌾(player⊸⊑) pos
+  ⟨pos2, score + pos2 × player=↕≠pos2⟩
+}
+f ← 3↓<˘⍉(↕∘≠ ≍ ⊣) ≠¨⊔+˝⍉>⥊1+↕3⥊3
+Play ← {
+ ⟨player,⟨pos,score⟩⟩: ∨´score ≥ 21 ? score ≥ 21 ;
+ ⟨player,st⟩: +´ { ⟨val,frq⟩: frq × Play (¬player)‿(Move val‿player‿st) }¨ f
+}
+•Show ⌈´ Play 0‿⟨start,⟨0,0⟩⟩
diff --git a/day21.clj b/day21.clj
new file mode 100644
index 0000000..d286dfe
--- /dev/null
+++ b/day21.clj
@@ -0,0 +1,56 @@
+(ns org.vuxu.aoc2021.day21
+  (:require [clojure.string :as str]))
+
+(def data
+  (->> (slurp "day21")
+       str/split-lines
+       (map (partial re-find #"\d+$"))
+       (mapv parse-long)))
+
+(def freqs
+  (frequencies
+   (for [a [1 2 3]
+         b [1 2 3]
+         c [1 2 3]]
+     (+ a b c))))
+
+(defn move [roll player state]
+  (let [state
+        (update-in state [:pos player] #(inc (mod (dec (+ % roll)) 10)))]
+    (update-in state [:score player] + (get-in state [:pos player]))))
+
+(def state {:pos data
+            :score [0 0]})
+
+(def part1
+  (let [game (take-while (fn [state]
+                           (every? #(< % 1000) (:score state)))
+                         (reductions
+                          (fn [state [player val]]
+                            (move val player state))
+                          state
+                          (map vector
+                               (cycle [0 1])
+                               (map (partial apply +)
+                                    (partition 3 (cycle (range 1 101)))))))]
+    (* (* 3 (count game))
+       (apply min (:score (last game))))))
+;; => 713328
+
+(def play
+  (memoize
+   (fn [player state]
+     (cond
+       (>= (get-in state [:score 0]) 21) [1 0]
+       (>= (get-in state [:score 1]) 21) [0 1]
+       :else
+       (reduce (fn [result [val freq]]
+                 (mapv + result
+                         (mapv (partial * freq)
+                               (play (- 1 player) (move val player state)))))
+               [0 0]
+               freqs)))))
+
+(def part2
+  (apply max (play 0 state)))
+;; => 92399285032143