Day 03 (& a bit of 04) of Advent of Code in Rust! Episode 67 of Unhindered by Coding
Channel: Unhindered by Coding!
Date: 2023-01-28

Did both parts of Day 03, and actually had a good start on Day 04!

On the first part, ikopor@Twitch pointed out that since `anyhow::bail!()` does a return, I can put it *inside* an `OK` and it will actually work. That did a nice job of simplifying the end of `process_rucksack()`.

I ended up pulling in `itertools` for part 2 of Day 03 so I could call `chunks(3)` to break the input lines into groups of three. Got kinda stuck on mapping across the chunks, but once I realized that I could use `reduce()` to intersect the three `HashSet`s, it wasn't too bad. A major issue was it took me a while to realize that I needed to call `.into_iter()` on the result of calling `chunks()`; all the documentation said this over and over, but it took me a while to realize what they actually _meant_ by what they were saying. I then had some trouble figuring out what type was being sent to `process_group()` by `.map(process_group)`, and ikopor@Twitch suggested being explicit about the closure so we could see the arguments. So changing

```rust
 .map(process_group)
```

to

```rust
 .map(|group| process_group(group))
```

let the Rust Analyzer (via VSCode) tell us that `group` (the argument to `process_goup()`) needed to be of type `Chunk(Lines)`. Nice trick!

To be honest, though, I don't fully grok how we can pass in `group: Chunk(Lines)` and then when we say `group.map()`, the values passed to the function in `map` are string slices (`&str`). It makes sense that they _should_ be that given that we're mapping over lines out of the file, but I don't really know how the Rust compiler gets from `Chunk(Lines)` to iterating over `&str`. (I think it would be useful if I knew how to check types like the compiler does, in a deterministic and structured way, but I've never seen someone describe that.)

NathanielBumppo@Twitch suggested a particularly nice use of `try_fold` as a way of dealing with closures that could return errors, and that really cleaned up the logic in my `process_pairs` function. They also suggested using `usize::from()` as a way of converting a boolean to an integer value (`usize` in this case), where `false` goes to zero and `true` goes to 1. This lets us replace

```rust
Ok(if overlaps(line)? {
 current_count + 1
} else {
 current_count
})
```

with

```rust
Ok(current_count + usize::from(overlaps(line)?))
```

My initial response was that I found this kinda obscure and didn't really want to go down this road. The more I thought about it, though, the more I bought into it as an idea. 

================

In the first few months of 2023 (at least to mid-March) I'm streaming at https://twitch.tv/NicMcPhee four times a week:

* Tuesday: 10am-noon CST
* Wednesday: 7-9pm CST
* Saturday: 2-4pm CST
* Sunday: 10am-noon CST

The Tuesday and Sunday slots will be focusing on building the EC system in Rust and on the ice-repos webapp. The Wednesday and Saturday slots will be going through the Advent of Code 2022 puzzles/exercises.

Thanks for watching!