import Data.List.Split (splitOn) import Data.List (foldl', transpose) import qualified Data.Vector.Unboxed as VU import Data.Vector.Unboxed (Vector) hashChar :: Char -> Int hashChar '#' = 1 hashChar '.' = 0 lineToInt :: String -> Int lineToInt = foldl' (\x y -> 2 * x + hashChar y) 0 matchesAt :: Vector Int -> Int -> Bool matchesAt v i = VU.reverse rightSide == leftSide where nMirrored = min i $ VU.length v - i leftSide = VU.slice (i - nMirrored) nMirrored v rightSide = VU.slice i nMirrored v findMatches :: Vector Int -> [Int] findMatches v = filter (matchesAt v) [1 .. VU.length v - 1] solveDirection :: [String] -> Int solveDirection = sum . findMatches . VU.fromList . map lineToInt solve :: [String] -> Int solve l = 100 * solveDirection l + (solveDirection . transpose) l main :: IO () main = print . sum . map (solve . lines) . splitOn "\n\n" =<< readFile "data.txt"