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

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

-}
module Main (main) where

import Advent (format)
import Data.Char (chr, ord)
import Intcode (intcodeToList)
import Debug.Trace

-- | >>> :main
-- 19355364
-- 1142530574
main :: IO ()
IO ()
main =
 do [Int]
inp <- [format|2019 21 %d&,%n|]
    let letsGo :: String -> IO ()
letsGo = Int -> IO ()
forall a. Show a => a -> IO ()
print (Int -> IO ()) -> (String -> Int) -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> Int
forall a. HasCallStack => [a] -> a
last ([Int] -> Int) -> (String -> [Int]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> [Int] -> [Int]
intcodeToList [Int]
inp ([Int] -> [Int]) -> (String -> [Int]) -> String -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Int) -> String -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
ord
    String -> IO ()
letsGo String
part1
    String -> IO ()
letsGo String
part2

eval :: [Int] -> [String] -> Either String Int
eval :: [Int] -> [String] -> Either String Int
eval [Int]
pgm [String]
input
  | String
counter:[String]
_ <- (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter (Char
'#' Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem`) [String]
outLines = String -> Either String Int
forall a b. a -> Either a b
Left String
counter
  | Bool
otherwise = Int -> Either String Int
forall a b. b -> Either a b
Right ([Int] -> Int
forall a. HasCallStack => [a] -> a
last [Int]
outs)
  where
    outs :: [Int]
outs = [Int] -> [Int] -> [Int]
intcodeToList [Int]
pgm ((Char -> Int) -> String -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
ord ([String] -> String
unlines [String]
input))
    outLines :: [String]
outLines = String -> [String]
lines (String -> String
traceId ((Int -> Char) -> [Int] -> String
forall a b. (a -> b) -> [a] -> [b]
map Int -> Char
chr [Int]
outs))


-- !(A ∧ C) ∧ D   # test cases didn't need B to be checked
part1 :: String
part1 :: String
part1 =
  [String] -> String
unlines
    [ String
"OR  A J",
      String
"AND C J",
      String
"NOT J J",
      String
"AND D J",
      String
"WALK" ]

-- !(A ∧ B ∧ C) ∧ D ∧ (E ∨ H)
part2 :: String
part2 :: String
part2 =
  [String] -> String
unlines
    [ String
"OR  A J",
      String
"AND B J",
      String
"AND C J",
      String
"NOT J J",
      String
"AND D J",
      String
"OR  E T",
      String
"OR  H T",
      String
"AND T J",
      String
"RUN" ]