From cffd7e04a6171bfa633d6769416d0f2b268fa9f3 Mon Sep 17 00:00:00 2001 From: Daniel Lin Date: Sat, 7 Dec 2024 01:34:30 -0500 Subject: [PATCH] It's faster in reverse --- hs/src/Day7.hs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/hs/src/Day7.hs b/hs/src/Day7.hs index 7a8aebec..d4845adf 100644 --- a/hs/src/Day7.hs +++ b/hs/src/Day7.hs @@ -8,7 +8,8 @@ module Day7 (part1, part2) where import Common (readEntire, readSome) import Control.Monad (ap) import Control.Parallel.Strategies (parMap, rseq) -import Data.List.NonEmpty (NonEmpty ((:|))) +import Data.List.NonEmpty (NonEmpty ((:|)), nonEmpty) +import Data.List.NonEmpty qualified as NE (reverse) import Data.Text (Text) import Data.Text qualified as T (lines, stripPrefix) import Data.Text.Read (Reader) @@ -18,7 +19,7 @@ parseLine :: (Integral a) => Reader (a, NonEmpty a) parseLine line = do (lhs, line') <- T.decimal line (rhs, line'') <- maybe (Left "") (readSome T.decimal) $ T.stripPrefix ": " line' - pure ((lhs, rhs), line'') + pure ((lhs, NE.reverse rhs), line'') parFilter :: (a -> Bool) -> [a] -> [a] parFilter f = fmap fst . filter snd . (zip `ap` parMap rseq f) @@ -26,11 +27,22 @@ parFilter f = fmap fst . filter snd . (zip `ap` parMap rseq f) solve :: (Integral a) => (a -> a -> [a]) -> Text -> Either String a solve op input = sum . map fst . parFilter f <$> mapM (readEntire parseLine) (T.lines input) where - f (lhs, r0 :| []) = lhs == r0 - f (lhs, r0 :| r1 : rhs) = or [r2 <= lhs && f (lhs, r2 :| rhs) | r2 <- r0 `op` r1] + f (x, y :| rest) + | Just rest' <- nonEmpty rest = or [f (z, rest') | z <- x `op` y] + | otherwise = x == y + +op1, op2 :: (Integral a) => a -> a -> [a] +op1 x y = [x - y | x >= y] <> case x `divMod` y of (z, 0) -> [z]; _ -> [] +op2 x y = + op1 x y + <> [ z + | d <- take 1 $ dropWhile (<= y) $ iterate (* 10) 10, + let (z, r) = x `divMod` d, + z /= 0 && r == y + ] part1 :: Text -> Either String Int -part1 = solve $ \a b -> [a + b, a * b] +part1 = solve op1 part2 :: Text -> Either String Int -part2 = solve $ \a b -> [a + b, a * b, read $ show a ++ show b] +part2 = solve op2