2022-12-30 15:11:20 +01:00
import Control.Lens
2023-01-05 13:58:32 +01:00
import Data.List.Split
2022-12-30 15:11:20 +01:00
import Linear.V2
type Sensor = ( V2 Int , V2 Int )
2023-01-05 13:58:32 +01:00
2022-12-30 15:11:20 +01:00
main :: IO ()
main = do
input <- map ( splitOneOf " =,: " ) . lines <$> readFile " input "
2023-01-05 13:58:32 +01:00
let sensors = map parse input
2023-01-05 15:06:45 +01:00
print $ " Cave from to: " ++ show ( caveMinMaxX sensors )
print $ part1 ( caveMinMaxX sensors ) sensors
print $ part2 sensors
2022-12-30 15:11:20 +01:00
2023-01-05 13:58:32 +01:00
getBorder :: [ Sensor ] -> [ V2 Int ]
2023-01-05 15:06:45 +01:00
getBorder ( s : ss ) = map ( + fst s ) xs ++ getBorder ss
where
xs =
concat $ take 4 $ iterate ( map perp ) [ V2 x ( d - x ) | x <- [ 0 .. pred d ] ]
d = succ $ dist s
getBorder [] = []
2022-12-30 15:11:20 +01:00
2023-01-05 13:58:32 +01:00
caveMinMaxX :: [ Sensor ] -> ( Int , Int )
caveMinMaxX sensors = ( minimum k , maximum l )
where
d = map dist sensors
s = map ( view _y . fst ) sensors
k = zipWith ( - ) s d
l = zipWith ( + ) s d
2022-12-30 15:11:20 +01:00
2023-01-05 13:58:32 +01:00
part1 :: ( Int , Int ) -> [ Sensor ] -> Int
part1 ( a , b ) sensors = length $ filter ( == '#' ) $ map ( checkPoint sensors ) xs
where
xs = [ V2 x 2000000 | x <- [ a .. b ] ] --y=10 for testinput
2022-12-30 15:11:20 +01:00
2023-01-05 15:06:45 +01:00
part2 :: [ Sensor ] -> Int
part2 sensors =
f $
head $
filter ( \ x -> checkPoint sensors x == ' ' ) $
filter ( \ ( V2 x y ) -> x >= 0 && x <= 4000000 && y >= 0 && y <= 4000000 ) $
getBorder sensors -- <=20 for testinput
where
f = ( + ) <$> view _y <*> ( ( * ) 4000000 . view _x )
2023-01-05 13:58:32 +01:00
parse :: [ String ] -> Sensor
parse [ _ , a , _ , b , _ , c , _ , d ] = ( V2 ( read a ) ( read b ) , V2 ( read c ) ( read d ) )
2022-12-30 15:11:20 +01:00
2023-01-05 13:58:32 +01:00
checkPoint :: [ Sensor ] -> V2 Int -> Char
checkPoint sensors point
| point ` elem ` map fst sensors = 'S'
| point ` elem ` map snd sensors = 'B'
| otherwise = checkPoint' sensors point
2022-12-30 15:11:20 +01:00
where
2023-01-05 13:58:32 +01:00
checkPoint' ( s : ss ) p =
if dist ( fst s , p ) <= dist s
then '#'
else checkPoint' ss p
checkPoint' [] _ = ' '
dist :: Sensor -> Int
dist ( a , b ) = sum $ abs $ a - b