-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day7.hs
48 lines (40 loc) · 1.52 KB
/
Day7.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module: Day7
-- Description: <https://adventofcode.com/2024/day/7 Day 7: Bridge Repair>
module Day7 (part1, part2) where
import Common (readEntire, readSome)
import Control.Monad (ap)
import Control.Parallel.Strategies (parMap, rseq)
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)
import Data.Text.Read qualified as T (decimal)
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, NE.reverse rhs), line'')
parFilter :: (a -> Bool) -> [a] -> [a]
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 (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 op1
part2 :: Text -> Either String Int
part2 = solve op2