Advertisement
Guest User

AoC #10

a guest
Dec 10th, 2023
1,791
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Haskell 2.12 KB | Source Code | 0 0
  1. {-# LANGUAGE ScopedTypeVariables #-}
  2.  
  3. import Data.Char
  4. import Data.Function
  5. import Data.List
  6. import Data.Maybe (Maybe, fromJust, isNothing, isJust)
  7. import Data.Bits
  8. import Data.Array
  9.  
  10. direction :: [(Int, Int)]
  11. direction = [(-1, 0), (0, 1), (1, 0), (0, -1)]
  12.  
  13. toDirection :: Char -> (Int, Int)
  14. toDirection c = case c of
  15.   '|' -> (0, 2)
  16.   '-' -> (1, 3)
  17.   'L' -> (0, 1)
  18.   'J' -> (0, 3)
  19.   '7' -> (2, 3)
  20.   'F' -> (1, 2)
  21.   _ -> (-1, -1)
  22.  
  23. otherDirection :: Char -> Int -> Int
  24. otherDirection c d
  25.   | f == d = s
  26.   | s == d = f
  27.   | otherwise = -1
  28.   where (f, s) = toDirection c
  29.  
  30. startPos :: [String] -> (Int, Int)
  31. startPos grid = (x, y)
  32.   where
  33.     x = fromJust . findIndex (\s -> 'S' `elem` s) $ grid
  34.     y = fromJust . elemIndex 'S' $ grid !! x
  35.  
  36. moveCell :: Int -> (Int, Int) -> (Int, Int)
  37. moveCell dir (x, y) = let (dx, dy) = direction !! dir in (x + dx, y + dy)
  38.  
  39. oppositeDirection :: Int -> Int = xor 2
  40.  
  41. getPath :: Char -> [String] -> (Int, Int) -> (Int, Int) -> Int -> [(Int, Int)]
  42. getPath fi grid (sx, sy) (tx, ty) dir
  43.   | not (inRange (0, m - 1) sx) || not (inRange (0, n - 1) sy) = []
  44.   | sx == tx && sy == ty && dir /= -1 = [(sx, sy)]
  45.   | otherwise = if od == -1 || null recr then [] else (sx, sy) : recr
  46.   where
  47.     m = length grid
  48.     n = length $ head grid
  49.     ch = grid !! sx !! sy
  50.     od = if dir == -1 then fst (toDirection fi) else otherDirection ch (oppositeDirection dir)
  51.     recr = getPath fi grid (moveCell od (sx, sy)) (tx, ty) od
  52.  
  53. getLoop :: [String] -> [(Int, Int)]
  54. getLoop grid = go ans
  55.   where
  56.     (sx, sy) = startPos grid
  57.     go c = getPath c grid (sx, sy) (sx, sy) (-1)
  58.     ans = fromJust $ find (not . null . go) "|-LJ7F"
  59.  
  60. shoeLace :: [(Int, Int)] -> Int
  61. shoeLace [_] = 0
  62. shoeLace ((x1, y1) : (x2, y2) : xs) = (y1 + y2) * (x2 - x1) + shoeLace ((x2, y2) : xs)
  63.  
  64. part1 :: [String] -> Int
  65. part1 grid = length (getLoop grid) `div` 2
  66.  
  67. --- I love Pick's Theorem
  68. part2 :: [String] -> Int
  69. part2 grid = let path = getLoop grid in (abs (shoeLace path) - length path + 3) `div` 2
  70.  
  71. main :: IO ()
  72. main = do
  73.   strings <- lines <$> getContents
  74.   print $ part1 strings
  75.   print $ part2 strings
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement