From 9dd10342313cd00b9f87444451a45a92e20895de Mon Sep 17 00:00:00 2001
From: Neil Smith <neil.git@njae.me.uk>
Date: Mon, 7 Dec 2020 15:58:45 +0000
Subject: [PATCH] Now uses a Reader monad

---
 advent25/package.yaml    |  1 +
 advent25/src/advent25.hs | 35 +++++++++++++++++++++++++----------
 2 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/advent25/package.yaml b/advent25/package.yaml
index 2df1822..c8c4d8a 100644
--- a/advent25/package.yaml
+++ b/advent25/package.yaml
@@ -58,3 +58,4 @@ executables:
     - text
     - containers
     - intcode
+    - mtl
diff --git a/advent25/src/advent25.hs b/advent25/src/advent25.hs
index 126fbc8..c9a7457 100644
--- a/advent25/src/advent25.hs
+++ b/advent25/src/advent25.hs
@@ -6,6 +6,10 @@ import qualified Data.Text.IO as TIO
 import qualified Data.Text as T
 import Data.Char
 import Data.List
+import Control.Monad.Reader
+
+type CachedMachine a = Reader (Machine, [String]) a
+
 
 main :: IO ()
 main = do 
@@ -48,21 +52,32 @@ powerList [] = [[]]
 powerList (x:xs) = powerList xs ++ map (x:) (powerList xs) 
 
 passSecurity :: Machine -> [String] -> [String] -> String
-passSecurity machine instructions items = 
-    "You keep: " ++ (intercalate ", " keeps) ++ "\n\n" ++ (attemptSecurity machine instructions validDropset)
+passSecurity machine instructions items = "You keep: " ++ (intercalate ", " keeps) ++ "\n\n" ++ successResponse
     where
+        env = (machine, instructions)
         dropsets = powerList items
-        validDropset = head $ filter (passesSecurity machine instructions) dropsets
+        validDropset = head $ filter (\ds -> runReader (passesSecurity ds) env) dropsets
+        successResponse = (runReader (attemptSecurity validDropset) env)
         keeps = items \\ validDropset
 
-passesSecurity :: Machine -> [String] -> [String] -> Bool
-passesSecurity machine instructions drops = not ("Alert" `isInfixOf` output)
-    where output = attemptSecurity machine instructions drops
+passesSecurity :: [String] -> CachedMachine Bool
+passesSecurity drops = 
+    do  output <- attemptSecurity drops
+        return $ not ("Alert" `isInfixOf` output)
+
+attemptSecurity :: [String] -> CachedMachine String
+attemptSecurity drops = 
+    do  let dropCommands = map ("drop " ++ ) drops
+        output <- runCachedMachine dropCommands
+        return output 
+
+runCachedMachine :: [String] -> CachedMachine String
+runCachedMachine dropCommands =
+    do (machine, instructions) <- ask
+       let (_, _, output) = runMachine (encodeCommands (instructions ++ dropCommands ++ ["north"])) machine
+       return $ decodeOutput output
+
 
-attemptSecurity :: Machine -> [String] -> [String] -> String
-attemptSecurity machine instructions drops = decodeOutput output
-    where dropCommands = map ("drop " ++ ) drops
-          (_, _, output) = runMachine (encodeCommands (instructions ++ dropCommands ++ ["north"])) machine
 
 runCommand :: [Integer] -> [String] -> (Machine, String)
 runCommand mem inputs = ( machine, decodeOutput output )
-- 
2.43.0