#!/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)
main = do
game <- readAndParseStdin
print $ part1 game
print $ part2 game
part1 :: [(Int, Int)] -> Int
part1 = product . map (length . getWinningTimes)
where
getWinningTimes (time, winCond) = filter (> winCond) $ map (`distance` time) [1 .. time - 1]
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)
scale :: Int -> Int
scale n
| n < 10 = 10
| otherwise = 10 * scale (n `div` 10)
distance :: Int -> Int -> Int
distance v t = v * (t - v)
readAndParseStdin :: IO [(Int, Int)]
readAndParseStdin = do
content <- getContents
case parse gameParser "" content of
Left parseError -> error $ show parseError
Right game -> return game
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