54 lines
1.3 KiB
Haskell
54 lines
1.3 KiB
Haskell
import Data.Array
|
|
import Text.Printf (printf)
|
|
|
|
ioAssert True _ = return ()
|
|
ioAssert False msg = fail msg
|
|
|
|
testInput =
|
|
[ "..##......."
|
|
, "#...#...#.."
|
|
, ".#....#..#."
|
|
, "..#.#...#.#"
|
|
, ".#...##..#."
|
|
, "..#.##....."
|
|
, ".#.#.#....#"
|
|
, ".#........#"
|
|
, "#.##...#..."
|
|
, "#...##....#"
|
|
, ".#..#...#.#"
|
|
]
|
|
|
|
data Field = Open | Tree deriving (Eq)
|
|
|
|
parseField :: Char -> Field
|
|
parseField '.' = Open
|
|
parseField '#' = Tree
|
|
|
|
parseInput :: [String] -> Array (Int, Int) Field
|
|
parseInput rows =
|
|
listArray ((0, 0), (maxY - 1 , maxX - 1)) $ concat $ map (map parseField) rows
|
|
where maxX = (length $ head rows) - 1
|
|
maxY = (length rows) - 1
|
|
|
|
solve :: Array (Int, Int) Field -> (Int, Int) -> Int
|
|
solve input = length . filter (==Tree) . path input
|
|
|
|
part1 = flip solve (3, 1)
|
|
part2 input = product $ map (solve input) [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
|
|
|
|
path arr (dX, dY) =
|
|
let ((_, _), (height, width)) = bounds arr
|
|
in [arr ! (y, x) | (i, y) <- zip [0,dX..] [0,dY..height],
|
|
let x = mod i (width + 1)]
|
|
|
|
main = do
|
|
input <- parseInput . lines <$> readFile "input"
|
|
runTests
|
|
putStr $ printf "Part 1: %d\n" $ part1 input
|
|
putStr $ printf "Part 2: %d\n" $ part2 input
|
|
|
|
runTests = do
|
|
ioAssert (7 == (part1 $ parseInput testInput)) "part1"
|
|
ioAssert (336 == (part2 $ parseInput testInput)) "part2"
|
|
putStrLn "Tests ok"
|