summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShivesh Mandalia <mail@shivesh.org>2023-01-21 18:35:06 +0000
committerShivesh Mandalia <mail@shivesh.org>2023-01-21 18:35:06 +0000
commit5e1a6e19bc0a40795d39e541abf2f6bba39d1065 (patch)
treec612b4f4b75f1a748ef6ad7e6107a586081a07a7
parent1750a9dbd6b6c62da90e5e1da431c20e83c30dc8 (diff)
downloadAOC_2022_haskell-5e1a6e19bc0a40795d39e541abf2f6bba39d1065.tar.gz
AOC_2022_haskell-5e1a6e19bc0a40795d39e541abf2f6bba39d1065.zip
complete day 2
-rw-r--r--cabal.project2
-rw-r--r--day02/app/Main.hs204
-rw-r--r--day02/day02.cabal34
-rw-r--r--day02/examples/input.txt2500
-rw-r--r--day02/examples/test.txt3
5 files changed, 2742 insertions, 1 deletions
diff --git a/cabal.project b/cabal.project
index 5676cb5..e5eaf02 100644
--- a/cabal.project
+++ b/cabal.project
@@ -1,2 +1,2 @@
-- Local packages
-packages: day01
+packages: day01, day02
diff --git a/day02/app/Main.hs b/day02/app/Main.hs
new file mode 100644
index 0000000..c16fc53
--- /dev/null
+++ b/day02/app/Main.hs
@@ -0,0 +1,204 @@
+{-
+--- Day 2: Rock Paper Scissors ---
+
+The Elves begin to set up camp on the beach. To decide whose tent gets to be closest to the
+snack storage, a giant Rock Paper Scissors tournament is already in progress.
+
+Rock Paper Scissors is a game between two players. Each game contains many rounds; in each
+round, the players each simultaneously choose one of Rock, Paper, or Scissors using a hand
+shape. Then, a winner for that round is selected: Rock defeats Scissors, Scissors defeats
+Paper, and Paper defeats Rock. If both players choose the same shape, the round instead ends
+in a draw.
+
+Appreciative of your help yesterday, one Elf gives you an encrypted strategy guide (your puzzle
+input) that they say will be sure to help you win. "The first column is what your opponent is
+going to play: A for Rock, B for Paper, and C for Scissors. The second column--" Suddenly, the
+Elf is called away to help with someone's tent.
+
+The second column, you reason, must be what you should play in response: X for Rock, Y for
+Paper, and Z for Scissors. Winning every time would be suspicious, so the responses must have
+been carefully chosen.
+
+The winner of the whole tournament is the player with the highest score. Your total score is
+the sum of your scores for each round. The score for a single round is the score for the shape
+you selected (1 for Rock, 2 for Paper, and 3 for Scissors) plus the score for the outcome of
+the round (0 if you lost, 3 if the round was a draw, and 6 if you won).
+
+Since you can't be sure if the Elf is trying to help you or trick you, you should calculate the
+score you would get if you were to follow the strategy guide.
+
+For example, suppose you were given the following strategy guide:
+
+```
+A Y
+B X
+C Z
+```
+
+This strategy guide predicts and recommends the following:
+
+ In the first round, your opponent will choose Rock (A), and you should choose Paper (Y).
+ This ends in a win for you with a score of 8 (2 because you chose Paper + 6 because you
+ won).
+ In the second round, your opponent will choose Paper (B), and you should choose Rock (X).
+ This ends in a loss for you with a score of 1 (1 + 0).
+ The third round is a draw with both players choosing Scissors, giving you a score of 3 + 3
+ = 6.
+
+In this example, if you were to follow the strategy guide, you would get a total score of 15 (8
++ 1 + 6).
+
+What would your total score be if everything goes exactly according to your strategy guide?
+
+--- Part Two ---
+
+The Elf finishes helping with the tent and sneaks back over to you. "Anyway, the second column
+says how the round needs to end: X means you need to lose, Y means you need to end the round in
+a draw, and Z means you need to win. Good luck!"
+
+The total score is still calculated in the same way, but now you need to figure out what shape
+to choose so the round ends as indicated. The example above now goes like this:
+
+ In the first round, your opponent will choose Rock (A), and you need the round to end in a
+ draw (Y), so you also choose Rock. This gives you a score of 1 + 3 = 4.
+ In the second round, your opponent will choose Paper (B), and you choose Rock so you lose
+ (X) with a score of 1 + 0 = 1.
+ In the third round, you will defeat your opponent's Scissors with Rock for a score of 1 + 6
+ = 7.
+
+Now that you're correctly decrypting the ultra top secret strategy guide, you would get a total
+score of 12.
+
+Following the Elf's instructions for the second column, what would your total score be if
+everything goes exactly according to your strategy guide?
+-}
+{-# LANGUAGE DerivingStrategies #-}
+
+module Main (main) where
+
+import Data.ByteString.Lazy (ByteString)
+import Options.Applicative (Parser, ParserInfo, argument, execParser, fullDesc, help, helper, info, metavar, str)
+import Relude hiding (ByteString, readFile)
+import Text.Parsec (ParseError, parse, (<?>))
+import Text.Parsec.ByteString.Lazy (GenParser)
+import Text.Parsec.Char (oneOf, space, string)
+import Text.Parsec.Combinator (eof, many1)
+import Text.Parsec.Prim (parsecMap, try)
+
+type Opts :: Type
+newtype Opts = Opts {_filename :: Text}
+
+type RockPaperScissorsKind :: Type
+data RockPaperScissorsKind = Rock | Paper | Scissors
+ deriving stock (Show)
+
+instance Enum RockPaperScissorsKind where
+ fromEnum Rock = 1
+ fromEnum Paper = 2
+ fromEnum Scissors = 3
+ toEnum _ = error "Unsupported"
+
+type GameOutcome :: Type
+data GameOutcome = Win | Loss | Draw deriving stock (Show)
+
+instance Enum GameOutcome where
+ fromEnum Win = 6
+ fromEnum Loss = 0
+ fromEnum Draw = 3
+ toEnum _ = error "Unsupported"
+
+type GamePrediction :: Type
+data GamePrediction = GamePrediction {player :: RockPaperScissorsKind, opponent :: RockPaperScissorsKind} deriving stock (Show)
+
+options :: Parser Opts
+options = Opts <$> filename
+ where
+ filename :: Parser Text
+ filename = argument str $ metavar "filename" <> help "Input file"
+
+opts :: ParserInfo Opts
+opts = info (helper <*> options) fullDesc
+
+parseInput :: FilePath -> ByteString -> Either ParseError [(Char, Char)]
+parseInput = parse parser
+
+eol :: GenParser t st ()
+eol =
+ parsecMap
+ (const ())
+ ( try (string "\n\r")
+ <|> try (string "\r\n")
+ <|> string "\n"
+ <|> string "\r"
+ <?> "end of line"
+ )
+
+parser :: GenParser t st [(Char, Char)]
+parser = many1 block <* eof
+
+block :: GenParser t st (Char, Char)
+block = (,) <$> (oneOf "ABC" <* space) <*> oneOf "XYZ" <* (eol <|> eof)
+
+parseOpp :: Char -> RockPaperScissorsKind
+parseOpp 'A' = Rock
+parseOpp 'B' = Paper
+parseOpp 'C' = Scissors
+parseOpp _ = error "invalid char"
+
+parse1 :: Char -> RockPaperScissorsKind
+parse1 'X' = Rock
+parse1 'Y' = Paper
+parse1 'Z' = Scissors
+parse1 _ = error "invalid char"
+
+parse2 :: Char -> GameOutcome
+parse2 'X' = Loss
+parse2 'Y' = Draw
+parse2 'Z' = Win
+parse2 _ = error "invalid char"
+
+outcome :: GamePrediction -> GameOutcome
+outcome (GamePrediction Rock Scissors) = Win
+outcome (GamePrediction Paper Rock) = Win
+outcome (GamePrediction Scissors Paper) = Win
+outcome (GamePrediction Rock Paper) = Loss
+outcome (GamePrediction Paper Scissors) = Loss
+outcome (GamePrediction Scissors Rock) = Loss
+outcome _ = Draw
+
+fromOutcome :: GameOutcome -> RockPaperScissorsKind -> RockPaperScissorsKind
+fromOutcome Win Rock = Paper
+fromOutcome Win Paper = Scissors
+fromOutcome Win Scissors = Rock
+fromOutcome Loss Rock = Scissors
+fromOutcome Loss Paper = Rock
+fromOutcome Loss Scissors = Paper
+fromOutcome Draw a = a
+
+score :: GamePrediction -> Int
+score a = (fromEnum . player) a + (fromEnum . outcome) a
+
+runPart1 :: [(Char, Char)] -> Int
+runPart1 = sum . map (score . prediction)
+ where
+ prediction (a, b) = GamePrediction (parse1 b) (parseOpp a)
+
+prediction2 :: (Char, Char) -> GamePrediction
+prediction2 (a, b) = GamePrediction (fromOutcome (parse2 b) opp) opp
+ where
+ opp = parseOpp a
+
+runPart2 :: [(Char, Char)] -> Int
+runPart2 = sum . map (score . prediction2)
+
+main :: IO ()
+main = do
+ fileName <- toString . _filename <$> execParser opts
+ rawInput <- readFileLBS fileName
+ case parseInput fileName rawInput of
+ Left e -> do
+ putTextLn "Error parsing input:"
+ print e
+ Right r -> do
+ print $ runPart1 r
+ print $ runPart2 r
diff --git a/day02/day02.cabal b/day02/day02.cabal
new file mode 100644
index 0000000..13e5967
--- /dev/null
+++ b/day02/day02.cabal
@@ -0,0 +1,34 @@
+cabal-version: 2.4
+name: day02
+version: 0.1.0.0
+synopsis:
+
+-- A URL where users can report bugs.
+-- bug-reports:
+license:
+author: Shivesh Mandalia
+maintainer: mail@shivesh.org
+
+executable day02
+ main-is: Main.hs
+
+ -- Modules included in this executable, other than Main.
+ -- other-modules:
+
+ -- LANGUAGE extensions used by modules in this package.
+ default-extensions:
+ NoImplicitPrelude
+ OverloadedStrings
+ StandaloneKindSignatures
+
+ build-depends:
+ , base ^>=4.16.4.0
+ , optparse-applicative >=0.17.0.0
+ , parsec >=3.1.16.1
+ , relude ^>=1.1.0.0
+
+ hs-source-dirs: app
+ default-language: Haskell2010
+ ghc-options:
+ -Weverything -Wno-unused-packages -Wno-missing-safe-haskell-mode
+ -Wno-safe -Wno-missing-import-lists
diff --git a/day02/examples/input.txt b/day02/examples/input.txt
new file mode 100644
index 0000000..627a35e
--- /dev/null
+++ b/day02/examples/input.txt
@@ -0,0 +1,2500 @@
+B Z
+B X
+C Y
+B Y
+B Y
+A X
+A X
+B Z
+A Z
+B Z
+B Y
+B X
+C X
+B Y
+A Z
+B Y
+A X
+B X
+C Y
+B Y
+B Y
+C Y
+B X
+B X
+C X
+B Y
+B Y
+B Y
+C Y
+C X
+B Y
+C X
+C X
+B Y
+B Z
+C Y
+B Y
+B Z
+B X
+B Y
+B Y
+C Y
+B Y
+C Y
+C Y
+A Z
+B X
+C X
+B Y
+B X
+C X
+A X
+B Y
+C Y
+B X
+C X
+C Y
+B X
+B Z
+B Y
+B X
+C Y
+B X
+B Y
+B Y
+B Y
+B Y
+A X
+A Z
+B Z
+B Y
+C X
+B Y
+B Y
+C Y
+C Z
+C Z
+C X
+B X
+C Z
+B Y
+B Y
+C X
+C Z
+C X
+A Z
+C Y
+B Y
+B Y
+B Y
+C Y
+C Y
+C X
+C X
+C Z
+A X
+B Y
+C X
+B Z
+B Y
+C X
+B X
+B Z
+A Z
+C Y
+B Z
+C X
+C X
+B Y
+B Y
+B Y
+C Y
+C X
+B X
+B Y
+A Z
+A Z
+C Y
+B Y
+C Y
+C Y
+C Y
+B X
+A Z
+C Y
+C Y
+A Z
+A Z
+B X
+B Y
+B Z
+A Z
+B X
+B Y
+C Z
+C Z
+B Z
+B Y
+B X
+A Y
+C Z
+C X
+A Z
+A Z
+B Y
+B Y
+C Y
+C Y
+B Y
+B Y
+B Y
+A Z
+C Y
+C Z
+C X
+A Z
+B X
+B Y
+A Y
+A Y
+B Y
+B Y
+C X
+B Y
+B Y
+C Z
+B Y
+B Y
+A Z
+C Y
+B X
+C X
+A X
+C X
+B Y
+B X
+A Z
+C X
+C Y
+A Z
+B Y
+A Z
+B X
+B X
+A Z
+B Y
+C X
+C X
+A Z
+A X
+C X
+C X
+C X
+B Y
+C Z
+C Y
+C X
+B Y
+B Y
+B Y
+A X
+A Z
+C Y
+B Y
+B Y
+A X
+C Y
+C Z
+C Y
+C X
+B Y
+B Y
+B Y
+B Y
+A Z
+B Y
+A Z
+B X
+B Y
+B Y
+B X
+C Y
+A X
+A Z
+B Y
+C Y
+C Y
+B Y
+B Y
+C X
+B Y
+B X
+A Z
+B Y
+B Y
+C Y
+B Y
+B Y
+B Y
+A X
+B X
+B Z
+C Y
+B Z
+C X
+C X
+B Z
+B Y
+A Z
+A Z
+B Y
+C X
+A X
+C Y
+B Y
+B Y
+A X
+B Y
+A Y
+C Y
+B Y
+C X
+B Y
+A Z
+B Z
+C Y
+B Y
+B Y
+C X
+B Y
+B Y
+B Y
+C Z
+A X
+B Y
+B X
+C X
+C Z
+C Z
+C Y
+C Y
+A X
+C Y
+B Y
+A X
+C X
+A Z
+C X
+B Y
+C Z
+C Z
+A Z
+A X
+C Y
+C X
+B Y
+C Z
+B Y
+C Y
+C X
+C Y
+B Y
+B Y
+B Y
+A X
+A Z
+B Y
+B X
+B X
+B Y
+B Y
+B Y
+A Z
+B Y
+B Y
+A X
+A X
+A Z
+A Z
+B X
+C Y
+A Z
+B Y
+B Y
+C Z
+C X
+C Y
+A Z
+C Y
+C Y
+C Y
+C Y
+C X
+A Z
+C Z
+A Z
+C Y
+C X
+B Y
+B Y
+C Z
+B X
+B Z
+C X
+A Y
+C Y
+B X
+B X
+B Y
+C Y
+A Z
+A Z
+B X
+B Z
+B X
+C Y
+A X
+A X
+C Z
+B Y
+C Y
+C X
+B Y
+A Z
+B Y
+C Y
+B Z
+C Z
+C X
+B Z
+C Z
+B Z
+A X
+C Y
+A Z
+B Y
+B Y
+B Y
+B Y
+B Y
+B Y
+A Z
+C Z
+B X
+C X
+C Y
+C Y
+B Y
+C X
+C X
+A Y
+C Y
+C Y
+A Z
+C Z
+B Y
+B X
+C X
+B Y
+C X
+B Y
+B Y
+C X
+B Y
+B Y
+B Y
+A Z
+C Y
+B Z
+B Y
+C X
+B Y
+C X
+A Y
+A Z
+B Y
+B Y
+B Y
+A Z
+B Y
+B Y
+B Y
+B Y
+B Z
+C Y
+B Z
+B Z
+A Z
+B Y
+B Y
+C X
+A X
+B Y
+A Z
+C X
+C X
+B Y
+B Y
+A X
+B Y
+B Y
+C X
+B Y
+C X
+B Y
+B Y
+B Y
+B Y
+A X
+B Y
+B Z
+B Y
+A Z
+C X
+C X
+C Y
+A Z
+C Y
+B Y
+B X
+A X
+B Y
+A Z
+B Y
+C Y
+B Y
+B Y
+C Y
+C X
+A Z
+A X
+A Z
+C Z
+B Y
+B Y
+C Y
+B X
+C X
+B Y
+A Z
+B Y
+C X
+A X
+C X
+C Y
+C Y
+B X
+B Y
+B Y
+C Z
+B Y
+C X
+A Z
+C Z
+C Y
+A Z
+C X
+C Y
+C Y
+C X
+B Y
+B Y
+C Z
+A Z
+B Y
+A X
+B Y
+A X
+A X
+C Y
+C X
+A Z
+B Y
+C Y
+C X
+B Y
+B Y
+B Y
+B X
+B X
+A X
+C X
+B Y
+C Y
+A Z
+A Z
+A Z
+B Y
+A Z
+B Y
+C X
+B Y
+C X
+C Y
+A Z
+B Y
+B Z
+A Z
+B Y
+A Z
+B Y
+B Y
+C Z
+B Y
+B Y
+A Z
+A X
+C Z
+C Z
+B Z
+B Y
+A Z
+B Y
+B Y
+B Y
+B Y
+C Z
+A Z
+C X
+B X
+B Y
+A X
+A X
+B Y
+A Z
+A X
+C Y
+B Y
+C X
+A Z
+B Y
+C Z
+C Y
+B Y
+A X
+C Y
+B Y
+B Z
+A Y
+B Y
+B Y
+A Z
+B Y
+C Z
+C X
+B Y
+A Y
+C Z
+B X
+A X
+B Y
+B Y
+B Z
+B Z
+C Y
+B Y
+B Y
+A Z
+A Z
+B Y
+B X
+C Y
+C Y
+B Y
+B Y
+B Z
+B Z
+B Y
+C Y
+A Z
+B Y
+A Z
+B Y
+B Y
+A Z
+A Z
+C X
+C Z
+B Y
+C X
+B X
+A Z
+B Y
+B Y
+C X
+B Y
+B Y
+B Y
+B Y
+B X
+B Y
+A X
+B Z
+A Z
+C Z
+B X
+A Z
+C Y
+C Y
+A Z
+B Y
+C Z
+C Z
+C Y
+B Y
+B Y
+B Y
+A Z
+B Y
+B X
+C X
+B Y
+B Y
+B Y
+B Y
+C Y
+B Y
+C Y
+B Y
+C Y
+C X
+A Z
+C Y
+C Z
+C Z
+B X
+C Y
+B Y
+B X
+C Y
+B Y
+B Y
+C Y
+C X
+C X
+A Z
+B Y
+C X
+A Z
+C Z
+B Y
+B Y
+C X
+C X
+B Y
+B X
+C Y
+B Y
+B Y
+A Z
+A Z
+C Z
+A Z
+B Y
+C X
+C X
+B X
+B Y
+B Y
+B Z
+B Y
+B Y
+B Y
+B Y
+B Z
+B Y
+C Y
+C Z
+B Y
+C Y
+C Y
+C Y
+C Y
+A Z
+A Z
+C Y
+C Y
+A X
+B Y
+C Y
+A X
+C X
+C Y
+A Z
+B Y
+B Z
+A X
+B Y
+B Z
+B Y
+B Y
+B Z
+C X
+C Y
+B Y
+B Z
+B X
+A Z
+B Y
+C Y
+B Y
+B Y
+A X
+C X
+B Y
+C X
+B Y
+C Y
+A X
+A X
+A Z
+C Y
+B Y
+C Y
+C X
+B X
+C X
+C X
+A X
+A Z
+B Y
+B Y
+B Y
+A Z
+B Y
+B Y
+B Y
+B Y
+B Y
+B Y
+B X
+B Y
+C Y
+B Y
+A Z
+B Y
+C X
+C Y
+B Z
+C Z
+B Y
+A Y
+C X
+B Y
+B Y
+B Y
+C X
+A Y
+C Z
+B Y
+C X
+C Y
+C Y
+C Y
+C X
+C Y
+B Z
+B Y
+C Y
+C X
+B Y
+B Y
+B X
+C Y
+B X
+C Z
+B Y
+C X
+B Z
+C X
+B Y
+C X
+B Y
+C Y
+C Y
+A Z
+C Y
+C X
+B Y
+C X
+B X
+A Z
+B Y
+A Z
+A Z
+A Z
+C Y
+B X
+A Y
+C Y
+B Y
+B Y
+C Y
+C Y
+C X
+B X
+A X
+A Z
+C X
+A Y
+B X
+C Z
+B Y
+B Y
+B X
+C X
+B Y
+B Y
+B Y
+B X
+B Y
+C X
+B Y
+B Y
+C Z
+C Y
+B Y
+C Y
+B Y
+A Z
+C Z
+A Y
+B Y
+B Y
+B Y
+C Y
+C Y
+C Y
+B Y
+C Z
+B Y
+C Z
+A Z
+A Z
+C Z
+C Y
+C Z
+C Y
+A Z
+C X
+B X
+B Y
+C Y
+B Z
+C Z
+C X
+B Y
+A Z
+B Y
+C X
+B Z
+A X
+B Y
+A Z
+C Z
+C X
+C X
+C Y
+B Y
+B Y
+A Z
+A Z
+B Y
+B X
+A Z
+B Y
+C Y
+A X
+C Z
+B Y
+B X
+B Y
+C Y
+C Z
+B Z
+A Z
+B Y
+A X
+C X
+B Y
+A Z
+C X
+B Z
+C Y
+C Y
+C X
+C X
+C Y
+B Y
+B Y
+B Z
+B X
+C X
+B Z
+C X
+B X
+C Z
+C Z
+C X
+B Y
+C Y
+C X
+B Y
+A Z
+C Y
+C Z
+C Z
+C Y
+B Y
+A X
+C Z
+C X
+B Y
+C X
+C Z
+B Y
+C Y
+B Y
+C Y
+A Z
+B Z
+C Z
+C X
+B Z
+B Z
+B Y
+A Y
+C Y
+C Y
+B X
+B X
+B Y
+B Y
+B Y
+C X
+B Z
+B Y
+B Y
+B Y
+C X
+A X
+C Y
+A X
+B Y
+B Y
+B Y
+B Y
+B Y
+C Y
+C Y
+B Y
+B Y
+B Y
+B Y
+C Y
+B Y
+C X
+B Y
+B Y
+C X
+A Z
+A X
+C Y
+C Z
+B Y
+C X
+B Y
+B X
+A Z
+B X
+B Y
+B Y
+A Z
+B Y
+B Y
+B Y
+B Z
+A Z
+A X
+B Y
+A Z
+C Y
+B Y
+C X
+B Y
+C Y
+B Y
+B Y
+C X
+C Y
+A Y
+C X
+C Y
+B Y
+A Y
+A Z
+C Z
+A Y
+A Z
+B Y
+C Y
+C Y
+B Y
+B Y
+B Y
+B Y
+A Z
+B Y
+B Y
+B Y
+C X
+C X
+B Y
+C X
+B Y
+A Z
+B Y
+B X
+C Z
+C Y
+A Y
+B Y
+C Y
+B Y
+C Y
+C Y
+C Y
+C X
+C Y
+B Y
+B Y
+C Y
+B Y
+C Y
+A Z
+A X
+B Y
+A Z
+B Y
+C X
+C X
+B Y
+C Z
+B Y
+B Y
+C Y
+B Y
+C Z
+A Y
+B Y
+C Y
+B Y
+A Z
+C Y
+B Z
+C Y
+C Y
+C Z
+B Y
+C X
+B Z
+B Y
+B Y
+B Y
+C Z
+B Y
+B Y
+B Y
+A Z
+C X
+B Z
+B Y
+B Y
+C Y
+B Y
+C X
+B Y
+B Y
+C Y
+C X
+C Y
+B Y
+B Y
+C Y
+B Y
+A Y
+B Y
+A Z
+B Y
+B Y
+B X
+A Z
+B Y
+B Y
+C Y
+C X
+C Z
+A Z
+A Z
+C X
+B Y
+C Y
+B Y
+C X
+B Y
+B Y
+C Y
+C X
+B Y
+B Y
+B Y
+B Y
+B Y
+C X
+B Z
+B Z
+A Z
+B Z
+B Y
+B Z
+B Y
+C Y
+A Z
+A X
+B Y
+C Z
+B X
+A X
+C Y
+B Y
+B Y
+C Y
+B Y
+C Y
+B Y
+A Z
+B Y
+B Y
+A Z
+B Y
+B Y
+A Z
+B Y
+B Y
+B Y
+B Y
+C Y
+B Y
+A X
+A X
+B Y
+B Y
+A Y
+C Z
+A Z
+A Z
+B Y
+A Z
+C Y
+B Y
+B Y
+B Y
+B Y
+C Y
+B Y
+A X
+B X
+B Y
+B Y
+B Y
+B Y
+B X
+C Y
+B Y
+B Y
+B X
+C Y
+A Y
+B Y
+B Y
+B Y
+A X
+B Z
+C X
+A X
+C Z
+B Y
+B Y
+B Y
+C X
+B Y
+B Y
+B Y
+B Y
+C Y
+B Z
+B Z
+B Y
+B Z
+B Y
+B Y
+C Z
+C Y
+B Y
+C Z
+C Z
+B Y
+C X
+A Y
+B Y
+B Z
+A Z
+B Y
+C X
+B Y
+B Y
+C Z
+A Z
+B Y
+B X
+B Y
+C Y
+B Y
+B Z
+B Y
+B Y
+C X
+C X
+C Z
+B Y
+B Y
+B Y
+A Z
+A X
+B Y
+A Z
+B Y
+B Y
+B Y
+B Z
+C X
+C Z
+B Y
+B Y
+B Y
+C Z
+B X
+C Z
+A X
+B Y
+C Y
+B Y
+A Z
+A X
+C X
+B X
+A Z
+C X
+B Y
+C Y
+B X
+A Z
+C Y
+C Y
+B Z
+C X
+B Y
+C X
+C Z
+C Y
+B Y
+C Z
+B Y
+B Y
+C X
+B Y
+B Y
+B Y
+B Y
+B Y
+B Y
+C X
+B Y
+B Y
+B Y
+A Z
+B Y
+B Y
+C Z
+B Y
+B Y
+B Y
+C X
+A Z
+B Z
+C Y
+C Y
+B Y
+A X
+C Y
+B Y
+C Z
+B Z
+B Y
+B Y
+C Y
+B Y
+B Y
+B Y
+C Z
+A X
+B Y
+C Y
+A X
+B Y
+B Y
+A X
+B Y
+A Y
+C X
+A Z
+A Z
+C Y
+B Y
+C Z
+C Y
+C Y
+C Z
+A Z
+A X
+C Z
+B Y
+C X
+A Z
+C X
+B Y
+B Y
+B Y
+C Z
+C Y
+C X
+C Y
+A Y
+C X
+A Z
+A Z
+B Z
+C X
+B Y
+B Y
+C X
+A Z
+C Z
+C Z
+B Y
+B Y
+A Y
+C X
+B Z
+B Y
+B Y
+C X
+C X
+C Z
+C Z
+B Y
+B Y
+B X
+B Y
+B Y
+C Z
+C Y
+C Z
+B Y
+B Y
+B Y
+C Y
+B X
+C X
+A Z
+C X
+C X
+C Y
+B Y
+B Y
+C Y
+B Z
+B Z
+C X
+C Y
+B Y
+B Z
+B Y
+B X
+A Z
+C X
+B Z
+A Z
+C X
+B Y
+C Y
+C Y
+B Y
+B Y
+B Y
+B X
+A X
+B Y
+A X
+A Z
+C Y
+B Y
+B Y
+B Y
+B Y
+B Y
+C Z
+B X
+B Y
+C X
+A Z
+B Y
+B Y
+A Z
+B Y
+C Y
+C Z
+C X
+C Y
+B Y
+B Y
+B Z
+B Y
+A X
+C Y
+B Y
+A X
+B Y
+C X
+A Z
+B Y
+C X
+A Z
+B Y
+C X
+C Y
+C X
+B Z
+C Z
+B Y
+C Y
+C X
+C Y
+B Z
+B X
+A X
+C Z
+B Y
+B Y
+C Y
+B Z
+C X
+C X
+B Y
+B Y
+C Y
+B X
+B Y
+C Y
+B Y
+B Y
+A Z
+B Y
+B Y
+B Y
+A X
+A Z
+B Z
+B Z
+B Y
+A Z
+B Y
+C Y
+B Y
+C X
+B X
+B Y
+B Y
+B X
+C Z
+B Y
+C Z
+C X
+B Y
+C Z
+B Y
+C Y
+B Z
+C Y
+C Y
+C Z
+C Z
+A X
+B Y
+A Z
+B Y
+B X
+A X
+B Y
+B Y
+B Y
+C Y
+B Y
+B X
+B Z
+C Z
+B X
+B Z
+B Y
+C Y
+B Y
+B Z
+C X
+A Z
+B X
+B Z
+C X
+C Z
+B Y
+A Z
+C X
+C Y
+B Z
+B Y
+C Y
+B Y
+C Y
+B Y
+B Y
+B Y
+C Y
+B Y
+C Y
+C X
+C Z
+B Y
+B Y
+B X
+C Z
+B X
+A Z
+C Y
+A Z
+C X
+C Y
+B Y
+C Z
+B Z
+C Z
+C Y
+C X
+B Y
+C Z
+C X
+B Y
+B Y
+B Y
+B X
+B Y
+B Y
+C X
+A X
+B Z
+C X
+C Z
+B Y
+C Y
+B Z
+C Z
+B Y
+C X
+B Y
+B Y
+A Z
+C Z
+B Y
+C Z
+C X
+B Y
+B Y
+C X
+C X
+C Y
+B Y
+A X
+A Z
+B Y
+C X
+B Y
+B Y
+C Y
+B Y
+A Z
+A Z
+C X
+C Z
+C X
+C X
+A X
+B Y
+B Y
+C Y
+C Z
+C Y
+B Z
+C Y
+B Y
+B Y
+B Y
+C Y
+B Z
+B Y
+B Y
+B X
+C Y
+C Y
+B Y
+A X
+C X
+A X
+C Z
+C Y
+A Y
+B Y
+B Y
+B Z
+C X
+C X
+B Y
+A X
+B Y
+A Z
+B Y
+A Z
+C X
+C X
+B Y
+B Y
+B Y
+B Y
+A X
+B Y
+B Z
+C Y
+C X
+C Z
+C Z
+B Y
+C Z
+B Y
+B Y
+C X
+B Y
+A X
+A Z
+B Y
+A Z
+C X
+B Y
+C Y
+B Z
+C Z
+B Y
+B Y
+B Y
+B Y
+C Y
+C Z
+B X
+B Y
+A Y
+C Y
+B Z
+B Y
+C Y
+A Z
+B Y
+B Y
+C Y
+C Y
+A Y
+C Y
+A Z
+C Y
+B X
+B Y
+B Y
+C Y
+A Z
+C Y
+A Z
+B Y
+B Y
+B Y
+B Y
+A X
+C Y
+A Z
+B Y
+B Y
+B Y
+B Y
+B Z
+C Z
+C Y
+C X
+B Y
+C X
+B Y
+B Y
+B Y
+B Y
+A Z
+B Y
+C Y
+C Y
+A Z
+A X
+B Y
+C Y
+C Y
+B Y
+C Y
+C Y
+C Y
+C Z
+A Z
+C X
+C Y
+C X
+B Y
+B Y
+C X
+C Z
+C X
+C Z
+B X
+B Y
+C Z
+B Z
+A Z
+C Y
+B Z
+C Y
+B Y
+A X
+B Y
+A Z
+B Y
+A X
+B Y
+B X
+B Z
+B X
+B Y
+B Y
+B Y
+C X
+B Y
+B X
+C X
+B Y
+B Z
+B Y
+C Y
+B Y
+B Y
+C X
+A Z
+C X
+B Y
+C Y
+C Z
+B Y
+C Z
+B Y
+B Y
+B Y
+B Y
+C Z
+C X
+C Y
+C Z
+B X
+A Z
+A Z
+B Y
+B Z
+C Y
+A X
+B Y
+B Y
+A Z
+B Y
+B Y
+B Y
+B Y
+A Z
+C Z
+B Z
+C Y
+A Z
+C Y
+B Y
+B Y
+B Y
+B Z
+B Y
+C X
+C Z
+B X
+C X
+B Y
+C Z
+C X
+B Y
+A Z
+A Z
+B Y
+B Y
+B Y
+C X
+A Y
+B Y
+B Y
+A Z
+A Z
+C Z
+C Y
+B Y
+B Y
+A X
+B Z
+A X
+B Y
+A Z
+B Y
+C X
+B Y
+A Y
+B Y
+B Z
+B Y
+B Z
+B Y
+B Y
+C Y
+C Y
+B Y
+C X
+C Z
+B Y
+B Y
+B Y
+C Z
+A Z
+C X
+B Y
+B Z
+B Y
+C Y
+B Y
+C X
+B Y
+B Y
+C Y
+B Y
+B Y
+B Y
+B Y
+B Y
+B Y
+B X
+B Y
+B Y
+C X
+B Y
+B Z
+A Z
+A Z
+C X
+B X
+B X
+C Y
+C Z
+B Y
+C X
+A X
+B Y
+C X
+C Z
+C X
+B Y
+B Y
+C Y
+B Y
+B Y
+B Y
+A Z
+C Z
+C X
+B Y
+B Y
+A X
+B Y
+C Y
+B Y
+B Y
+C Y
+B X
+B X
+A X
+C Y
+C Z
+C Y
+B Y
+B Y
+C X
+A X
+A X
+C X
+B Y
+C X
+B Y
+B Y
+B Y
+C Y
+A Z
+B Z
+A Z
+B Y
+B X
+C Y
+B Z
+B Y
+A Z
+B Y
+C Y
+B Y
+C Y
+A X
+B Y
+B Y
+B Y
+C X
+A Z
+C Y
+B Y
+B Y
+B Y
+C X
+B Y
+C Y
+B Y
+B X
+C X
+B Y
+B Y
+C Y
+C X
+C Z
+C Z
+B Y
+B Y
+B Y
+B X
+C X
+B X
+A Y
+A Z
+C Y
+A X
+B Y
+B Y
+B Y
+A Z
+C Y
+C X
+C Y
+C Z
+A Z
+B Y
+B Y
+B Y
+B Y
+A Z
+B Y
+A Z
+B Y
+B Y
+C Y
+C Z
+C Y
+A Z
+C Y
+B Y
+C Y
+B X
+B Y
+A X
+C Z
+C Z
+A X
+C X
+C Z
+C X
+C X
+B Y
+A X
+A Z
+C Y
+B Y
+C X
+B Y
+B Y
+B X
+C Y
+C Z
+B Y
+B Z
+A Z
+C Y
+B Y
+A Z
+B Y
+C X
+C X
+B Z
+C Y
+B X
+B Y
+C Y
+B Z
+A Z
+C X
+C Y
+C X
+C Z
+B Z
+C Z
+B Y
+B X
+B Y
+B X
+B Y
+B Y
+B Y
+B Y
+C X
+C X
+C Y
+B Z
+C X
+B Y
+B Y
+B Z
+C Z
+C Y
+B Y
+B Y
+B Y
+C X
+B Z
+B Y
+B X
+B Y
+C Y
+C X
+C Z
+C X
+C Y
+B Y
+B Y
+B X
+B Y
+C X
+B X
+A X
+B Y
+C Y
+B Y
+A X
+C Y
+B Z
+B Z
+C X
+C Z
+C X
+B Y
+C Y
+C Y
+B Y
+C Z
+B Y
+C Y
+B Y
+C Y
+A Z
+B Z
+C X
+C X
+B Y
+B Y
+B Z
+B Y
+B Z
+A X
+C X
+C X
+B Y
+C X
+A Z
+C Y
+B Y
+A Z
+C Z
+B X
+C Y
+C X
+C X
+A Z
+B Y
+B Y
+C Z
+B Y
+A Y
+C Y
+B Y
+B X
+B Z
+C X
+B Y
+B X
+C Z
+B Y
+B X
+B Y
+B Y
+B Y
+A Z
+A Z
+B Z
+A Z
+C Y
+C Z
+B X
+C X
+A Z
+C X
+B Y
+B Y
+A X
+B X
+B Y
+B X
+B X
+A Y
+A Z
+C X
+B Z
+B Z
+C Y
+C Y
+B Y
+B Y
+B Y
+A Z
+A Z
+B Y
+B Y
+C Y
+C Y
+C Y
+C Z
+C X
+C Y
+B Y
+B X
+B Y
+A Y
+A X
+C Y
+B Y
+A Z
+B Y
+B Y
+C X
+C X
+B Y
+B Y
+C Y
+A Z
+B Y
+C Y
+C Z
+C Z
+C Y
+A Y
+B Y
+B Y
+C Y
+B X
+C Z
+C Z
+C Z
+B Y
+B Y
+B Y
+C Y
+A Z
+B Y
+A Z
+B Y
+A Z
+C X
+C Z
+C Y
+B Y
+A Z
+B Y
+B Y
+C Z
+B Y
+C X
+B Y
+C Y
+C Y
+B Y
+B Y
+A X
+C Z
+B Y
+C Y
+C X
+B Y
+B Y
+B Y
+B Z
+A Z
+B Y
+B Y
+B Y
+A Z
+B Y
+A X
+B Y
+B Y
+B Y
+C Y
+C X
+C Y
+A Z
+B Y
+C Y
+B Y
+C Y
+C Y
+C Y
+A X
+C Z
+B Y
+B Y
+C Z
+B Y
+B Y
+C Z
+B Z
+B Y
+C Y
+B Y
+B Y
+B Y
+B Y
+B X
+C X
+C Y
+B Y
+A Z
+B Y
+A X
+B Y
+B Y
+B Y
+B Y
+C Z
+C Z
+B Y
+A Z
+B Y
+C X
+C X
+C Y
+B X
+A X
+B X
+B Y
+C X
+C Z
+C Y
+C Y
+B Y
+C Z
+B Y
+B Y
+C Z
+A X
+B Y
+C Z
+B Z
+B Y
+C X
+C X
+B Y
+B Y
+B X
+C Z
+A Z
+A X
+B Y
+C X
+B Y
+B Y
+C Z
+B Z
+C Y
+B Y
+B X
+C X
+C Z
+B Z
+B Z
+C Y
+B Y
+A X
+B Y
+B Y
+C X
+B X
+A Z
+B Y
+A Z
+B Y
+B Y
+A Z
+C X
+C X
+B Y
+B X
+B Y
+A Z
+C Y
+C Z
+B Y
+B Y
+A X
+B Y
+C Y
+C Y
+B Y
+A X
+B Y
+B Y
+A Z
+C X
+C X
+C Y
+B Y
+A X
+B Y
+B Y
+C Y
+B Y
+B Y
+B Y
+B Z
+B Y
+C Y
+C Y
+B Y
+C X
+C X
+B Y
+C Y
+B Y
+C X
+B Y
+B Z
+B Y
+A Z
+A Z
+C X
+A Z
+A Z
+B Y
+B X
+C Z
+B Y
+B Y
+B Y
+B Y
+B Y
+C X
+C Y
+B Y
+A X
+C X
+C X
+C Y
+B Y
+C X
+C X
+C Z
+B Z
+C Y
+C X
+B Y
+B Y
+C X
+B X
+C Z
+B Y
+B Y
+C Y
+A Z
+C Y
+C X
+C Y
+B Y
+B Y
+C X
+C Y
+C Y
+C X
+B Z
+B Z
+B Y
+B Y
+C Y
+B Y
+C X
+A Z
+A X
+C Z
+B Y
+C Y
+C Y
+B Y
+B Y
+C Y
+B Y
diff --git a/day02/examples/test.txt b/day02/examples/test.txt
new file mode 100644
index 0000000..db60e36
--- /dev/null
+++ b/day02/examples/test.txt
@@ -0,0 +1,3 @@
+A Y
+B X
+C Z