{-# Language QuasiQuotes #-} {-| Module : Main Description : Day 5 solution Copyright : (c) Eric Mertens, 2019 License : ISC Maintainer : emertens@gmail.com <https://adventofcode.com/2019/day/7> To compute our thrust controller feedback loop I evaluate the given Intcode program as a function from input values to output values. Connecting the outputs of one instance of the program to the inputs of the next is as simple as composing the two functions together. Thanks to non-strict evaluation I can pass the output of a composition of these functions back in as its own input! -} module Main (main) where import Advent (format) import Data.List (permutations) import Intcode (intcodeToList) -- | A function from a list of input values to a list of output values. type ListFn = [Int] -> [Int] -- | >>> :main -- 34852 -- 44282086 main :: IO () IO () main = do [Int] -> [Int] pgm <- [Int] -> [Int] -> [Int] intcodeToList ([Int] -> [Int] -> [Int]) -> IO [Int] -> IO ([Int] -> [Int]) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> [format|2019 7 %d&,%n|] Int -> IO () forall a. Show a => a -> IO () print (([Int] -> [Int]) -> Int part1 [Int] -> [Int] pgm) Int -> IO () forall a. Show a => a -> IO () print (([Int] -> [Int]) -> Int part2 [Int] -> [Int] pgm) -- | Run the given amplitude controller in a feedback loop across -- all permutations of the settings 0 through 4. Returns the -- maximum initial thruster output. -- -- >>> part1 (intcodeToList [3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0]) -- 43210 -- >>> part1 (intcodeToList [3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0]) -- 54321 -- >>> part1 (intcodeToList [3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0]) -- 65210 part1 :: ListFn {- ^ amplifier controller software -} -> Int {- ^ maximum initial thruster output -} part1 :: ([Int] -> [Int]) -> Int part1 = ([Int] -> Int) -> [Int] -> ([Int] -> [Int]) -> Int forall a. Ord a => ([Int] -> a) -> [Int] -> ([Int] -> [Int]) -> a optimize [Int] -> Int forall a. HasCallStack => [a] -> a head [Int 0..Int 4] -- | Run the given amplitude controller in a feedback loop across -- all permutations of the settings 5 through 9. Returns the -- maximum final thruster output. -- -- >>> part2 (intcodeToList [3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5]) -- 139629729 -- >>> :{ -- >>> part2 (intcodeToList [3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54, -- >>> -5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4, -- >>> 53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10]) -- >>> :} -- 18216 part2 :: ListFn {- ^ amplifier controller software -} -> Int {- ^ maximum final thruster output -} part2 :: ([Int] -> [Int]) -> Int part2 = ([Int] -> Int) -> [Int] -> ([Int] -> [Int]) -> Int forall a. Ord a => ([Int] -> a) -> [Int] -> ([Int] -> [Int]) -> a optimize [Int] -> Int forall a. HasCallStack => [a] -> a last [Int 5..Int 9] -- | Try all the permutations of the phases listed and return the -- maximum value of the characterizing function. optimize :: Ord a => ([Int] -> a) {- ^ output characterization -} -> [Int] {- ^ phase available -} -> ListFn {- ^ phases to outputs -} -> a {- ^ maximized characterization -} optimize :: forall a. Ord a => ([Int] -> a) -> [Int] -> ([Int] -> [Int]) -> a optimize [Int] -> a f [Int] phases [Int] -> [Int] pgm = [a] -> a forall a. Ord a => [a] -> a forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a maximum [[Int] -> a f (([Int] -> [Int]) -> [Int] -> [Int] thrustController [Int] -> [Int] pgm [Int] p) | [Int] p <- [Int] -> [[Int]] forall a. [a] -> [[a]] permutations [Int] phases] -- | Given a amplifier controller software function and a list of -- phase settings, generate the resulting list of thruster outputs. -- -- Once instances of the control software is started for each phase setting, -- the instances are all sequenced together into a single loop. A starting -- @0@ element is added as an initial input. -- -- >>> thrustController (intcodeToList [3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0]) [4,3,2,1,0] -- [43210] -- >>> thrustController (intcodeToList [3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5]) [9,8,7,6,5] -- [129,4257,136353,4363425,139629729] thrustController :: ListFn {- ^ amplifier controller software -} -> ListFn {- ^ thrust controller -} thrustController :: ([Int] -> [Int]) -> [Int] -> [Int] thrustController [Int] -> [Int] pgm [Int] phases = [Int] outs where outs :: [Int] outs = ([Int] -> Int -> [Int]) -> [Int] -> [Int] -> [Int] forall b a. (b -> a -> b) -> b -> [a] -> b forall (t :: * -> *) b a. Foldable t => (b -> a -> b) -> b -> t a -> b foldl (\[Int] prev Int p -> [Int] -> [Int] pgm (Int pInt -> [Int] -> [Int] forall a. a -> [a] -> [a] :[Int] prev)) (Int 0Int -> [Int] -> [Int] forall a. a -> [a] -> [a] :[Int] outs) [Int] phases