about summary refs log tree commit diff
path: root/day21.clj
blob: d286dfe2b54d86ce2cebe5f8895d5735ca5f6072 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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