[haskell] Solve day 6
This commit is contained in:
parent
d6f9b4dae3
commit
a79cc27359
|
@ -25,6 +25,7 @@ library
|
||||||
, Day3
|
, Day3
|
||||||
, Day4
|
, Day4
|
||||||
, Day5
|
, Day5
|
||||||
|
, Day6
|
||||||
|
|
||||||
executable aoc2023
|
executable aoc2023
|
||||||
import: warnings
|
import: warnings
|
||||||
|
|
|
@ -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
99
haskell/src/Day6.hs
Normal 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
2
input/day6
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Time: 62 73 75 65
|
||||||
|
Distance: 644 1023 1240 1023
|
2
input/day6-eg
Normal file
2
input/day6-eg
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Time: 7 15 30
|
||||||
|
Distance: 9 40 200
|
Loading…
Reference in a new issue