@@ -1990,14 +1990,18 @@ Now, `stepTape` is an action (in `State` and `Maybe`) that uses an underlying
1990
1990
get the underlying ` Machine ` action using:
1991
1991
1992
1992
``` haskell
1993
- execTapeProg :: TapeProg a -> ProgState -> Machine ProgState
1993
+ runTapeProg :: TapeProg a -> (ProgState -> Machine (a , ProgState ))
1994
+ runTapeProg tp ps = flip runStateT ps . runMaybeT $ tp
1995
+
1996
+ execTapeProg :: TapeProg a -> (ProgState -> Machine (a , ProgState ))
1994
1997
execTapeProg tp ps = flip execStateT ps . runMaybeT $ tp
1995
1998
```
1996
1999
1997
2000
Which will "run" a ` TapeProg a ` , with a given state, to produce the ` Machine `
1998
- action (basically, a tree of nested ` CRcv ` and ` CSnd ` ).
2001
+ action (basically, a tree of nested ` CRcv ` and ` CSnd ` ). You can think of this
2002
+ as "compiling" a ` TapeProg a ` to be a ` ProgState -> Machine (a, ProgState) `
1999
2003
2000
- Conceptually, this is similar to how ` execStateT :: StateT s IO a -> IO s `
2004
+ Conceptually, this is similar to how ` runStateT :: StateT s IO a -> IO (a, s) `
2001
2005
produces an ` IO ` action that computes the final state that the ` execStateT `
2002
2006
encodes.
2003
2007
@@ -2020,6 +2024,51 @@ stepTape :: TapeProg ()
2020
2024
many stepTape :: TapeProg [() ]
2021
2025
```
2022
2026
2027
+ ### Part 1
2028
+
2029
+ Okay, so, once we get a ` ProgState -> Machine ProgState ` that represents
2030
+ repeatedly running ` stepTape ` until we run out of bounds, how do we get our
2031
+ answer?
2032
+
2033
+ Part 1 asks for the first successful ` rcv ` ("recover"). We need to properly
2034
+ interpret our ` Command ` in an environment that lets us recover this.
2035
+
2036
+ We can use ` StateT (Maybe Int) (Writer [Int]) ` :
2037
+
2038
+ * The ` Maybe Int ` state represents the last thing "sent".
2039
+ * The ` [Int] ` writer log represents all of the "recovered" things.
2040
+
2041
+ ``` haskell
2042
+ type PartA = StateT (Maybe Int ) (Writer [Int ])
2043
+ ```
2044
+
2045
+ Interpreting this is straightforward:
2046
+
2047
+ ```haskell
2048
+ interpretA :: Command a -> PartA a
2049
+ interpretA = \ case
2050
+ CSnd x -> put (Just x)
2051
+ CRcv x -> do
2052
+ when (x /= 0 ) $
2053
+ lastSent <- get
2054
+ forM_ lastSet $ \ y ->
2055
+ lift $ tell [y]
2056
+ return x
2057
+ ```
2058
+
2059
+ And now we can "run" it to get our Part 1 answer!
2060
+
2061
+ ``` haskell
2062
+ execPartA :: PartA a -> Int
2063
+ execPartA = head . snd . runWriter . flip execStateT Nothing
2064
+
2065
+ day18a :: Tape Op -> Int
2066
+ day18a = execPartA -- run the `PartA` to get the answer
2067
+ . runPromptM interpretA -- interpret `Machine ProgState` to `PartA ProgState`
2068
+ . execTapeProg (many stepTape) -- compile `many stepTape` to `Machine ProgState`
2069
+ . (`PS ` M. empty) -- assemble `ProgState`
2070
+ ```
2071
+
2023
2072
### Day 18 Benchmarks
2024
2073
2025
2074
```
0 commit comments