Year 2015 Day 8 Part 2

This commit is contained in:
Nathan McCarty 2025-01-17 13:49:30 -05:00
parent 9a16de8be7
commit ca07f2995e

View file

@ -199,7 +199,7 @@ string = do
pure xs pure xs
``` ```
## Running a parser ### Running a parser
Run a parser, with some debug logging, by peeling the parsing effects of of the 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" 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 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 Functions
### Part 1 ### 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. `Maybe (List String)`, and the compute the difference in character counts.
```idris ```idris
part1 : Eff (PartEff String) (Int, ()) part1 : Eff (PartEff String) (Int, List String)
part1 = do part1 = do
inputs <- map lines $ askAt "input" inputs <- map lines $ askAt "input"
outputs <- traverse (runParser string) inputs outputs <- traverse (runParser string) inputs
@ -301,11 +318,34 @@ part1 = do
| _ => throw "Some strings failed to parse" | _ => throw "Some strings failed to parse"
let difference = let difference =
sum $ zipWith (\x, y => strLength x - strLength y) inputs outputs 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
``` ```
<!-- idris <!-- idris
public export public export
day8 : Day day8 : Day
day8 = First 8 part1 day8 = Both 8 part1 part2
--> -->