From ca07f2995e9ee56d99a102c437f59bca5e01bed2 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Fri, 17 Jan 2025 13:49:30 -0500 Subject: [PATCH] Year 2015 Day 8 Part 2 --- src/Years/Y2015/Day8.md | 48 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/Years/Y2015/Day8.md b/src/Years/Y2015/Day8.md index cd94ff9..995da3d 100644 --- a/src/Years/Y2015/Day8.md +++ b/src/Years/Y2015/Day8.md @@ -199,7 +199,7 @@ string = do pure xs ``` -## Running a parser +### Running a parser Run a parser, with some debug logging, by peeling the parsing effects of of the type. The order is important here, remember that function composition "runs" @@ -284,6 +284,23 @@ runParser x str = do lazyRights (Right x :: xs) = x :: lazyRights xs ``` +## Escaping characters + +This is much more boring the the parsing, we just do simple recursive pattern +matching on the characters of the provided string, escaping `"` and `\`, and +surround the resulting string with quotes. + +```idris +escape : String -> String +escape str = "\"\{pack . escape' . unpack $ str}\"" + where + escape' : List Char -> List Char + escape' [] = [] + escape' ('"' :: xs) = '\\' :: '"' :: escape' xs + escape' ('\\' :: xs) = '\\' :: '\\' :: escape' xs + escape' (x :: xs) = x :: escape' xs +``` + ## Part Functions ### Part 1 @@ -293,7 +310,7 @@ possible failures by sequencing the `List (Maybe String)` into a `Maybe (List String)`, and the compute the difference in character counts. ```idris -part1 : Eff (PartEff String) (Int, ()) +part1 : Eff (PartEff String) (Int, List String) part1 = do inputs <- map lines $ askAt "input" outputs <- traverse (runParser string) inputs @@ -301,11 +318,34 @@ part1 = do | _ => throw "Some strings failed to parse" let difference = sum $ zipWith (\x, y => strLength x - strLength y) inputs outputs - pure (difference, ()) + pure (difference, inputs) +``` + +### Part 2 + +Map our character escaping function over our input string and compute the +difference in character counts. + +Make a little stop along the way to ensure that escape -> parse round trips +without changing the content of the string. + +```idris +part2 : List String -> Eff (PartEff String) Int +part2 inputs = do + let outputs = map escape inputs + Just reversed_outputs <- map sequence . traverse (runParser string) $ outputs + | _ => throw "Reversing escaping of the inputs failed" + unless (all id $ zipWith (==) inputs reversed_outputs) $ do + debug . delay . joinBy "\n" . map show . filter (\(x, y, z) => x /= z) $ + zip3 inputs outputs reversed_outputs + throw "Parsed outputs were not identical to inputs" + let difference = + sum $ zipWith (\x, y => strLength y - strLength x) inputs outputs + pure difference ```