🏡 index : ~doyle/aoc.git

author Jordan Doyle <jordan@doyle.la> 2023-12-07 12:25:42.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2023-12-07 12:25:42.0 +00:00:00
commit
b41933c48e31a903a93366d157ce5dfb9ed8ca45 [patch]
tree
b405c0f419e255a482148df013ded71ea38ae2f8
parent
641548d3a25c6c1b98426fda5898c65210a371e7
download
b41933c48e31a903a93366d157ce5dfb9ed8ca45.tar.gz

Add day 6



Diff

 6.hs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

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