From a35f6d928eb37fc2d3d8017472f10678c77daa16 Mon Sep 17 00:00:00 2001 From: Amneesh Singh Date: Wed, 3 Dec 2025 02:42:55 +0530 Subject: [PATCH] day 2: init Signed-off-by: Amneesh Singh --- aoc2025.cabal | 6 +++++ src/Day02.hs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 src/Day02.hs diff --git a/aoc2025.cabal b/aoc2025.cabal index bf19b85..5094e88 100644 --- a/aoc2025.cabal +++ b/aoc2025.cabal @@ -29,3 +29,9 @@ executable day01 hs-source-dirs: src main-is: Day01.hs build-depends: libaoc + +executable day02 + import: common + hs-source-dirs: src + main-is: Day02.hs + build-depends: libaoc diff --git a/src/Day02.hs b/src/Day02.hs new file mode 100644 index 0000000..708af56 --- /dev/null +++ b/src/Day02.hs @@ -0,0 +1,71 @@ +import qualified AoC as A (extract) +import Data.List (nub) +import Text.Parsec (char, digit, many1, parse, sepEndBy1) +import Text.Parsec.String (Parser) + +type Id = Int + +type Range = (Id, Id) + +parseRanges :: Parser [Range] +parseRanges = sepEndBy1 parseRange (char ',') + where + parseRange :: Parser Range + parseRange = liftA2 (,) parseId (char '-' *> parseId) + + parseId :: Parser Id + parseId = read <$> many1 digit + +-- Imagine the number is of form xx where x is the repeated k digit number +-- Note that xx is of length 2 * k, since x is of length k, and k is log_10(x) +-- The number will always be of the form x + (10 ^ k) * x or x * (10 ^ k + 1) +-- Hence, in modular arithmetic, xx = x (mod (10 ^ k + 1)) +part1 :: [Range] -> Int +part1 = sum . map invalids + where + invalids :: Range -> Int + invalids (l, r) = + let len = length . show $ r + reps = 2 + k = len `div` reps + m = 10 ^ k + 1 + in sum + [ xx + | x <- + [ ceiling (fromIntegral l / fromIntegral m :: Float) + .. floor (fromIntegral r / fromIntegral m :: Float) + ], + let xx = x * m, + length (show xx) `mod` reps == 0 + ] + +-- Second part is similar to first part except that it is now a geometric +-- progression of form x + (10 ^ k) * x .. (10 ^ (n - 1) * k) * x, where n is the +-- number of repetitions (2 in part1). So using similar logic and sum for +-- geometric progression we get: +part2 :: [Range] -> Int +part2 = sum . map invalids + where + invalids :: Range -> Int + invalids (l, r) = + let len = length . show $ r + in sum . nub $ + [ xx + | reps <- [2 .. len], + let k = len `div` reps + m = (10 ^ (reps * k) - 1) `div` (10 ^ k - 1), + x <- + [ ceiling (fromIntegral l / fromIntegral m :: Float) + .. floor (fromIntegral r / fromIntegral m :: Float) + ], + let xx = x * m, + length (show xx) `mod` reps == 0 + ] + +main :: IO () +main = + do + raw <- readFile "./inputs/day2.in" + let ranges = A.extract $ parse parseRanges "" raw + putStr "Part 1: " >> print (part1 ranges) + putStr "Part 2: " >> print (part2 ranges)