Skip to content

Instantly share code, notes, and snippets.

Last active December 3, 2018 13:13
What would you like to do?
Advent of Code 2018 - Day 3
(ns aoc.aoc3
(:require [clojure.string :as s]
[clojure.set :as set]))
(defrecord Claim [claim-number squares])
(defn convert-to-grid
"Converts a claim into a sequence of 'taken' squares."
[claim grid-width]
;; Named groups would be great here, but Clojure doesn't support this natively.
(let [matcher #"#(?<claim>\d+)\s@\s(?<x>\d+),(?<y>\d+):\s(?<width>\d+)x(?<height>\d+)$"
matches (re-find matcher claim)
[_ claim horiz vert width height] matches
x (Integer. horiz)
y (Integer. vert)
w (Integer. width)
h (Integer. height)
rows (take h (iterate inc y))]
(->> (map #(range (+ x (* grid-width %)) (+ (+ x w) (* grid-width %))) rows)
(Claim. (Integer. claim) ))))
(defn get-overlap
"returns the amount of overlap based on calculated inputs.
Answer provided in square units matching the units entered
(for the case of the problem, square inches)."
;; Perform intersection to find any matches, then union to combine; repeat through the list.
(loop [mapped-area (map #(convert-to-grid % 1000) claims)
shared-fabric #{}
intersections #{}]
(if (empty? mapped-area)
(let [intersect (set/intersection shared-fabric (:squares (first mapped-area)))
union (set/union shared-fabric (:squares (first mapped-area)))]
(recur (rest mapped-area) union (set/union intersections intersect))))))
(defn overlapping-claim [c1 c2]
(= (:claim-number c1) (:claim-number c2)) nil
(not-empty (set/intersection (:squares c1) (:squares c2))) c2))
(defn find-no-overlap
"given a set of input claims, find the claim that has no overlap
with any other claims."
(let [grid-claims (map #(convert-to-grid % 1000) claims)]
(loop [idx 0 ignores #{}]
(if-not (contains? (:claim-id (nth grid-claims idx)) ignores)
(if-let [overlap (some #(overlapping-claim (nth grid-claims idx) %) grid-claims)]
(recur (inc idx) (conj ignores (:claim-number overlap)))
(:claim-number (nth grid-claims idx)))
(recur (inc idx) ignores)))))
(ns aoc.aoc3-test
(:require [aoc.aoc3 :as sut]
[clojure.test :refer :all]))
(deftest convert-to-grid-test
(testing "convert-to-grid"
(testing "a simple example"
(is (= (set '(2 3 4 7 8 9 12 13 14)) (:squares (sut/convert-to-grid "#1 @ 2,0: 3x3" 5)))))))
(deftest part1
(testing "provided example"
(let [input-values ["#1 @ 1,3: 4x4"
"#2 @ 3,1: 4x4"
"#3 @ 5,5: 2x2"]]
(is (= 4 (count (sut/get-overlap input-values)))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment