From b41933c48e31a903a93366d157ce5dfb9ed8ca45 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Thu, 7 Dec 2023 12:25:42 +0000 Subject: [PATCH] Add day 6 --- 6.hs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 6.hs diff --git a/6.hs b/6.hs new file mode 100755 index 0000000..e16fcd0 --- /dev/null +++ b/6.hs @@ -0,0 +1,53 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" + +import Control.Applicative ((<*)) +import Text.Parsec +import Text.Parsec.Char +import Text.Parsec.Combinator +import Text.Parsec.String (Parser) + +{- https://adventofcode.com/2023/day/6 -} + +main = do + game <- readAndParseStdin + print $ part1 game + print $ part2 game + +-- returns the product of how many winning times there are per game +part1 :: [(Int, Int)] -> Int +part1 = product . map (length . getWinningTimes) + where + getWinningTimes (time, winCond) = filter (> winCond) $ map (`distance` time) [1 .. time - 1] + +-- concatenates all games into one big game and returns how many winning times +-- there are in the big game +part2 :: [(Int, Int)] -> Int +part2 game = part1 [foldl concatenate (0, 0) game] + where + concatenate (tAcc, dAcc) (t, d) = (tAcc * scale t + t, dAcc * scale d + d) + +-- calculates the "scale" of a number + 1 and returns the magnitude ie. 8 -> 10, 23 -> 100, 694 -> 1000 +scale :: Int -> Int +scale n + | n < 10 = 10 + | otherwise = 10 * scale (n `div` 10) + +-- calculates distance travelled in a game based on velocity * time minus "button pressing time" +distance :: Int -> Int -> Int +distance v t = v * (t - v) + +-- reads stdin and parses game +readAndParseStdin :: IO [(Int, Int)] +readAndParseStdin = do + content <- getContents + case parse gameParser "" content of + Left parseError -> error $ show parseError + Right game -> return game + +-- parses `Time: [n1] [n2] [n3]\nDistance:[n4] [n5] [n6]` and returns `[(n1, n4), (n2, n5), (n3, n6)]` +gameParser :: Parser [(Int, Int)] +gameParser = do + time <- map read <$> (string "Time:" *> spaces *> many1 digit `endBy` spaces) + distance <- map read <$> (string "Distance:" *> spaces *> many1 digit `endBy` spaces) + return $ zip time distance -- libgit2 1.7.2