Created
December 15, 2022 21:27
-
-
Save skatenerd/cabfcd6bf07697854c1b69be0ceba0bf to your computer and use it in GitHub Desktop.
day fifteen
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
{-# LANGUAGE OverloadedStrings #-} | |
module DayFifteen | |
( main | |
) where | |
import qualified Data.Maybe as M | |
import qualified Data.Ord as O | |
import qualified Data.Text as T | |
import qualified Data.Text.IO as TI | |
import qualified Data.List as L | |
import qualified Data.List.Split as LS | |
import qualified Data.Set as S | |
import qualified Data.Function as F | |
import Data.Range | |
import Debug.Trace | |
data Coordinate = Coordinate { x :: Int, y :: Int } deriving (Eq, Ord, Show) | |
data InputFact = InputFact { sensor :: Coordinate, beacon :: Coordinate } deriving (Eq, Show) | |
distanceToRow coordinate row = manhattan coordinate (Coordinate (x coordinate) row) | |
radius InputFact { sensor, beacon } = manhattan sensor beacon | |
parse line = InputFact { sensor=(Coordinate sensorX sensorY), beacon=(Coordinate beaconX beaconY)} | |
where splitted = T.split (`L.elem` splitters) line | |
splitters :: String = ",=:" | |
sensorX = readText (splitted !! 1) | |
sensorY = readText (splitted !! 3) | |
beaconX = readText (splitted !! 5) | |
beaconY = readText (splitted !! 7) | |
readText = read . T.unpack | |
manhattan Coordinate{x=fromX,y=fromY} Coordinate{x=toX,y=toY} = (abs (fromX - toX)) + (abs (fromY - toY)) | |
testInput :: [T.Text] | |
testInput = [ | |
"Sensor at x=2, y=18: closest beacon is at x=-2, y=15", | |
"Sensor at x=9, y=16: closest beacon is at x=10, y=16", | |
"Sensor at x=13, y=2: closest beacon is at x=15, y=3", | |
"Sensor at x=12, y=14: closest beacon is at x=10, y=16", | |
"Sensor at x=10, y=20: closest beacon is at x=10, y=16", | |
"Sensor at x=14, y=17: closest beacon is at x=10, y=16", | |
"Sensor at x=8, y=7: closest beacon is at x=2, y=10", | |
"Sensor at x=2, y=0: closest beacon is at x=2, y=10", | |
"Sensor at x=0, y=11: closest beacon is at x=2, y=10", | |
"Sensor at x=20, y=14: closest beacon is at x=25, y=17", | |
"Sensor at x=17, y=20: closest beacon is at x=21, y=22", | |
"Sensor at x=16, y=7: closest beacon is at x=15, y=3", | |
"Sensor at x=14, y=3: closest beacon is at x=15, y=3", | |
"Sensor at x=20, y=1: closest beacon is at x=15, y=3" | |
] | |
testFacts = map parse testInput | |
emptyRange = 1 *=* 1 | |
getFootprintInTargetRow targetRow fact | |
| relativeRadius >= 1 = low +=+ high | |
| relativeRadius == 0 = SingletonRange (x theSensor) | |
| otherwise = emptyRange | |
where relativeRadius = (radius fact) - (distanceToRow theSensor targetRow) | |
theSensor = sensor fact | |
low = (x theSensor) - relativeRadius | |
high = ((x theSensor) + relativeRadius) | |
main targetRow facts = S.size realAnswer | |
where overcount = fromRanges $ mergeRanges $ map (getFootprintInTargetRow targetRow) facts | |
overcountCoordinates = S.fromList $ map (\x -> (Coordinate x targetRow)) overcount | |
realAnswer = S.difference overcountCoordinates beacons | |
beacons = S.fromList $ map beacon facts | |
rowIsInteresting minX maxX facts targetRow = [wholeRange] /= (intersection wholeFootprint [wholeRange]) | |
where wholeRange = minX +=+ maxX | |
wholeFootprint = joinRanges $ map (getFootprintInTargetRow targetRow) facts | |
partTwo facts minX maxX minY maxY = filter (rowIsInteresting minX maxX facts) [minY..maxY] | |
getLines path = do | |
input <- TI.readFile path | |
return $ T.lines input |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment