diff options
Diffstat (limited to 'day07/day07.hs')
-rw-r--r-- | day07/day07.hs | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/day07/day07.hs b/day07/day07.hs new file mode 100644 index 0000000..1f3cce1 --- /dev/null +++ b/day07/day07.hs @@ -0,0 +1,73 @@ +import Data.Bits +import Data.List +import Data.List.Split + +type Eqn = (Int, [Int]) +data Op = Add | Mul +data Op2 = Add2 | Mul2 | Cat2 deriving Show + +atoi :: String -> Int +atoi = read + +process :: String -> Eqn +process line = + let [targs, inss] = splitOn ": " line + targ = atoi targs + ins = map atoi $ words inss in + (targ, ins) + +opList :: [Op] -> Int -> Int -> [Op] +opList acc 0 _ = acc +opList acc w n = + opList ((case bit of {0 -> Add; otherwise -> Mul}):acc) dw n + where dw = w - 1 + bit = n .&. (1 `shift` dw) + +reifies :: Eqn -> [Op] -> Bool +reifies (targ, (h:t)) ops = + foldl operate h tasks == targ + where tasks = zip ops t + operate = \acc (op, arg) -> case op of {Add -> acc + arg; Mul -> acc * arg} + +reifiable :: Eqn -> Bool +reifiable eqn@(_, args) = + any (reifies eqn) $ map (opList [] l) [0..(2^l - 1)] + where l = (length args) - 1 + +op2List :: [Op2] -> Int -> Int -> [Op2] +op2List acc 0 _ = acc +op2List acc w n = + op2List ((case trit of {0 -> Add2; 1 -> Mul2; 2 -> Cat2}):acc) dw n + where dw = w - 1 + trit = (n `div` (3 ^ dw)) `mod` 3 + +reifies2 :: Eqn -> [Op2] -> Bool +reifies2 (targ, (h:t)) ops = + foldl operate h tasks == targ + where tasks = zip ops t + operate = \acc (op, arg) -> case op of + Add2 -> acc + arg + Mul2 -> acc * arg + Cat2 -> atoi (show acc ++ show arg) + +reifiable2 :: Eqn -> Bool +reifiable2 eqn@(_, args) = + any (reifies2 eqn) $ map (op2List [] l) [0..(3^l - 1)] + where l = (length args) - 1 + +part1 :: [Eqn] -> Int +part1 eqns = + foldl sumCar 0 $ filter reifiable eqns + where sumCar = \acc (i, _) -> acc + i + +part2 :: [Eqn] -> Int +part2 eqns = + foldl sumCar 0 $ filter reifiable2 eqns + where sumCar = \acc (i, _) -> acc + i + +main = do + file <- readFile "day07.input" + let lns = lines file + eqns = map process lns + putStrLn ("Part 1: " ++ (show $ part1 eqns)) + putStrLn ("Part 2: " ++ (show $ part2 eqns)) |