[haskell] Solve day 6

This commit is contained in:
Akshay Mankar 2023-12-09 00:31:04 +01:00
parent d6f9b4dae3
commit a79cc27359
Signed by: axeman
GPG key ID: CA08F3AB62369B89
5 changed files with 109 additions and 3 deletions

View file

@ -25,6 +25,7 @@ library
, Day3 , Day3
, Day4 , Day4
, Day5 , Day5
, Day6
executable aoc2023 executable aoc2023
import: warnings import: warnings

View file

@ -4,10 +4,11 @@ module Main where
import Day1 qualified import Day1 qualified
import Day2 qualified import Day2 qualified
import Day3 qualified
import Day4 qualified
import Day5 qualified
import Day6 qualified
import System.Environment (getArgs) import System.Environment (getArgs)
import qualified Day3
import qualified Day4
import qualified Day5
main :: IO () main :: IO ()
main = do main = do
@ -17,4 +18,5 @@ main = do
["day3"] -> Day3.run ["day3"] -> Day3.run
["day4"] -> Day4.run ["day4"] -> Day4.run
["day5"] -> Day5.run ["day5"] -> Day5.run
["day6"] -> Day6.run
args -> error $ "Invlaid args: " <> show args args -> error $ "Invlaid args: " <> show args

99
haskell/src/Day6.hs Normal file
View file

@ -0,0 +1,99 @@
module Day6 where
import Data.Char
import Text.ParserCombinators.ReadP
run :: IO ()
run = do
(records, record) <- readInput
putStrLn $ "Part 1 Answer: " <> show (part1 records)
putStrLn $ "Part 2 Answer: " <> show (part2 record)
part1 :: [Record] -> Int
part1 =
product . map (uncurry waysOfWinning)
part2 :: Record -> Int
part2 = uncurry waysOfWinning
-- | There is definitely a better way for doing this. But this runs in less than
-- a second.
waysOfWinning :: Time -> Distance -> Int
waysOfWinning time recordDistance =
length $ filter (> recordDistance) $ productsOfAdders time
-- | Finds products of all adders
--
-- >>> productsOfAdders 7
-- [0,6,10,12,12,10,6,0]
--
-- >>> productsOfAdders 30
-- [0,29,56,81,104,125,144,161,176,189,200,209,216,221,224,225,224,221,216,209,200,189,176,161,144,125,104,81,56,29,0]
productsOfAdders :: Int -> [Int]
productsOfAdders = map (uncurry (*)) . adders
-- | Postitive integers which add up to the given integer
--
-- >>> adders 7
-- [(0,7),(1,6),(2,5),(3,4),(4,3),(5,2),(6,1),(7,0)]
--
-- >>> adders 8
-- [(0,8),(1,7),(2,6),(3,5),(4,4),(5,3),(6,2),(7,1),(8,0)]
adders :: Int -> [(Int, Int)]
adders n = map (\x -> (x, n - x)) [0 .. n]
type Time = Int
type Distance = Int
type Race = (Time, Distance)
type Record = (Time, Distance)
readInput :: IO ([Record], Record)
readInput = do
input <- getContents
let parseWith p = case readP_to_S p input of
[] -> error "Parser failed"
[(parsed, "")] -> parsed
xs -> error $ "Parser failed: " <> show xs
pure (parseWith recordsParser, parseWith betterRecordParser)
numberParser :: ReadP Int
numberParser =
read <$> munch1 isDigit
timesParser :: ReadP [Time]
timesParser = do
_ <- string "Time: "
_ <- skipSpaces
sepBy1 numberParser skipSpaces
distancesParser :: ReadP [Distance]
distancesParser = do
_ <- string "Distance: "
_ <- skipSpaces
sepBy1 numberParser skipSpaces
recordsParser :: ReadP [Record]
recordsParser = do
times <- timesParser
_ <- char '\n'
distances <- distancesParser
eof
pure $ zip times distances
betterNumberParser :: ReadP Int
betterNumberParser =
read . filter (/= ' ') <$> munch1 (\c -> c == ' ' || isDigit c)
betterRecordParser :: ReadP (Time, Distance)
betterRecordParser = do
_ <- string "Time: "
skipSpaces
t <- betterNumberParser
_ <- string "\nDistance: "
skipSpaces
d <- betterNumberParser
eof
pure (t, d)

2
input/day6 Normal file
View file

@ -0,0 +1,2 @@
Time: 62 73 75 65
Distance: 644 1023 1240 1023

2
input/day6-eg Normal file
View file

@ -0,0 +1,2 @@
Time: 7 15 30
Distance: 9 40 200