#!/usr/bin/env nix-shell #!nix-shell --pure -i "runghc -- -i../" -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" import Aoc (readAndParseStdin, shoelace) import Text.Parsec (char, choice, count, digit, hexDigit, many1, sepBy, spaces, string) import Text.Parsec.String (Parser) main = do input <- readAndParseStdin parse print $ (score . map fst) input print $ (score . map snd) input score :: [(Direction, Int)] -> Int score input = round $ shoelace (calculateVertices input) + fromIntegral (perimiter input `div` 2) + 1 perimiter :: [(Direction, Int)] -> Int perimiter = sum . map snd calculateVertices :: [(Direction, Int)] -> [(Int, Int)] calculateVertices input = go input 0 0 where go [] hAcc vAcc = [] go ((d, c) : xs) hAcc vAcc = let (newHAcc, newVAcc) = calcAcc d c hAcc vAcc in (newHAcc, newVAcc) : go xs newHAcc newVAcc calcAcc :: Direction -> Int -> Int -> Int -> (Int, Int) calcAcc U c hAcc vAcc = (hAcc, vAcc - c) calcAcc D c hAcc vAcc = (hAcc, vAcc + c) calcAcc L c hAcc vAcc = (hAcc - c, vAcc) calcAcc R c hAcc vAcc = (hAcc + c, vAcc) parse :: Parser [((Direction, Int), (Direction, Int))] parse = parseLine `sepBy` char '\n' parseLine :: Parser ((Direction, Int), (Direction, Int)) parseLine = do p1d <- parseDirection <* spaces p1c <- read <$> many1 digit <* spaces p2c <- string "(#" *> count 5 hexDigit p2d <- parseNumericDirection <* char ')' return ((p1d, p1c), (p2d, read ("0x" ++ p2c))) parseDirection :: Parser Direction parseDirection = choice [ U <$ char 'U', D <$ char 'D', L <$ char 'L', R <$ char 'R' ] parseNumericDirection :: Parser Direction parseNumericDirection = choice [ U <$ char '3', D <$ char '1', L <$ char '2', R <$ char '0' ] data Direction = U | D | L | R deriving (Show, Enum)