{-# LANGUAGE TupleSections #-} import Data.List -- this is literally only a function because read is stupid parse :: String -> [[Int]] parse = map (map (read . singleton)) . lines getGridSize :: [[a]] -> (Int, Int) getGridSize grid = (length $ head grid, length grid) getScenicScore :: [[Int]] -> (Int, Int) -> Int getScenicScore grid (x, y) = product $ map startStep [(-1, 0), (1, 0), (0, -1), (0, 1)] where startGridValue = grid !! y !! x (gridWidth, gridHeight) = getGridSize grid startStep (facingX, facingY) = scenicScoreStep (x + facingX, y + facingY) (facingX, facingY) scenicScoreStep (gridX, gridY) (facingX, facingY) | gridX < 0 || gridY < 0 || gridX > (gridWidth - 1) || gridY > (gridHeight - 1) = 0 | (grid !! gridY !! gridX) < startGridValue = 1 + scenicScoreStep (gridX + facingX, gridY + facingY) (facingX, facingY) | otherwise = 1 listPermutations :: [a] -> [a] -> [(a, a)] listPermutations a = concatMap (\b' -> map (, b') a) getAllCoordinates grid = listPermutations [0..gridWidth-1] [0..gridHeight-1] where (gridWidth, gridHeight) = getGridSize grid main = interact $ show . maximum . (\grid -> map (getScenicScore grid) $ getAllCoordinates grid) . parse