🎄 Advent of Clerk: Day 4

(ns advent-of-clerk.day-04
(:require #?@(:bb [] :clj [[nextjournal.clerk :as clerk]])
[advent-of-clerk.utils :as utils :refer [not-bb]]
[clojure.set :as cset]
[clojure.string :as cstr]))
(def input (->> (utils/load-input "day_04.txt")
(cstr/split-lines)))
["
34-82,33-81"
"
59-59,69-73"
"
6-96,98-99"
"
1-94,3-96"
"
13-92,20-64"
"
37-75,76-93"
"
5-98,6-6"
"
40-65,40-64"
"
13-63,84-91"
"
31-75,31-35"
"
83-96,86-96"
"
65-85,64-85"
"
85-85,36-86"
"
71-73,72-81"
"
3-91,91-92"
"
45-72,45-73"
"
42-70,42-58"
"
45-45,16-45"
"
2-59,49-58"
"
46-59,60-60"
980 more elided]
(def ex-input
["2-4,6-8"
"2-3,4-5"
"5-7,7-9"
"2-8,3-7"
"6-6,4-6"
"2-6,4-8"])
["
2-4,6-8"
"
2-3,4-5"
"
5-7,7-9"
"
2-8,3-7"
"
6-6,4-6"
"
2-6,4-8"
]

Part 1

(defn parse [input]
(map (comp (partial partition 2)
(partial map parse-long)
(partial re-seq #"\d+"))
input))
#object[advent_of_clerk.day_04$parse 0x60ed5158 "
advent_of_clerk.day_04$parse@60ed5158"
]
(defn intervals-contained?
[[[a1 a2] [b1 b2]]]
(or (and (>= b1 a1) (<= b2 a2))
(and (>= a1 b1) (<= a2 b2))))
#object[advent_of_clerk.day_04$intervals_contained_QMARK_ 0x318fd928 "
advent_of_clerk.day_04$intervals_contained_QMARK_@318fd928"
]
(defn solve-1
[input]
(->> input
parse
(filter intervals-contained?)
count))
#object[advent_of_clerk.day_04$solve_1 0x4c06f69f "
advent_of_clerk.day_04$solve_1@4c06f69f"
]

Studies

(def interval-groups (parse ex-input))
(((2 4) (6 8)) ((2 3) (4 5)) ((5 7) (7 9)) ((2 8) (3 7)) ((6 6) (4 6)) ((2 6) (4 8)))
(filter intervals-contained? interval-groups)
(((2 8) (3 7)) ((6 6) (4 6)))

Observations

  • which contains which is irrelevant
  • could be done with set operations but maybe too inefficient

Part 2

(defn intervals-overlap?
[[[a1 a2] [b1 b2]]]
(or (and (>= b1 a1) (<= b1 a2))
(and (>= a1 b1) (<= a1 b2))))
#object[advent_of_clerk.day_04$intervals_overlap_QMARK_ 0x144602ef "
advent_of_clerk.day_04$intervals_overlap_QMARK_@144602ef"
]
(defn solve-2
[input]
(->> input
parse
(filter intervals-overlap?)
count))
#object[advent_of_clerk.day_04$solve_2 0x1eabf6ae "
advent_of_clerk.day_04$solve_2@1eabf6ae"
]

Studies

(filter intervals-overlap? interval-groups)
(((5 7) (7 9)) ((2 8) (3 7)) ((6 6) (4 6)) ((2 6) (4 8)))
(defn get-bounds [intervals]
(reduce (fn [[lower-min upper-max] [lower upper]]
[(if (< lower lower-min) lower lower-min)
(if (> upper upper-max) upper upper-max)])
[##Inf 0] intervals))
#object[advent_of_clerk.day_04$get_bounds 0x51223aca "
advent_of_clerk.day_04$get_bounds@51223aca"
]
(defn get-intersection
[[[a1 a2] [b1 b2] :as group]]
(when (intervals-overlap? group)
[(max a1 b1) (min a2 b2)]))
#object[advent_of_clerk.day_04$get_intersection 0x2aeb8c7f "
advent_of_clerk.day_04$get_intersection@2aeb8c7f"
]
(defn make-chart [groups]
(let [[x-min x-max] (get-bounds (map get-bounds groups))
unit-h 0.3
margin 0.1
amount (count groups)
chart-h (+ (* amount unit-h)
(* (dec amount) margin))]
[:svg {:width "100%"
:view-box (str "0 0 " (inc x-max) " " chart-h)
:style {:margin "2rem 0"}
}
(into [:g]
(map-indexed
(fn [y [[a1 a2] [b1 b2] :as group]]
(into [:g]
(map-indexed
(fn [i [x1 x2]]
[:rect {:x (dec x1)
:y (* y (+ unit-h margin))
:width (inc (- x2 x1))
:height unit-h
:fill (cond
(== i 3) "#ff0076"
(== i 2) "#344a77"
(== i 1) "#253455"
:else "#090c14")}])
(let [overlap (get-intersection group)
bg [1 x-max]]
(if overlap
(concat [bg] group [overlap])
(concat [bg] group))))))
groups))]))
#object[advent_of_clerk.day_04$make_chart 0xe9ea2b7 "
advent_of_clerk.day_04$make_chart@e9ea2b7"
]
(not-bb
(clerk/html (make-chart interval-groups)))
(not-bb
(clerk/html (make-chart (parse input))))

Observations

  • the number of overlapping sections doesn’t matter
  • no interesting pattern in the overlap-viz :(
(comment
)
nil