import Control.Arrow import Control.Lens import Data.Function import Data.Ix import Data.List import Data.Ord import Linear.V2 main :: IO () main = interact $ show . (day11 1 &&& day11 999999) . parse . lines day11 :: V2 Int -> [V2 Int] -> Int day11 n = (`div` 2) . sum . f . (expandBy n =<< 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) expandBy :: V2 Int -> [V2 Int] -> [V2 Int] -> [V2 Int] expandBy _ [] input = input expandBy n (d:ds) input = expandBy n (map (moveCoord n d) ds) (map (moveCoord n 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 -> V2 Int 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