X-Git-Url: https://git.njae.me.uk/?p=advent-of-code-20.git;a=blobdiff_plain;f=advent19%2Fsrc%2Fadvent19atto.hs;fp=advent19%2Fsrc%2Fadvent19atto.hs;h=b322324de0b9d2c3622f27cbd519f56946be10ab;hp=0000000000000000000000000000000000000000;hb=cc6239892b5dea639d6787a53bffef90a5cf2841;hpb=39598d4a19968acde767a9af7ce4cf0736062e47 diff --git a/advent19/src/advent19atto.hs b/advent19/src/advent19atto.hs new file mode 100644 index 0000000..b322324 --- /dev/null +++ b/advent19/src/advent19atto.hs @@ -0,0 +1,104 @@ +-- import Debug.Trace + +import Data.Text (Text) +import qualified Data.Text as T +import qualified Data.Text.IO as TIO + +import Data.Attoparsec.Text +-- import Data.Attoparsec.Combinator +import Control.Applicative +-- import Control.Applicative.Combinators + +import qualified Data.IntMap.Strict as M +import Data.IntMap.Strict ((!)) +import Data.Functor (void) +import Prelude hiding (take) +import Data.Either + + +data Rule = Letter Char + -- | Then2 Rule Rule + -- | Then3 Rule Rule Rule + | Then [Rule] + | Or Rule Rule + | See Int + deriving (Show, Eq) + +-- data Tree = TEmpty +-- | TLetter Char +-- | TThen [Tree] +-- deriving (Show, Eq) + + +type RuleSet = M.IntMap Rule + + +main :: IO () +main = + do text <- TIO.readFile "data/advent19b.txt" + -- print text + let (rules, messages) = successfulParse inputP text + let messagesT = map T.pack messages + -- print rules + -- print messages + print $ part1 rules messagesT + print $ part2 rules messagesT + -- print $ part2 text + +setup fname = + do text <- TIO.readFile fname + let (rules, messages) = successfulParse inputP text + let messagesT = map T.pack messages + let Right newRules = parseOnly rulesP "8: 42 | 42 8\n11: 42 31 | 42 11 31" + let updatedRules = M.union newRules rules + let myParser = (makeParser updatedRules (See 0)) <* endOfInput + return (myParser, updatedRules, messagesT) + + + +part1 = countMatches + +part2 rules messages = countMatches updatedRules messages + where Right newRules = parseOnly rulesP "8: 42 | 42 8\n11: 42 31 | 42 11 31" + updatedRules = M.union newRules rules + +countMatches rules messages + = length + $ filter isRight + $ map (parseOnly myParser) messages + where myParser = ((makeParser rules (See 0)) <* endOfInput) + + +-- Generate the rules + +makeParser :: RuleSet -> Rule -> Parser () +makeParser m (Letter c) = void $ char c +makeParser m (Then rs) = mapM_ (makeParser m) rs +makeParser m (Or a b) = (makeParser m a) <|> (makeParser m b) +makeParser m (See i) = makeParser m (m!i) + + +-- Parse the input + +rulesP = M.fromList <$> ruleP `sepBy` endOfLine +ruleP = (,) <$> decimal <* ": " <*> ruleBodyP +ruleBodyP = choice [letterRuleP, orRuleP, thenRuleP, seeRuleP] + +letterRuleP = Letter <$> ("\"" *> anyChar) <* "\"" +orRuleP = Or <$> thenRuleP <* " | " <*> thenRuleP +thenRuleP = Then <$> seeRuleP `sepBy` (string " ") +seeRuleP = See <$> decimal + + +inputP = (,) <$> rulesP <* blankLines <*> messagesP + +messagesP = (many1 letter) `sepBy` endOfLine + +blankLines = skipMany1 endOfLine + + +-- successfulParse :: Text -> (Integer, [Maybe Integer]) +successfulParse parser input = + case parseOnly parser input of + Left _err -> (M.empty, []) -- TIO.putStr $ T.pack $ parseErrorPretty err + Right expressions -> expressions