{-# Language QuasiQuotes #-}
{-|
Module      : Main
Description : Day 2 solution
Copyright   : (c) Eric Mertens, 2019
License     : ISC
Maintainer  : emertens@gmail.com

<https://adventofcode.com/2019/day/2>

-}
module Main (main) where

import Advent.Format (format)
import Intcode

-- | >>> :main
-- 7210630
-- 3892
main :: IO ()
IO ()
main =
  do pgm <- [Int] -> Machine
new ([Int] -> Machine) -> IO [Int] -> IO Machine
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [format|2019 2 %d&,%n|]
     print (startup 12 2 pgm)
     print (head [ 100 * noun + verb
                 | noun <- [0..99]
                 , verb <- [0..99]
                 , startup noun verb pgm == 19690720 ])

-- | Run the given program after assigning the given noun and verb.
startup :: Int {- ^ noun -} -> Int {- ^ verb -} -> Machine -> Int
startup :: Int -> Int -> Machine -> Int
startup Int
noun Int
verb
  = (Machine -> Int -> Int
! Int
0)
  (Machine -> Int) -> (Machine -> Machine) -> Machine -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Machine -> Machine
runPgm
  (Machine -> Machine) -> (Machine -> Machine) -> Machine -> Machine
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Machine -> Machine
set Int
1 Int
noun
  (Machine -> Machine) -> (Machine -> Machine) -> Machine -> Machine
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Machine -> Machine
set Int
2 Int
verb

-- | Run the given program starting at the given program counter
-- returning the initial memory value once the program halts.
--
-- >>> let check = memoryList . runPgm . new
-- >>> check [1,0,0,0,99]
-- [2,0,0,0,99]
-- >>> check [2,3,0,3,99]
-- [2,3,0,6,99]
-- >>> check [2,4,4,5,99,0]
-- [2,4,4,5,99,9801]
-- >>> check [1,1,1,4,99,5,6,0,99]
-- [30,1,1,4,2,5,6,0,99]
-- >>> check [1,9,10,3,2,3,11,0,99,30,40,50]
-- [3500,9,10,70,2,3,11,0,99,30,40,50]
runPgm :: Machine -> Machine
runPgm :: Machine -> Machine
runPgm Machine
mach =
  case Machine -> Step
step Machine
mach of
    Step Machine
mach'     -> Machine -> Machine
runPgm Machine
mach'
    Step
StepHalt       -> Machine
mach
    Step
_              -> String -> Machine
forall a. HasCallStack => String -> a
error String
"Unexpected step on day 2"