X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=advent05%2FMain.hs;fp=advent05%2FMain.hs;h=9ec1d254707abaf10b2e7818813c7681050a8dbe;hb=81f9c61ac7fe5482ba3210eede266450c4e562b6;hp=0000000000000000000000000000000000000000;hpb=6db626fdd0b191829d9a3ba276fc8c027fe67274;p=advent-of-code-22.git diff --git a/advent05/Main.hs b/advent05/Main.hs new file mode 100644 index 0000000..9ec1d25 --- /dev/null +++ b/advent05/Main.hs @@ -0,0 +1,124 @@ +-- Writeup at https://work.njae.me.uk/2022/12/04/advent-of-code-2022-day-4/ + +import System.Environment +import Data.Text (Text) +import qualified Data.Text.IO as TIO +import Data.Attoparsec.Text hiding (take) +import Control.Applicative +import Data.List +import Data.Maybe +import qualified Data.IntMap.Strict as M +import Data.IntMap.Strict ((!), (!?)) + +data Crate = Crate Char deriving (Show, Eq) +type Wharf = M.IntMap [Crate] + +data Move = Move Int Int Int -- quantity, from, to + deriving (Show, Eq) + + +main :: IO () +main = + do dataFileName <- getDataFileName + text <- TIO.readFile dataFileName + let ((wharfLines, colNames), moves) = successfulParse text + -- print wharfLines + -- print colNames + -- print moves + let wharf = makeWharf wharfLines colNames + -- print wharf + -- print $ applyMove wharf (head moves) + putStrLn $ part1 wharf moves + putStrLn $ part2 wharf moves + + +getDataFileName :: IO String +getDataFileName = + do args <- getArgs + progName <- getProgName + let baseDataName = if null args + then progName + else head args + let dataFileName = "data/" ++ baseDataName ++ ".txt" + return dataFileName + + +part1 :: Wharf -> [Move] -> String +part1 wharf moves = showTops $ applyMoves1 wharf moves + +part2 :: Wharf -> [Move] -> String +part2 wharf moves = showTops $ applyMoves2 wharf moves + +showTops :: Wharf -> String +showTops wharf = fmap extractName $ fmap (head . snd) $ M.toAscList wharf + +extractName :: Crate -> Char +extractName (Crate c) = c + +makeWharf :: [[Maybe Crate]] -> [Int] -> Wharf +makeWharf wharfLines colNames = M.fromList $ zip colNames wharfCols + where wharfCols = fmap (fmap fromJust) + $ fmap (dropWhile isNothing) + $ transpose wharfLines + +applyMoves1 :: Wharf -> [Move] -> Wharf +applyMoves1 wharf moves = foldl' applyMove1 wharf moves + +applyMove1 :: Wharf -> Move -> Wharf +applyMove1 wharf m@(Move n _ _) = foldl' makeMove1 wharf (replicate n m) + +makeMove1 :: Wharf -> Move -> Wharf +makeMove1 wharf (Move _ from to) = M.insert from origin + $ M.insert to destination wharf + where (c:origin) = wharf!from + destination = c:(fromMaybe [] $ wharf!?to) + +applyMoves2 :: Wharf -> [Move] -> Wharf +applyMoves2 wharf moves = foldl' applyMove2 wharf moves + +applyMove2 :: Wharf -> Move -> Wharf +applyMove2 wharf (Move n from to) = M.insert from origin' + $ M.insert to destination wharf + where origin = wharf!from + moving = take n origin + origin' = drop n origin + destination = moving ++ (fromMaybe [] $ wharf!?to) + + +-- Parse the input file + +problemP :: Parser (([[Maybe Crate]], [Int]), [Move]) +wharfP :: Parser ([[Maybe Crate]], [Int]) +wharfLineP :: Parser [Maybe Crate] +wharfCellP, blankP, crateP :: Parser (Maybe Crate) +stackLabelsP :: Parser [Int] +movesP :: Parser [Move] +moveP :: Parser Move + +-- problemP = (,) <$> wharfP <* endOfLine <* endOfLine <*> movesP +problemP = (,) <$> wharfP <*> movesP + +wharfP = (,) <$> (wharfLineP `sepBy` endOfLine) <*> stackLabelsP + +wharfLineP = wharfCellP `sepBy1` (char ' ') + +wharfCellP = crateP <|> blankP +blankP = Nothing <$ (count 3 space) +crateP = (Just . Crate) <$> ("[" *> letter) <* "]" + +-- stackLabelsP = ((many1 space) *> (decimal `sepBy` (many1 space))) <* (takeWhile1 isHorizontalSpace) +stackLabelsP = (many1 space) + *> (decimal `sepBy` (many1 space)) + <* (many1 space) + +movesP = moveP `sepBy` endOfLine +moveP = Move <$> ("move " *> decimal) + <*> (" from " *> decimal) + <*> (" to " *> decimal) + + +successfulParse :: Text -> (([[Maybe Crate]], [Int]), [Move]) +successfulParse input = + case parseOnly problemP input of + Left _err -> (([], []), []) -- TIO.putStr $ T.pack $ parseErrorPretty err + Right problem -> problem