55 lines
1.9 KiB
Haskell
55 lines
1.9 KiB
Haskell
import Data.List.Split (splitOn)
|
|
import qualified Data.Set as S
|
|
|
|
type Coord = (Int, Int)
|
|
|
|
readCoord :: String -> Coord
|
|
readCoord s = read ("(" ++ s ++ ")")
|
|
|
|
readLine :: String -> [Coord]
|
|
readLine xs = map readCoord (splitOn " -> " xs)
|
|
|
|
interpolate :: Coord -> Coord -> S.Set Coord
|
|
interpolate (a,b) (x,y)
|
|
| a == x && b == y = S.singleton (a,b)
|
|
| a == x && b < y = S.insert (a,b) (interpolate (a,b+1) (x,y))
|
|
| a == x && b > y = S.insert (a,b) (interpolate (a,b-1) (x,y))
|
|
| a < x && b == y = S.insert (a,b) (interpolate (a+1,b) (x,y))
|
|
| a > x && b == y = S.insert (a,b) (interpolate (a-1,b) (x,y))
|
|
|
|
interpolateLine :: [Coord] -> S.Set Coord
|
|
interpolateLine [x,y] = interpolate x y
|
|
interpolateLine (x:y:xs) = S.union (interpolate x y) (interpolateLine (y:xs))
|
|
|
|
part1 :: Coord -> S.Set Coord -> Int -> Int
|
|
part1 (x,y) occupied limit
|
|
| y > limit = 0
|
|
| S.notMember (x,y+1) occupied = part1 (x, y+1) occupied limit
|
|
| S.notMember (x-1, y+1) occupied = part1 (x-1, y+1) occupied limit
|
|
| S.notMember (x+1, y+1) occupied = part1 (x+1, y+1) occupied limit
|
|
| otherwise = 1 + part1 (500,0) (S.insert (x,y) occupied) limit
|
|
|
|
part2 :: Coord -> S.Set Coord -> Int -> Int
|
|
part2 (x,y) occupied limit
|
|
| S.member (500,0) occupied = 0
|
|
| y+1 == limit+2 = 1 + part2 (500,0) (S.insert (x,y) occupied) limit
|
|
| S.notMember (x,y+1) occupied = part2 (x, y+1) occupied limit
|
|
| S.notMember (x-1, y+1) occupied = part2 (x-1, y+1) occupied limit
|
|
| S.notMember (x+1, y+1) occupied = part2 (x+1, y+1) occupied limit
|
|
| otherwise = 1 + part2 (500,0) (S.insert (x,y) occupied) limit
|
|
|
|
|
|
|
|
main :: IO ()
|
|
main = do
|
|
x <- map readLine . lines <$> getContents
|
|
let rocks = foldr1 S.union (map interpolateLine x)
|
|
|
|
let start = (500,0)
|
|
let lowest = maximum (map snd (S.toList rocks))
|
|
|
|
putStr "part 1: "
|
|
print $ part1 (500,0) rocks lowest
|
|
|
|
putStr "part 2: "
|
|
print $ part2 (500,0) rocks lowest |