49 lines
1.7 KiB
Haskell
49 lines
1.7 KiB
Haskell
import Data.List (find)
|
|
import Data.Map qualified as M
|
|
import Data.Maybe (catMaybes, isNothing, mapMaybe)
|
|
import Data.Set qualified as S
|
|
import Lib (buildGrid, readFile')
|
|
|
|
data Direction = East | West | North | South deriving (Show, Eq)
|
|
|
|
type Coord = (Int, Int)
|
|
|
|
main :: IO ()
|
|
main = do
|
|
grid <- buildGrid . lines <$> readFile "day10.in"
|
|
let [((sx, sy), _)] = M.toList $ M.filter (== 'S') grid
|
|
let path =
|
|
head $
|
|
mapMaybe
|
|
(uncurry $ travel grid [])
|
|
[ ((sx - 1, sy), North),
|
|
((sx, sy + 1), East)
|
|
]
|
|
|
|
putStr "Q1: "
|
|
print $ div (length path) 2
|
|
|
|
putStr "Q2: "
|
|
print $ pick (shoelace path) (length path)
|
|
|
|
travel :: M.Map Coord Char -> [Coord] -> Coord -> Direction -> Maybe [Coord]
|
|
travel grid a c@(x, y) d
|
|
| isNothing (M.lookup c grid) || cur == '.' = Nothing
|
|
| cur == 'S' = Just $ c : a
|
|
| (cur, d) `elem` [('L', West), ('|', North), ('J', East)] = travel grid (c : a) (x - 1, y) North
|
|
| (cur, d) `elem` [('F', West), ('|', South), ('7', East)] = travel grid (c : a) (x + 1, y) South
|
|
| (cur, d) `elem` [('L', South), ('-', East), ('F', North)] = travel grid (c : a) (x, y + 1) East
|
|
| (cur, d) `elem` [('J', South), ('-', West), ('7', North)] = travel grid (c : a) (x, y - 1) West
|
|
where
|
|
cur = grid M.! c
|
|
|
|
-- https://en.wikipedia.org/wiki/Shoelace_formula
|
|
-- this just uses trapezoids/triangles from consecutive points
|
|
shoelace :: [Coord] -> Int
|
|
shoelace xs = flip div 2 . abs . sum $ zipWith (\(x1, y1) (x2, y2) -> (x1 * y2) - (x2 * y1)) xs (tail $ cycle xs)
|
|
|
|
-- https://en.wikipedia.org/wiki/Pick%27s_theorem
|
|
-- area -> path length -> integers inside
|
|
pick :: Int -> Int -> Int
|
|
pick a b = (a + 1) - div b 2
|