about summary refs log tree commit diff
path: root/day04.clj
blob: 316fcefa5147526c1f9e8198f497a41a85cba670 (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.day04
  (:require [clojure.string :as str]))

(let [[draws & cards] (str/split (slurp "day04") #"\n\n")]
  (def draws (->> (str/split draws #",")
                  (map parse-long)))
  (def cards (for [card cards]
               (->> card
                    str/split-lines
                    (map str/trim)
                    (mapv #(->> (str/split % #" +")
                                (mapv parse-long)))))))

(defn find-in [number card]
  (first (for [[lineno line] (map-indexed vector card)
               [rowno cand] (map-indexed vector line)
               :when (= cand number)]
           [lineno rowno])))

(defn cross [number card]
  (if-let [pos (find-in number card)]
    (update-in card pos (constantly true))
    card))

(defn won? [card]
  (when (or (some (partial every? true?) card)
            (some (partial every? true?) (apply mapv vector card)))
    card))

(defn score [card draw]
  (->> card
       flatten
       (filter number?)
       (apply +)
       (* draw)))

(def part1
  (reduce (fn [cards draw]
            (let [new-cards (map (partial cross draw) cards)]
              (if-let [winner (some won? new-cards)]
                (reduced (score winner draw))
                new-cards)))
          cards
          draws))
;; => 33348

(def part2
  (reduce (fn [cards draw]
            (let [new-cards (map (partial cross draw) cards)
                  remaining-cards (filter (complement won?) new-cards)]
              (if (empty? remaining-cards)  ; assume only one last winner
                (reduced (score (first new-cards) draw))
                remaining-cards)))
          cards
          draws))
;; => 8112