Created
December 10, 2023 16:47
-
-
Save seltzer1717/6a9192e2edfe0ac28419f9d9a53dac8d to your computer and use it in GitHub Desktop.
Day 3a Solution
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns cloud.seltzer1717.aoc.day3a | |
(:require [clojure.set :as set] | |
[clojure.pprint :as pretty]) | |
(:import (java.io BufferedReader FileReader) | |
(java.nio.file Files Paths))) | |
(def symbolPattern #"(?<symbol>[^\.\d])") | |
(def partPattern #"(?<part>\d+)") | |
(defn getPartAdjacents | |
"Takes part and returns set of part adjacents." | |
[[lineIndex startPosition endPosition]] | |
(as-> #{} $ | |
(reduce conj $ (for [col (range (dec startPosition) (+ 2 endPosition))] [(dec lineIndex) col])) ;; below | |
(reduce conj $ (for [col (range (dec startPosition) (+ 2 endPosition))] [(inc lineIndex) col])) ;; above | |
(reduce conj $ #{[lineIndex (dec startPosition)] [lineIndex (inc endPosition)]}))) | |
(defn partNumber? | |
"Takes part: symbolAdjacents, partNumber(lineIndex, startColumn, endColumn) | |
and returns whether partNumber is valid part number: | |
#,$ - symbols | |
nbr - 1234, 789 | |
. - unoccupied position | |
a - adjacent position to symbol | |
A - adjacent position to part number | |
000000000011 | |
012345678901 | |
00........$... | |
01...aaa...... | |
02...a#aAAAA.. | |
03bbbba1234A.. | |
04....AAAAAA.. | |
05..789....... | |
#,$ - #{[2 4] [0 8]} | |
1234 - #{[2 4] [2 5] [2 6] [2 7] [2 8] [2 9] [3 4] [3 9] [[4 4] [4 5] [4 6] [4 7] [4 8] [4 9]]} | |
Intersection of adjacents: symbols, 1234 is: #{[2 4]} - valid part number. | |
Intersection of adjacents: symbols, 789 is: #{} - not valid part number." | |
[symbolLocations [lineIndex startPosition endPosition :as part]] | |
(let [partAdjacents (getPartAdjacents part)] ;; left, right ends | |
(pos? (count (set/intersection symbolLocations partAdjacents))))) | |
(defn getSymbolsInLine | |
"Takes line, returns set of symbols." | |
[line lineIndex] | |
(let [symbolMatcher (.matcher symbolPattern line)] | |
(loop [symbols #{}] | |
(if (.find symbolMatcher) | |
(recur (conj symbols {:symbol (.group symbolMatcher "symbol") | |
:location [lineIndex (.start symbolMatcher)]})) | |
symbols)))) | |
(defn getPartsInLine | |
"Takes line, returns set of symbols." | |
[line lineIndex] | |
(let [partMatcher (.matcher partPattern line)] | |
(loop [parts #{}] | |
(if (.find partMatcher) | |
(recur (conj parts {:content (.group partMatcher "part") | |
:location [lineIndex (.start partMatcher) (dec (.end partMatcher))]})) | |
parts)))) | |
(defn getSumOfPartNumbers | |
"Takes schematic returns sum of part numbers." | |
[schematicPath] | |
(with-open [schematicReader (BufferedReader. (FileReader. schematicPath))] | |
(let [[symbols parts] | |
(loop [line (.readLine schematicReader) | |
lineIndex 0 | |
symbols #{} | |
parts #{}] | |
(if line | |
(recur (.readLine schematicReader) | |
(inc lineIndex) | |
(concat symbols (getSymbolsInLine line lineIndex)) | |
(concat parts (getPartsInLine line lineIndex))) | |
[symbols parts]))] | |
(let [symbolLocations (set (map :location symbols))] | |
(loop [prts parts | |
{:keys [content location] :as prt} (first prts) | |
actualParts []] | |
(if prt | |
(let [newPrts (rest prts) | |
newPrt (first newPrts)] | |
(recur newPrts | |
newPrt | |
(if (partNumber? symbolLocations location) | |
(conj actualParts (Integer/parseInt content)) | |
actualParts))) | |
(apply + actualParts))))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment