35 lines
1.1 KiB
Haskell
35 lines
1.1 KiB
Haskell
import Data.Function
|
|
import Data.Ix
|
|
import Control.Lens
|
|
import Data.List
|
|
import Data.Ord
|
|
import Linear.V2
|
|
|
|
main :: IO ()
|
|
main = interact $ show . day11 . parse . lines
|
|
|
|
day11 :: [V2 Int] -> Int
|
|
day11 = (`div` 2) . sum . f . (expand =<< findEmptyRows)
|
|
where f xs = [sum $ abs $ x-y | x<- xs, y<- xs]
|
|
|
|
parse :: [String] -> [V2 Int]
|
|
parse = map fst . filter ((=='#') . snd) . concat . zipWith (map . f) [0..] . map (zip [0..])
|
|
where f x (y,z) = (V2 y x, z)
|
|
|
|
|
|
expand :: [V2 Int] -> [V2 Int] -> [V2 Int]
|
|
expand [] input = input
|
|
expand (d:ds) input = expand (map (moveCoord d) ds) (map (moveCoord d) input)
|
|
|
|
|
|
findEmptyRows :: [V2 Int] -> [V2 Int]
|
|
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
|
|
|
|
moveCoord :: V2 Int -> V2 Int -> V2 Int
|
|
moveCoord x y = if y^.p >= x ^.p then y + signum x else y
|
|
where p = if x^._x == 0 then _y else _x
|