Day 18: Lavaduct Lagoon
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Haskell
import Data.ByteString.Char8 (unpack) import Data.Char (isDigit, isHexDigit) import Relude import qualified Relude.Unsafe as Unsafe import Text.ParserCombinators.ReadP data Dir = R | D | L | U deriving (Show, Eq) type Pos = (Int, Int) data Action = Action Dir Int deriving (Show, Eq) parse :: ByteString -> Maybe [(Action, Action)] parse = fmap fst . viaNonEmpty last . readP_to_S (sepBy1 parseAction (char '\n') <* char '\n' <* eof) . unpack where parseAction = do dir <- choice [U <$ char 'U', D <$ char 'D', L <$ char 'L', R <$ char 'R'] <* char ' ' x <- Unsafe.read <$> munch1 isDigit <* char ' ' y <- char '(' *> char '#' *> (Unsafe.read . ("0x" ++) <$> count 5 (satisfy isHexDigit)) dir' <- choice [R <$ char '0', D <$ char '1', L <$ char '2', U <$ char '3'] <* char ')' return (Action dir x, Action dir' y) vertices :: [Action] -> [Pos] vertices = scanl' (flip step) origin where step (Action U n) = first $ subtract n step (Action D n) = first (+ n) step (Action L n) = second $ subtract n step (Action R n) = second (+ n) origin :: Pos origin = (0, 0) area, perimeter, solve :: [Action] -> Int area a = (`div` 2) . abs . sum $ zipWith (-) x y where (p, rp) = (origin :) &&& (++ [origin]) $ vertices a x = zipWith (*) (fst <$> p) (snd <$> rp) y = zipWith (*) (snd <$> p) (fst <$> rp) perimeter = sum . fmap (\(Action _ n) -> n) solve = area &&& (`div` 2) . perimeter >>> uncurry (+) >>> succ part1, part2 :: [(Action, Action)] -> Int part1 = solve . fmap fst part2 = solve . fmap snd