73 lines
1.8 KiB
Haskell
73 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)
|
||
|
|
||
|
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
|