2023-12-12 18:09:34 +01:00
import Control.Arrow
2023-12-12 18:09:46 +01:00
import Control.Lens
2023-12-12 18:03:08 +01:00
import Data.Function
import Data.Ix
import Data.List
import Data.Ord
import Linear.V2
main :: IO ()
2023-12-12 18:09:34 +01:00
main = interact $ show . ( day11 1 &&& day11 999999 ) . parse . lines
2023-12-12 18:03:08 +01:00
2023-12-12 18:09:34 +01:00
day11 :: V2 Int -> [ V2 Int ] -> Int
day11 n = ( ` div ` 2 ) . sum . f . ( expandBy n =<< findEmptyRows )
2023-12-12 18:09:46 +01:00
where
f xs = [ sum $ abs $ x - y | x <- xs , y <- xs ]
2023-12-12 18:03:08 +01:00
parse :: [ String ] -> [ V2 Int ]
2023-12-12 18:09:46 +01:00
parse =
map fst .
filter ( ( == '#' ) . snd ) . concat . zipWith ( map . f ) [ 0 .. ] . map ( zip [ 0 .. ] )
where
f x ( y , z ) = ( V2 y x , z )
2023-12-12 18:03:08 +01:00
2023-12-12 18:09:34 +01:00
expandBy :: V2 Int -> [ V2 Int ] -> [ V2 Int ] -> [ V2 Int ]
expandBy _ [] input = input
2023-12-12 18:09:46 +01:00
expandBy n ( d : ds ) input =
expandBy n ( map ( moveCoord n d ) ds ) ( map ( moveCoord n d ) input )
2023-12-12 18:03:08 +01:00
findEmptyRows :: [ V2 Int ] -> [ V2 Int ]
2023-12-12 18:09:46 +01:00
findEmptyRows input =
map flipV2 ( findEmptyRows $ map flipV2 input ) ++ findEmptyRows input
where
findEmptyRows = deleteFirstsBy ( ( == ) ` on ` view _x ) b
b = range ( V2 0 0 , set _y 0 maxP )
maxP = maximumBy ( comparing ( view _x ) ) input
flipV2 ( V2 x y ) = V2 y x
2023-12-12 18:03:08 +01:00
2023-12-12 18:09:34 +01:00
moveCoord :: V2 Int -> V2 Int -> V2 Int -> V2 Int
2023-12-12 18:09:46 +01:00
moveCoord n x y =
if y ^. p >= x ^. p
then y + n * signum x
else y
where
p =
if x ^. _x == 0
then _y
else _x