diff options
author | Julien Dessaux | 2024-11-19 00:31:01 +0100 |
---|---|---|
committer | Julien Dessaux | 2024-11-19 00:31:01 +0100 |
commit | b26eca34cd939200e4815bcf7f7031c43ea48641 (patch) | |
tree | ef647d5daa72ca05682c843e7ec1ad4991ab99d0 /2023/24-Never_Tell_Me_The_Odds/first.hs | |
parent | 2023-23 part 2 in haskell (diff) | |
download | advent-of-code-b26eca34cd939200e4815bcf7f7031c43ea48641.tar.gz advent-of-code-b26eca34cd939200e4815bcf7f7031c43ea48641.tar.bz2 advent-of-code-b26eca34cd939200e4815bcf7f7031c43ea48641.zip |
2023-24 part 1 in haskell
Diffstat (limited to '')
-rw-r--r-- | 2023/24-Never_Tell_Me_The_Odds/first.hs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/2023/24-Never_Tell_Me_The_Odds/first.hs b/2023/24-Never_Tell_Me_The_Odds/first.hs new file mode 100644 index 0000000..0964c12 --- /dev/null +++ b/2023/24-Never_Tell_Me_The_Odds/first.hs @@ -0,0 +1,81 @@ +-- requires cabal install --lib megaparsec parser-combinators heap vector +module Main (main) where + +import Control.Applicative.Permutations +import Control.Monad (void, when) +import qualified Data.Char as C +import Data.Either +import Data.Functor +import qualified Data.Heap as H +import qualified Data.List as L +import qualified Data.Map as M +import Data.Maybe +import Data.Ratio +import qualified Data.Set as S +import qualified Data.Vector as V +import qualified Data.Vector.Unboxed as VU +import Data.Void (Void) +import Text.Megaparsec +import Text.Megaparsec.Char + +import Debug.Trace + +exampleExpectedOutput = 2 + +type Hail = (Rational, Rational, Rational, Rational, Rational, Rational) +type Input = [Hail] + +type Parser = Parsec Void String + +parseNumber :: Parser Integer +parseNumber = read <$> some (char '-' <|> digitChar) <* optional (char ',') <* optional hspace <* optional (char '@' <* hspace) + +parseHail :: Parser Hail +parseHail = (,,,,,) <$> (fromInteger <$> parseNumber) + <*> (fromInteger <$> parseNumber) + <*> (fromInteger <$> parseNumber) + <*> (fromInteger <$> parseNumber) + <*> (fromInteger <$> parseNumber) + <*> (fromInteger <$> parseNumber) + +parseInput' :: Parser Input +parseInput' = some (parseHail <* eol) <* eof + +parseInput :: String -> IO Input +parseInput filename = do + input <- readFile filename + case runParser parseInput' filename input of + Left bundle -> error $ errorBundlePretty bundle + Right input' -> return input' + +compute :: Rational -> Rational -> Input -> Int +compute mini maxi = compute' + where + compute' :: Input -> Int + compute' (_:[]) = 0 + compute' ((x1, y1, _, a1, b1, _):hs) = L.foldl' computeOne 0 hs + compute' hs + where + (x2, y2) = (x1 + a1, y1 + b1) + computeOne :: Int -> Hail -> Int + computeOne acc (x3, y3, _, a3, b3, _) | valid = acc + 1 + | otherwise = acc + where + valid | denominator == 0 || t < 0 || u < 0 = False + | x >= mini && x <= maxi && y >= mini && y <= maxi = True + | otherwise = False + (x4, y4) = (x3 + a3, y3 + b3) + denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4) + a = x1 * y2 - y1 * x2 + b = x3 * y4 - y3 * x4 + numeratorX = b * a1 - a * a3 + numeratorY = b * b1 - a * b3 + (x, y) = (numeratorX / denominator, numeratorY / denominator) + (t, u) = ((x - x1) / a1, (x - x3) / a3) + +main :: IO () +main = do + example <- parseInput "example" + let exampleOutput = compute 7 27 example + when (exampleOutput /= exampleExpectedOutput) (error $ "example failed: got " ++ show exampleOutput ++ " instead of " ++ show exampleExpectedOutput) + input <- parseInput "input" + print $ compute 200000000000000 400000000000000 input |