Skip to content

Instantly share code, notes, and snippets.

@seltzer1717
Created December 10, 2023 16:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seltzer1717/6a9192e2edfe0ac28419f9d9a53dac8d to your computer and use it in GitHub Desktop.
Save seltzer1717/6a9192e2edfe0ac28419f9d9a53dac8d to your computer and use it in GitHub Desktop.
Day 3a Solution
(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