Last active
December 3, 2023 18:49
-
-
Save skatenerd/df3887c133f74b7296197214d51cf35a to your computer and use it in GitHub Desktop.
2023 Day 3 Advent of Code
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
module DayThree (module DayThree) where | |
import qualified Data.Text as T | |
import qualified Text.Read as TR | |
import qualified Data.Foldable as DF | |
import qualified Data.Maybe as M | |
import qualified Data.List.Safe as LS | |
import qualified Data.Set as S | |
import qualified Data.List as L | |
import qualified Data.Text.IO as TI | |
at world (row, col) = (world !! row) !! col | |
getNeighbors world row col = filter isLegal allNeighbors | |
where allNeighbors = do | |
r <- [row - 1, row, row + 1] | |
c <- [col - 1, col, col + 1] | |
[(r,c)] | |
isLegal (r,c) = (r,c) /= (row, col) && r >= 0 && c >= 0 && c < length (world !! 0) && r < length world | |
rowNeighbors world row col = filter (\(nr, nc) -> nr == row) (getNeighbors world row col) | |
partOne textWorld = sum $ M.catMaybes $ map (numFromIndices world) $ S.toList numberBlobs | |
where numberBlobs = S.fromList $ map (fullNumberIndices world) symbolNeighborIndices | |
world = (map T.unpack textWorld) | |
symbolIndices = filter isSymbol (allIndices world) | |
symbolNeighborIndices = concatMap nbrs symbolIndices | |
isSymbol (r,c) | |
| v == '.' = False | |
| v `elem` ('0' `enumFromTo` '9') = False | |
| otherwise = True | |
where v = world `at` (r,c) | |
nbrs (r,c) = getNeighbors world r c | |
partTwo textWorld = sum $ map scoreGear gearIndices | |
where gearIndices = filter (isGear world) (allIndices world) | |
scoreGear (r,c) = DF.product (gearNumbers world (r,c)) | |
world = map T.unpack textWorld | |
testWorld = ["467..114..", | |
"...*......", | |
"..35..633.", | |
"......#...", | |
"617*......", | |
".....+.58.", | |
"..592.....", | |
"......755.", | |
"...$.*....", | |
".664.598.."] | |
numFromIndices :: [String] -> S.Set (Int, Int) -> Maybe Int | |
numFromIndices world bunch = TR.readMaybe $ map (world `at`) (L.sort (S.toList bunch)) | |
fullNumberIndices :: [String] -> (Int, Int) -> S.Set (Int, Int) | |
fullNumberIndices world (row,col) = S.fromList $ go [] (row,col) | |
where go visitedSoFar (row,col) | |
| (world `at` (row, col) `elem` (enumFromTo '0' '9')) = (row,col):(concatMap (go ((row,col):visitedSoFar)) ((rowNeighbors world row col) L.\\ visitedSoFar)) | |
| otherwise = [] | |
isGear world (row,col) = hasStar && length (gearNumbers world (row, col)) == 2 | |
where hasStar = (world `at` (row, col)) == '*' | |
gearNumbers world (row,col) = S.fromList $ M.catMaybes $ map (numFromIndices world) bunches | |
where bunches = map (fullNumberIndices world) $ getNeighbors world row col | |
allIndices world = do | |
r <- 0 `enumFromTo` ((length world) - 1) | |
c <- 0 `enumFromTo` ((length (world !! 0)) - 1) | |
[(r,c)] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment