Day 04 & the crazy parsing of Day 05 of Advent of Code in Rust! Episode 68 of Unhindered by Coding
Channel: Unhindered by Coding!
Date: 2023-01-30

### Day 04

We finished off Day 04, part 1 pretty easily. We added a `SectionAssignment` type and the tools for parsing those. Then we just needed a simple `SectionAssignment::contains()` method to finish the logic off.

Part 2 of Day 04 was also pretty straightforward – I "just" had to modify the logic to support partial overlap instead of complete containment. I got that wrong the first time, though, because I thought something (what is now called `SectionAssignment::contains_endpoint_of`) was symmetric when it's not, and I needed to call both `first.contains_endpoint_of(&second)` _and_ `second.contains_endpoint_of(&first)`. Once I resolved that, though, we were good.

### Starting Day 05

At least a few people had apparently been waiting for me to get to Day 05 because there's a somewhat tricky parsing problem in reading the inputs, in particular the initial state of the stacks. #Wgaffa said that some folks did an end run and hand-coded that initial state into their system, but I went ahead and parsed things for the practice. We spent over an hour on just that part of the parsing, which we completed right at the end of the session.

In `extract_stack_elements()` I ended up `collect()`ing the characters in a line into a `Vec`. It's possible we could have avoided that through using `nth()` on the `line.chars()` iterator, but the advancing is weird and we'd have to special case the first stack in annoying ways. Most of the time was spent writing `impl FromStr for Stacks`. It was only 10 lines or so in the end, but there's a lot in those lines and it definitely took some work and thinking. We spent a while discussing why I didn't need more `mut` in those lines, and I'm still not _100%_ sure I understand why we don't need more things to be declared as _mut_. I think, though, that we end up passing ownership (not borrowing) pretty much everywhere, and code that _owns_ a value can mutate it without worrying about what that might to do someone else.

As an example, consider

```rust
fn main() {
    let s = "Morris".to_string();
    add_state(s);
}

fn add_state(s: String) {
    do_add_state(s);
}

fn do_add_state(mut s: String) {
    s.push_str(", Minnesota");
    println!("I live in {s}");
}
```

This compiles and runs fine, even those `s` isn't marked as mutable in either `main()` or `add_state()`. That's because the ownership is passed on to the functions being called, and when we do finally need to mutate (in `do_add_state()`) we can do that freely because we _own_ the value at that point and am guaranteed that no one upstream will be affected by our modification of the value. Since, for example, `add_state()` doesn't actually modify the `String` it's given, it doesn't need to declare it as `mut`.  It just passes ownership off to `do_add_state()` and doesn't know or care what (if anything) `do_add_state()` might do to it.

As another example, consider:

```rust
fn main() {
    let s = "Morris".to_string();
    add_state(s);
}

fn add_state(s: String) {
    do_add_state(s);
}

fn do_add_state(s: String) {
    let mut t = s;
    t.push_str(", Minnesota");
    println!("I live in {t}");
}
```

Here _none_ of the functions have their parameters declared as `mut`. Since `do_add_state()` _owns_ the `String`, though, it can redeclare it as `mut t`, and then perform `mut` operations on that value.

So in our code there will only be _one_ copy of `Stacks` being passed around in `Stacks::from_str` (even though the passing is fairly complex), so when someone finally needs to modify it (in the innermost closure) they can safely declare it as `mut` since they _own_ it and know that their modification of it can't affect anyone else in the control flow. Really cool, actually, and actually a lot more like functional programming, where you would only have one value at any given time.

After the stream ended I did some additional documentation and refactoring to try to make the code a little more readable.

In the next #AdventOfCode session we'll need to add parsing for the movement instructions, and then interpret those on our `Stacks` state.

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

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!