🎄 Advent of Clerk: Day 3

(ns advent-of-clerk.day-03
(:require #?@(:bb [] :clj [[nextjournal.clerk :as clerk]])
[advent-of-clerk.utils :as utils]
[clojure.set :as cset]
[clojure.string :as str]))
(def input (->> (utils/load-input "day_03.txt")
(str/split-lines)))
["
gvNbShZZgQfWdQhdPQmggLTFLwmwjFqjVVgM"
"
CsJnHllcsnnnnJrGRnRwPPLVmFLHLBjFFVHmPT"
"
JlnCtctJnJDcJlDCRpPrSSQWfphzWZfbZSvfNfbS"
"
WjvRSdSQjvpjWzNlnZlNZqCCMzZZ"
"
nJtJsbctPBPwLNcDZNNGLClC"
"
tsFJHBgJwgJbnvSHHWVWHhVhpQ"
"
zRzPhCCSHVZzfGHZ"
"
qBsWBpqBwBcvqqWgdfZrprdggPHHVZ"
"
WWmvwvBbnWmnwvWcbmWWnqNCRSDRRSSjjSDbPJbRjClLhC"
"
rQrznfHHhrHzllzlzTGcJgtJ"
"
jhhjjSZVPWVZvSFtTttLTglgFtvm"
"
dqSCqVWdbDSSVqbVVSqhNdrnpnCnfsnnwfnsRpMpBMrf"
"
rTnvrSSHvHtnDQVDtfmW"
"
ZjCglhcCJschpZbZgbtGmRtbGmwtQtbmtN"
"
FFZCghFJhlslFpjcdFTPLHHmrqTMTdzBLHLH"
"
WzDfrDwwDCCDMnfDHHJjTHTtNdngdHtQ"
"
FmScGPPPPmpspchbGHtRsjdJJJWJWNttgH"
"
bvhFlVhPchPvqWLwqLWqvq"
"
RcchVlCCvmhDRjNJJJjbjllZlJ"
"
wPwFGFMPfpdtqbpwFFfGPQZTWTZjtzQWTBBQJzZjZZ"
280 more elided]
(def ex-input
["vJrwpWtwJgWrhcsFMMfFFhFp"
"jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL"
"PmmdzqPrVvPwwTWBwg"
"wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn"
"ttgJtRGJQctTZtZT"
"CrZsJsPPZsGzwwsLwLmpwMDw"])
["
vJrwpWtwJgWrhcsFMMfFFhFp"
"
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL"
"
PmmdzqPrVvPwwTWBwg"
"
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn"
"
ttgJtRGJQctTZtZT"
"
CrZsJsPPZsGzwwsLwLmpwMDw"
]

Part 1

(defn type->prio [c]
(let [n (int c)]
(if (> n 90)
(- n 96)
(+ 27 (- n 65)))))
#object[advent_of_clerk.day_03$type__GT_prio 0x16a475d3 "
advent_of_clerk.day_03$type__GT_prio@16a475d3"
]
(defn prio->type [n] ;; unnecessary, just for debugging
(char (if (< n 27)
(+ n 96)
(+ 65 (- n 27)))))
#object[advent_of_clerk.day_03$prio__GT_type 0x7b9e4b0d "
advent_of_clerk.day_03$prio__GT_type@7b9e4b0d"
]
(defn parse-input-1 [input]
(let [split-half #(split-at (/ (count %) 2) %)]
(map #(->> %
(map type->prio)
split-half
(map set))
input)))
#object[advent_of_clerk.day_03$parse_input_1 0x1e22ff5f "
advent_of_clerk.day_03$parse_input_1@1e22ff5f"
]
(defn compartment-intersections [rucksacks]
(map #(apply cset/intersection %)
rucksacks))
#object[advent_of_clerk.day_03$compartment_intersections 0x49592e11 "
advent_of_clerk.day_03$compartment_intersections@49592e11"
]
(defn solve-1
[input]
(->> input
parse-input-1
compartment-intersections
(map (partial reduce +))
(reduce +)))
#object[advent_of_clerk.day_03$solve_1 0x7ce6c004 "
advent_of_clerk.day_03$solve_1@7ce6c004"
]

Studies

(clerk/table
(clerk/use-headers (apply vector
["Char" "Unicode" "Char→Priority" "Priority→Char"]
(mapv (fn [c] [c (int c) (type->prio c)
(prio->type (type->prio c))])
"azAZ"))))
Char
Unicode
Char→Priority
Priority→Char
\a971\a
\z12226\z
\A6527\A
\Z9052\Z
(def rucksacks (parse-input-1 ex-input))
((#{7 16 18 20 22 23 36 49} #{3 6 8 16 19 32 39}) (#{10 17 26 30 33 34 38 40 44} #{6 18 19 32 38 39 45 52}) (#{4 13 17 18 26 42 48} #{7 22 23 28 42 46 49}) (#{8 17 22 23 34 38 39 52} #{2 3 10 14 22 28 32 43 45 46}) (#{7 20 33 36 44} #{3 20 43 46 52}) (#{18 19 26 29 33 36 42 52} #{13 16 19 23 30 38 39}))
(def shared-prios (compartment-intersections rucksacks))
(#{16} #{38} #{42} #{22} #{20} #{19})
(reduce + (map (partial reduce +) shared-prios))
157

Observations

  • order within compartments doesn’t matter
  • the category symbols are irrelevant, only their priorities matter

Part 2

(defn parse-input-2 [input]
(partition 3 (map #(->> % (map type->prio) set)
input)))
#object[advent_of_clerk.day_03$parse_input_2 0xeb069cb "
advent_of_clerk.day_03$parse_input_2@eb069cb"
]
(defn find-group-badges [inventory-groups]
(map (comp first (partial apply cset/intersection))
inventory-groups))
#object[advent_of_clerk.day_03$find_group_badges 0x17f74794 "
advent_of_clerk.day_03$find_group_badges@17f74794"
]
(defn solve-2
[input]
(->> input
parse-input-2
find-group-badges
(reduce +)))
#object[advent_of_clerk.day_03$solve_2 0x45149573 "
advent_of_clerk.day_03$solve_2@45149573"
]

Studies

(def inventory-groups (parse-input-2 ex-input))
((#{3 6 7 8 16 18 19 20 22 23 32 36 39 49} #{6 10 17 18 19 26 30 32 33 34 38 39 40 44 45 52} #{4 7 13 17 18 22 23 26 28 42 46 48 49}) (#{2 3 8 10 14 17 22 23 28 32 34 38 39 43 45 46 52} #{3 7 20 33 36 43 44 46 52} #{13 16 18 19 23 26 29 30 33 36 38 39 42 52}))
(apply cset/intersection (first inventory-groups))
#{18}
(apply cset/intersection (second inventory-groups))
#{52}

Observations

  • compartments are irrelevant here
(comment
)
nil