aoc-2021/5/5.hs
Jack Bond-Preston 08fe41ccd5 day 5
Signed-off-by: Jack Bond-Preston <jackbondpreston@outlook.com>
2021-12-12 02:22:40 +00:00

75 lines
1.8 KiB
Haskell

import System.IO
( hClose, openFile, hGetContents, IOMode(ReadMode) )
import Text.Parsec
import Text.Parsec.String
import Control.Monad
import Data.List
import Data.Maybe
import Data.Sequence (replicate, Seq, mapWithIndex)
import Data.Map (Map, (!))
import qualified Data.Map as Map
type Coord = (Int, Int)
type LineEnds = (Coord, Coord)
type Grid = Map Coord Integer
int :: Parser Int
int = read <$> many1 digit
eol :: Parser ()
eol = void $ char '\n'
coord :: Parser Coord
coord = do
x <- int
char ','
y <- int
return (x, y)
arrow :: Parser ()
arrow = void $ string " -> "
line :: Parser LineEnds
line = do
from <- coord
arrow
to <- coord
return (from, to)
inputParser :: Parser [LineEnds]
inputParser = line `endBy1` eol
lineToCellList :: LineEnds -> [Coord]
lineToCellList ((x0, y0), (x1, y1))
| x0 == x1 = [ (x0, y) | y <- [min y0 y1 .. max y0 y1] ]
| y0 == y1 = [ (x, y0) | x <- [min x0 x1 .. max x0 x1] ]
| otherwise = [ (x, y) | x <- [min x0 x1 .. max x0 x1],
y <- [min y0 y1 .. max y0 y1],
abs (x - x0) == abs (y - y0) ]
type CoordMap = Map Coord Int
scoreFold :: Coord -> (CoordMap, Int) -> (CoordMap, Int)
scoreFold coord (map, acc)
| Map.member coord map = if
(map ! coord) == 1 then (Map.adjust (+1) coord map, acc + 1)
else (Map.adjust (+1) coord map, acc)
| otherwise = (Map.insert coord 1 map, acc)
score :: [LineEnds] -> Int
score les = snd (foldr scoreFold (Map.empty, 0) coords)
where
coords = concatMap lineToCellList les
main = do
handle <- openFile "input.txt" ReadMode
contents <- hGetContents handle
case parse inputParser "" contents of
Left x -> print x
Right x -> print (score x)
hClose handle