module Commons where import GHC.IO.Handle (isEOF) import Data.Array (Array, listArray, (!), indices) import Data.List.Unique (sortUniq) type Image = [(Int, Int)] type ExpansionArray = Array Int Int parseLine :: Int -> Int -> String -> Image parseLine _ _ [] = [] parseLine row column ('#': t) = (column, row): parseLine row (column + 1) t parseLine row column (_: t) = parseLine row (column + 1) t parseImage :: Int -> Image -> IO Image parseImage row image = do done <- isEOF if done then return image else do line <- getLine parseImage (row + 1) (image ++ parseLine row 1 line) parse :: IO Image parse = parseImage 1 [] getExpansionArray :: Int -> Int -> Int -> [Int] -> [Int] getExpansionArray _ _ _ [] = [] getExpansionArray i expOffset expInc (h: t) | i == h = i + expOffset: getExpansionArray (i + 1) expOffset expInc t | i < h = i + expOffset: getExpansionArray (i + 1) (expOffset + expInc) expInc (h: t) getExpansionArrays :: Int -> Image -> (ExpansionArray, ExpansionArray) getExpansionArrays expInc image = let expX = getExpansionArray 1 0 expInc $ sortUniq . map fst $ image expY = getExpansionArray 1 0 expInc $ sortUniq . map snd $ image in (listArray (1, length expX) expX, listArray (1, length expY) expY) getDistancesGalaxy :: Image -> (ExpansionArray, ExpansionArray) -> (Int, Int) -> [Int] getDistancesGalaxy [] _ _ = [] getDistancesGalaxy ((x0, y0): t) (expX, expY) (x1, y1) = abs ((expX ! x0) - (expX ! x1)) + abs ((expY ! y0) - (expY ! y1)): getDistancesGalaxy t (expX, expY) (x1, y1) getDistances :: Image -> (ExpansionArray, ExpansionArray) -> [[Int]] getDistances [] _ = [] getDistances (h: t) (expX, expY) = getDistancesGalaxy t (expX, expY) h: getDistances t (expX, expY)