Day 21 mostly done
authorNeil Smith <neil.git@njae.me.uk>
Fri, 22 Nov 2019 16:29:08 +0000 (16:29 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Fri, 22 Nov 2019 16:29:08 +0000 (16:29 +0000)
advent-of-code.cabal
data/advent21.txt [new file with mode: 0644]
problems/day20.html [new file with mode: 0644]
src/advent21/advent21.hs [new file with mode: 0644]

index dd2f20754ba2f713b5b9c3bd1fa882c22d0b439b..68d29fa1d191ccbc574f9c6fc0e0788721a5e73c 100644 (file)
@@ -240,3 +240,13 @@ executable advent20
                      , text
                      , megaparsec 
                      , linear
+
+executable advent21
+  hs-source-dirs:      src/advent21
+  main-is:             advent21.hs
+  default-language:    Haskell2010
+  build-depends:       base >= 4.7 && < 5
+                     , containers
+                     , mtl
+                     , text
+                     , megaparsec   
\ No newline at end of file
diff --git a/data/advent21.txt b/data/advent21.txt
new file mode 100644 (file)
index 0000000..8ae617f
--- /dev/null
@@ -0,0 +1,32 @@
+#ip 3
+seti 123 0 1
+bani 1 456 1
+eqri 1 72 1
+addr 1 3 3
+seti 0 0 3
+seti 0 0 1
+bori 1 65536 2
+seti 10605201 9 1
+bani 2 255 5
+addr 1 5 1
+bani 1 16777215 1
+muli 1 65899 1
+bani 1 16777215 1
+gtir 256 2 5
+addr 5 3 3
+addi 3 1 3
+seti 27 3 3
+seti 0 3 5
+addi 5 1 4
+muli 4 256 4
+gtrr 4 2 4
+addr 4 3 3
+addi 3 1 3
+seti 25 3 3
+addi 5 1 5
+seti 17 5 3
+setr 5 5 2
+seti 7 6 3
+eqrr 1 0 5
+addr 5 3 3
+seti 5 8 3
diff --git a/problems/day20.html b/problems/day20.html
new file mode 100644 (file)
index 0000000..1646a8c
--- /dev/null
@@ -0,0 +1,238 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 20 - Advent of Code 2018</title>
+<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]-->
+<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
+<link rel="stylesheet" type="text/css" href="/static/style.css?20"/>
+<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/>
+<link rel="shortcut icon" href="/favicon.png"/>
+</head><!--
+
+
+
+
+Oh, hello!  Funny seeing you here.
+
+I appreciate your enthusiasm, but you aren't going to find much down here.
+There certainly aren't clues to any of the puzzles.  The best surprises don't
+even appear in the source until you unlock them for real.
+
+Please be careful with automated requests; I'm not Google, and I can only take
+so much traffic.  Please be considerate so that everyone gets to play.
+
+If you're curious about how Advent of Code works, it's running on some custom
+Perl code. Other than a few integrations (auth, analytics, ads, social media),
+I built the whole thing myself, including the design, animations, prose, and
+all of the puzzles.
+
+The puzzles are most of the work; the easiest ones take 3-4 hours each, but the
+harder ones take 6-8 hours, and a few even longer than that. A lot of effort
+went into building this thing - I hope you're enjoying playing it as much as I
+enjoyed making it for you!
+
+If you'd like to hang out, I'm @ericwastl on Twitter.
+
+- Eric Wastl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-->
+<body>
+<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2018/about">[About]</a></li><li><a href="/2018/events">[Events]</a></li><li><a href="https://teespring.com/adventofcode-2019" target="_blank">[Shop]</a></li><li><a href="/2018/settings">[Settings]</a></li><li><a href="/2018/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2018/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">38*</span></div></div><div><h1 class="title-event">&nbsp;&nbsp;&nbsp;<span class="title-event-wrap">sub y{</span><a href="/2018">2018</a><span class="title-event-wrap">}</span></h1><nav><ul><li><a href="/2018">[Calendar]</a></li><li><a href="/2018/support">[AoC++]</a></li><li><a href="/2018/sponsors">[Sponsors]</a></li><li><a href="/2018/leaderboard">[Leaderboard]</a></li><li><a href="/2018/stats">[Stats]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2018/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://xebia.com/community/advent-of-code" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);" rel="noopener">Xebia</a> - an international network of passionate technologists and craftspeople, dedicated to exploring and creating new frontiers in IT</div></div>
+</div><!--/sidebar-->
+
+<main>
+<article class="day-desc"><h2>--- Day 20: A Regular Map ---</h2><p>While you were learning about instruction pointers, the Elves made considerable progress. When you look up, you discover that the North Pole base construction project has completely surrounded you.</p>
+<p>The area you are in is made up entirely of <em>rooms</em> and <em>doors</em>. The rooms are arranged in a grid, and rooms only connect to adjacent rooms when a door is present between them.</p>
+<p>For example, drawing rooms as <code>.</code>, walls as <code>#</code>, doors as <code>|</code> or <code>-</code>, your current position as <code>X</code>, and where north is up, the area you're in might look like this:</p>
+<pre><code>#####
+#.|.#
+#-###
+#.|X#
+#####
+</code></pre>
+<p>You get the attention of a passing construction Elf and ask for a map. "I don't have time to draw out a map of this place - it's <em>huge</em>. Instead, I can give you directions to <em>every room in the facility</em>!" He writes down some directions on a piece of parchment and runs off. In the example above, the instructions might have been <code>^WNE$</code>, a <a href="https://en.wikipedia.org/wiki/Regular_expression">regular expression</a> or "<em>regex</em>" (your puzzle input).</p>
+<p>The regex matches routes (like <code>WNE</code> for "west, north, east") that will take you from your current room through various doors in the facility. In aggregate, the routes will take you through <em>every door in the facility at least once</em>; mapping out all of these routes will let you build a proper map and find your way around.</p>
+<p><code>^</code> and <code>$</code> are at the beginning and end of your regex; these just mean that the regex doesn't match anything outside the routes it describes. (Specifically, <code>^</code> matches the start of the route, and <code>$</code> matches the end of it.) These characters will not appear elsewhere in the regex.</p>
+<p>The rest of the regex matches various sequences of the characters <code>N</code> (north), <code>S</code> (south), <code>E</code> (east), and <code>W</code> (west). In the example above, <code>^WNE$</code> matches only one route, <code>WNE</code>, which means you can move <em>west, then north, then east</em> from your current position. Sequences of letters like this always match that exact route in the same order.</p>
+<p>Sometimes, the route can <em>branch</em>. A branch is given by a <em>list of options</em> separated by pipes (<code>|</code>) and wrapped in parentheses. So, <code>^N(E|W)N$</code> contains a branch: after going north, you must choose to go <em>either east or west</em> before finishing your route by going north again. By tracing out the possible routes after branching, you can determine where the doors are and, therefore, where the rooms are in the facility.</p>
+<p>For example, consider this regex: <code>^ENWWW(NEEE|SSE(EE|N))$</code></p>
+<p>This regex begins with <code>ENWWW</code>, which means that from your current position, all routes must begin by moving east, north, and then west three times, in that order. After this, there is a branch.  Before you consider the branch, this is what you know about the map so far, with doors you aren't sure about marked with a <code>?</code>:</p>
+<pre><code>#?#?#?#?#
+?.|.|.|.?
+#?#?#?#-#
+    ?X|.?
+    #?#?#
+</code></pre>
+<p>After this point, there is <code>(NEEE|SSE(EE|N))</code>. This gives you exactly two options: <code>NEEE</code> and <code>SSE(EE|N)</code>. By following <code>NEEE</code>, the map now looks like this:</p>
+<pre><code>#?#?#?#?#
+?.|.|.|.?
+#-#?#?#?#
+?.|.|.|.?
+#?#?#?#-#
+    ?X|.?
+    #?#?#
+</code></pre>
+<p>Now, only <code>SSE(EE|N)</code> remains. Because it is in the same parenthesized group as <code>NEEE</code>, it starts from the same room <code>NEEE</code> started in. It states that starting from that point, there exist doors which will allow you to move south twice, then east; this ends up at another branch. After that, you can either move east twice or north once. This information fills in the rest of the doors:</p>
+<pre><code>#?#?#?#?#
+?.|.|.|.?
+#-#?#?#?#
+?.|.|.|.?
+#-#?#?#-#
+?.?.?X|.?
+#-#-#?#?#
+?.|.|.|.?
+#?#?#?#?#
+</code></pre>
+<p>Once you've followed all possible routes, you know the remaining unknown parts are all walls, producing a finished map of the facility:</p>
+<pre><code>#########
+#.|.|.|.#
+#-#######
+#.|.|.|.#
+#-#####-#
+#.#.#X|.#
+#-#-#####
+#.|.|.|.#
+#########
+</code></pre>
+<p>Sometimes, a list of options can have an <em>empty option</em>, like <code>(NEWS|WNSE|)</code>. This means that routes at this point could effectively skip the options in parentheses and move on immediately.  For example, consider this regex and the corresponding map:</p>
+<pre><code>^ENNWSWW(NEWS|)SSSEEN(WNSE|)EE(SWEN|)NNN$
+
+###########
+#.|.#.|.#.#
+#-###-#-#-#
+#.|.|.#.#.#
+#-#####-#-#
+#.#.#X|.#.#
+#-#-#####-#
+#.#.|.|.|.#
+#-###-###-#
+#.|.|.#.|.#
+###########
+</code></pre>
+<p>This regex has one main route which, at three locations, can optionally include additional detours and be valid: <code>(NEWS|)</code>, <code>(WNSE|)</code>, and <code>(SWEN|)</code>. Regardless of which option is taken, the route continues from the position it is left at after taking those steps. So, for example, this regex matches all of the following routes (and more that aren't listed here):</p>
+<ul>
+<li><code>ENNWSWWSSSEENEENNN</code></li>
+<li><code>ENNWSWW<em>NEWS</em>SSSEENEENNN</code></li>
+<li><code>ENNWSWW<em>NEWS</em>SSSEENEE<em>SWEN</em>NNN</code></li>
+<li><code>ENNWSWWSSSEEN<em>WNSE</em>EENNN</code></li>
+</ul>
+<p>By following the various routes the regex matches, a full map of all of the doors and rooms in the facility can be assembled.</p>
+<p>To get a sense for the size of this facility, you'd like to determine which room is <em>furthest</em> from you: specifically, you would like to find the room for which the <em>shortest path to that room would require passing through the most doors</em>.</p>
+<ul>
+<li>In the first example (<code>^WNE$</code>), this would be the north-east corner <code><em>3</em></code> doors away.</li>
+<li>In the second example (<code>^ENWWW(NEEE|SSE(EE|N))$</code>), this would be the south-east corner <code><em>10</em></code> doors away.</li>
+<li>In the third example (<code>^ENNWSWW(NEWS|)SSSEEN(WNSE|)EE(SWEN|)NNN$</code>), this would be the north-east corner <code><em>18</em></code> doors away.</li>
+</ul>
+<p>Here are a few more examples:</p>
+<pre><code>Regex: ^ESSWWN(E|NNENN(EESS(WNSE|)SSS|WWWSSSSE(SW|NNNE)))$
+Furthest room requires passing 23 doors
+
+#############
+#.|.|.|.|.|.#
+#-#####-###-#
+#.#.|.#.#.#.#
+#-#-###-#-#-#
+#.#.#.|.#.|.#
+#-#-#-#####-#
+#.#.#.#X|.#.#
+#-#-#-###-#-#
+#.|.#.|.#.#.#
+###-#-###-#-#
+#.|.#.|.|.#.#
+#############
+</code></pre>
+<pre><code>Regex: ^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$
+Furthest room requires passing 31 doors
+
+###############
+#.|.|.|.#.|.|.#
+#-###-###-#-#-#
+#.|.#.|.|.#.#.#
+#-#########-#-#
+#.#.|.|.|.|.#.#
+#-#-#########-#
+#.#.#.|X#.|.#.#
+###-#-###-#-#-#
+#.|.#.#.|.#.|.#
+#-###-#####-###
+#.|.#.|.|.#.#.#
+#-#-#####-#-#-#
+#.#.|.|.|.#.|.#
+###############
+</code></pre>
+<p><em>What is the largest number of doors you would be required to pass through to reach a room?</em> That is, find the room for which the shortest path from your starting location to that room would require passing through the most doors; what is the fewest doors you can pass through to reach it?</p>
+</article>
+<p>To begin, <a href="20/input" target="_blank">get your puzzle input</a>.</p>
+<form method="post" action="20/answer"><input type="hidden" name="level" value="1"/><p>Answer: <input type="text" name="answer" autocomplete="off"/> <input type="submit" value="[Submit]"/></p></form>
+<p>You can also <span class="share">[Share<span class="share-content">on
+  <a href="https://twitter.com/intent/tweet?text=%22A+Regular+Map%22+%2D+Day+20+%2D+Advent+of+Code+2018&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2018%2Fday%2F20&amp;related=ericwastl&amp;hashtags=AdventOfCode" target="_blank">Twitter</a>
+  <a href="http://www.reddit.com/submit?url=https%3A%2F%2Fadventofcode%2Ecom%2F2018%2Fday%2F20&amp;title=%22A+Regular+Map%22+%2D+Day+20+%2D+Advent+of+Code+2018" target="_blank">Reddit</a
+></span>]</span> this puzzle.</p>
+</main>
+
+<!-- ga -->
+<script>
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-69522494-1', 'auto');
+ga('set', 'anonymizeIp', true);
+ga('send', 'pageview');
+</script>
+<!-- /ga -->
+</body>
+</html>
\ No newline at end of file
diff --git a/src/advent21/advent21.hs b/src/advent21/advent21.hs
new file mode 100644 (file)
index 0000000..198154b
--- /dev/null
@@ -0,0 +1,228 @@
+{-# LANGUAGE NegativeLiterals #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE BangPatterns #-}
+
+import Debug.Trace
+
+-- import Prelude hiding ((++))
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+
+import Data.Void (Void)
+import Text.Megaparsec hiding (State)
+import Text.Megaparsec.Char
+import qualified Text.Megaparsec.Char.Lexer as L
+import qualified Control.Applicative as CA
+
+import qualified Data.Map.Strict as M
+import Data.Map.Strict ((!))
+import qualified Data.Set as S
+import Data.Bits ((.&.), (.|.))
+
+import Control.Monad (when)
+import Control.Monad.State.Strict
+import Control.Monad.Reader
+import Control.Monad.Writer
+
+type Memory = M.Map Integer Integer
+
+data Location = Literal Integer | Register Integer deriving (Show, Eq)
+data Instruction = 
+      Addr Integer Integer Integer
+    | Addi Integer Integer Integer
+    | Mulr Integer Integer Integer
+    | Muli Integer Integer Integer
+    | Banr Integer Integer Integer
+    | Bani Integer Integer Integer
+    | Borr Integer Integer Integer
+    | Bori Integer Integer Integer
+    | Setr Integer Integer Integer
+    | Seti Integer Integer Integer
+    | Gtir Integer Integer Integer
+    | Gtri Integer Integer Integer
+    | Gtrr Integer Integer Integer
+    | Eqir Integer Integer Integer
+    | Eqri Integer Integer Integer
+    | Eqrr Integer Integer Integer
+    deriving (Eq, Show, Ord)
+
+
+data Machine = Machine { _registers :: M.Map Integer Integer
+                       , _pc :: Int
+                       , _history :: S.Set Integer
+                       , _previous :: Integer
+                       -- , _pcReg :: Integer
+                       } 
+               deriving (Show, Eq)
+
+type ProgrammedMachine = WriterT [Integer] (ReaderT (Integer, [Instruction]) (State Machine)) ()
+
+emptyMachine = Machine { _registers = M.fromList (zip [0..5] (repeat 0))
+                       , _pc = 0
+                       , _history = S.empty
+                       , _previous = 0
+                       }
+
+main :: IO ()
+main = do 
+        text <- TIO.readFile "data/advent21.txt"
+        let (ip, instrs) = successfulParse text
+        -- print (ip, instrs)
+        -- print $ zip [0..] instrs
+        print $ part1 ip instrs
+        print $ part2 ip instrs
+
+part1 ip instructions = 
+    runState (
+        runReaderT (
+            runWriterT executeInstructions1
+                   ) 
+            (ip, instructions)
+             ) 
+             emptyMachine
+
+part2 ip instructions = 
+    runState (
+        runReaderT (
+            runWriterT executeInstructions2
+                   ) 
+            (ip, instructions)
+             ) 
+             emptyMachine
+
+
+-- part2 ip instructions = head (dropWhile terminates [11592302..]) - 1
+-- part2 ip instructions = terminates 11592301
+--     where emptyRegisters = _registers emptyMachine
+--           m2 reg0 = emptyMachine {_registers = M.insert 0 reg0 emptyRegisters}
+--           terminates reg0 = null $ runResult (m2 reg0) ip instructions
+
+-- runResult machine ip instructions = r1Repeat
+--     where 
+--         r1Repeat = snd $ fst $ result
+--         result = 
+--           runState (
+--             runReaderT (
+--                 runWriterT executeInstructions2
+--                        ) 
+--                 (ip, instructions)
+--                  ) 
+--                  machine
+
+
+executeInstructions1 = 
+    do  (_, instrs) <- ask
+        m <- get
+        if (_pc m == 28) then do
+          tell [(_registers m)!1]
+        else do
+          when (_pc m >= 0 && _pc m < length instrs)
+              $
+              do executeInstruction
+                 executeInstructions1
+
+executeInstructions2 = 
+    do  (_, instrs) <- ask
+        m0 <- get
+        let r1 = (trace ("R1 = " ++ (show $ (_registers m0)!1) ++ " :: " ++ (show $ S.size (_history m0)))) $ (_registers m0)!1
+        if (_pc m0 == 28 && (S.member r1 (_history m0))) then do
+            -- abort as found a loop
+            tell $ [_previous m0]
+        else do
+            when (_pc m0 == 28) 
+                $
+                do 
+                    let m0' = m0 { _history = S.insert ((_registers m0)!1) (_history m0)
+                                 , _previous = (_registers m0)!1 }
+                    -- let x = trace ("PC = 28, register 1 = " ++ (show ((_registers m0)!1))) $! True
+                    put m0'
+            m <- get
+            when (_pc m >= 0 && _pc m < length instrs)
+                $
+                do  executeInstruction
+                    executeInstructions2
+
+
+executeInstruction :: ProgrammedMachine
+executeInstruction =
+    do  (pcIs, instrs) <- ask
+        m <- get
+        let instr = instrs!!(_pc m)
+        let memory0 = _registers m
+        let memory1 = M.insert pcIs (fromIntegral (_pc m)) memory0
+        let memory2 = perform instr memory1 
+        let pc' = fromIntegral ((memory2!pcIs) + 1)
+        -- let aaa = trace ("pc: " ++ show (_pc m) ++ " m0: " ++ show memory0 ++ " m1: " ++ show memory1 ++ "m2: " ++ show memory2 ++ "pc': " ++ show pc') $! True
+        let m' = m {_registers = memory2, _pc = pc'}
+        put m'
+
+
+perform :: Instruction -> Memory -> Memory
+-- perform instr memory | ((memory!5 == 7) || ((memory!5 == 3) && (memory!1 == 1))) && (trace ("Perform " ++ show instr ++ " " ++ show memory) False) = undefined
+-- perform instr memory | trace ("Perform " ++ show instr ++ " " ++ show memory) False = undefined
+perform (Addr a b c) !memory = M.insert c (memory!a + memory!b) memory
+perform (Addi a b c) !memory = M.insert c (memory!a + b) memory
+perform (Mulr a b c) !memory = M.insert c (memory!a * memory!b) memory
+perform (Muli a b c) !memory = M.insert c (memory!a * b) memory
+perform (Banr a b c) !memory = M.insert c (memory!a .&. memory!b) memory
+perform (Bani a b c) !memory = M.insert c (memory!a .&. b) memory
+perform (Borr a b c) !memory = M.insert c (memory!a .|. memory!b) memory
+perform (Bori a b c) !memory = M.insert c (memory!a .|. b) memory
+perform (Setr a b c) !memory = M.insert c (memory!a) memory
+perform (Seti a b c) !memory = M.insert c a memory
+perform (Gtir a b c) !memory = M.insert c (if a > (memory!b) then 1 else 0) memory
+perform (Gtri a b c) !memory = M.insert c (if (memory!a) > b then 1 else 0) memory
+perform (Gtrr a b c) !memory = M.insert c (if (memory!a) > (memory!b) then 1 else 0) memory
+perform (Eqir a b c) !memory = M.insert c (if a == memory!b then 1 else 0) memory
+perform (Eqri a b c) !memory = M.insert c (if (memory!a) == b then 1 else 0) memory
+perform (Eqrr a b c) !memory = M.insert c (if (memory!a) == (memory!b) then 1 else 0) memory
+
+
+-- evaluate :: Machine -> Location -> Integer
+-- evaluate _ (Literal i)  = i
+-- evaluate m (Register r) = M.findWithDefault 0 r (registers m)
+
+
+
+type Parser = Parsec Void Text
+
+sc :: Parser ()
+sc = L.space (skipSome spaceChar) CA.empty CA.empty
+
+lexeme  = L.lexeme sc
+integer = lexeme L.decimal
+symb = L.symbol sc
+
+
+instructionsP = (,) <$> headerP <*> many instructionP
+instructionP = choice [ addrP, addiP, mulrP, muliP, banrP, baniP, 
+    borrP, boriP, setrP, setiP, gtirP, gtriP, gtrrP, 
+    eqirP, eqriP, eqrrP ]
+
+headerP = symb "#ip" *> integer
+
+addrP = Addr <$> (try (symb "addr") *> integer) <*> integer <*> integer
+addiP = Addi <$> (try (symb "addi") *> integer) <*> integer <*> integer
+mulrP = Mulr <$> (try (symb "mulr") *> integer) <*> integer <*> integer
+muliP = Muli <$> (try (symb "muli") *> integer) <*> integer <*> integer
+banrP = Banr <$> (try (symb "banr") *> integer) <*> integer <*> integer
+baniP = Bani <$> (try (symb "bani") *> integer) <*> integer <*> integer
+borrP = Borr <$> (try (symb "borr") *> integer) <*> integer <*> integer
+boriP = Bori <$> (try (symb "bori") *> integer) <*> integer <*> integer
+setrP = Setr <$> (try (symb "setr") *> integer) <*> integer <*> integer
+setiP = Seti <$> (try (symb "seti") *> integer) <*> integer <*> integer
+gtirP = Gtir <$> (try (symb "gtir") *> integer) <*> integer <*> integer
+gtriP = Gtri <$> (try (symb "gtri") *> integer) <*> integer <*> integer
+gtrrP = Gtrr <$> (try (symb "gtrr") *> integer) <*> integer <*> integer
+eqirP = Eqir <$> (try (symb "eqir") *> integer) <*> integer <*> integer
+eqriP = Eqri <$> (try (symb "eqri") *> integer) <*> integer <*> integer
+eqrrP = Eqrr <$> (try (symb "eqrr") *> integer) <*> integer <*> integer
+
+successfulParse :: Text -> (Integer, [Instruction])
+successfulParse input = 
+        case parse instructionsP "input" input of
+                Left  _error -> (0, []) -- TIO.putStr $ T.pack $ parseErrorPretty err
+                Right instructions  -> instructions
\ No newline at end of file