{-# Language ImportQualifiedPost, QuasiQuotes, TemplateHaskell #-}
module Main (main) where
import Advent (format, stageTH)
import Data.IntMap (IntMap)
import Data.IntMap qualified as IntMap
data O = Onop | Ojmp | Oacc
stageTH
main :: IO ()
IO ()
main =
do [(O, Int)]
inp <- [format|2020 8 (@O (|%+)%d%n)*|]
let pgm :: IntMap (O, Int)
pgm = [(Int, (O, Int))] -> IntMap (O, Int)
forall a. [(Int, a)] -> IntMap a
IntMap.fromList ([Int] -> [(O, Int)] -> [(Int, (O, Int))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [(O, Int)]
inp)
Int -> IO ()
forall a. Show a => a -> IO ()
print ((Int, Int) -> Int
forall a b. (a, b) -> b
snd (IntMap (O, Int) -> Int -> Int -> (Int, Int)
part1 IntMap (O, Int)
pgm Int
0 Int
0))
Int -> IO ()
forall a. Show a => a -> IO ()
print (IntMap (O, Int) -> Int -> Int -> Int
part2 IntMap (O, Int)
pgm Int
0 Int
0)
part1 :: IntMap (O, Int) -> Int -> Int -> (Int,Int)
part1 :: IntMap (O, Int) -> Int -> Int -> (Int, Int)
part1 IntMap (O, Int)
pgm Int
ip Int
acc =
let continue :: Int -> Int -> (Int, Int)
continue = IntMap (O, Int) -> Int -> Int -> (Int, Int)
part1 (Int -> IntMap (O, Int) -> IntMap (O, Int)
forall a. Int -> IntMap a -> IntMap a
IntMap.delete Int
ip IntMap (O, Int)
pgm) in
case Int -> IntMap (O, Int) -> Maybe (O, Int)
forall a. Int -> IntMap a -> Maybe a
IntMap.lookup Int
ip IntMap (O, Int)
pgm of
Maybe (O, Int)
Nothing -> (Int
ip, Int
acc)
Just (O
Onop, Int
_) -> Int -> Int -> (Int, Int)
continue (Int
ipInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
acc
Just (O
Oacc, Int
n) -> Int -> Int -> (Int, Int)
continue (Int
ipInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Int
accInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n)
Just (O
Ojmp, Int
n) -> Int -> Int -> (Int, Int)
continue (Int
ipInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n) Int
acc
part2 :: IntMap (O, Int) -> Int -> Int -> Int
part2 :: IntMap (O, Int) -> Int -> Int -> Int
part2 IntMap (O, Int)
pgm Int
ip Int
acc =
case IntMap (O, Int)
pgm IntMap (O, Int) -> Int -> (O, Int)
forall a. IntMap a -> Int -> a
IntMap.! Int
ip of
(O
Onop, Int
n) -> (Int, Int) -> Int -> Int
forall {b}. (Int, b) -> b -> b
try (IntMap (O, Int) -> Int -> Int -> (Int, Int)
part1 IntMap (O, Int)
pgm (Int
ipInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n) Int
acc) (IntMap (O, Int) -> Int -> Int -> Int
part2 IntMap (O, Int)
pgm (Int
ipInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
acc)
(O
Ojmp, Int
n) -> (Int, Int) -> Int -> Int
forall {b}. (Int, b) -> b -> b
try (IntMap (O, Int) -> Int -> Int -> (Int, Int)
part1 IntMap (O, Int)
pgm (Int
ipInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
acc) (IntMap (O, Int) -> Int -> Int -> Int
part2 IntMap (O, Int)
pgm (Int
ipInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n) Int
acc)
(O
Oacc, Int
n) -> IntMap (O, Int) -> Int -> Int -> Int
part2 IntMap (O, Int)
pgm (Int
ipInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Int
accInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n)
where
try :: (Int, b) -> b -> b
try (Int
ip', b
acc') b
e
| Int
ip' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== IntMap (O, Int) -> Int
forall a. IntMap a -> Int
IntMap.size IntMap (O, Int)
pgm = b
acc'
| Bool
otherwise = b
e