-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDay07.curry
44 lines (37 loc) · 1.45 KB
/
Day07.curry
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
{-# OPTIONS_FRONTEND -Wno-incomplete-patterns #-}
import Control.Search.SetFunctions (set1, notEmpty)
import Data.List (splitOn, sum)
import System.Environment (getArgs)
data Equation = Equation { lhs :: Int, rhs :: [Int] }
deriving (Show, Eq)
parseEquation :: String -> Equation
parseEquation raw = Equation lhs rhs
where [rawLhs, rawRhs] = splitOn ": " raw
lhs = read rawLhs
rhs = read <$> splitOn " " rawRhs
isSolvable :: [Int -> Int -> Int] -> Equation -> Bool
isSolvable ops = notEmpty . set1 isSolvable'
where
isSolvable' (Equation l (r:rs)) | l =:= evalAcc r rs = True
where
evalAcc acc vals = case vals of
-- Prune branches that already overshoot the target
_ | acc > l -> failed
[] -> acc
(v:vs) -> anyOf $ (\op -> evalAcc (op acc v) vs) <$> ops
totalResult :: [Int -> Int -> Int] -> [Equation] -> Int
totalResult ops eqns = sum $ lhs <$> filter (isSolvable ops) eqns
(||.) :: Int -> Int -> Int
x ||. y = x * (10 ^ floor (1 + if y == 0 then 0 else logBase 10 (toFloat y))) + y
main :: IO ()
main = do
args <- getArgs
case args of
[path] -> do
raw <- readFile path
let eqns = (parseEquation <$>) . lines $!! raw
part1 = totalResult [(+), (*)] eqns
part2 = totalResult [(+), (*), (||.)] eqns
putStrLn $ "Part 1: " ++ show part1
putStrLn $ "Part 2: " ++ show part2
_ -> putStrLn "Usage: day07 <path to input>"