---
title: "Advent of Code: Day Five"
date: 2022-12-05T00:00:00
slug: advent-of-code-day-five
tags: [advent-of-code-2022]
---
**Spoilers for Advent of Code below**

* [Day four](/post/advent-of-code-day-four)
* [All Advent of Code posts](/blog/category/advent-of-code)
* [Source](https://github.com/lewisdaleuk/advent-of-code-2022)

Today was the first day that I can definitely say that I struggled to get the task done.

## Part one

The brief _sounded_ fairly simple. Given a list of "stacks" of boxes (represented by a character), and a set of instructions (in the format `move n from x to y`), work out what the final configuration would look like.

The input:

```bash
    [D]    
[N] [C]    
[Z] [M] [P]
	1   2   3 

move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
```

I was planning out my data structures, and this is where I made my first and silliest mistake: I used String for my stacks. "They're just lists of chars", I thought, this should be easy.

Unfortunately, my logic was off and I kept forgetting to reverse my strings, leading to a lot of banging my head against the wall when I came up with this:

```rust
#[derive(Debug, PartialEq, Eq)]
struct Operation {
	quantity: usize,
	source: usize,
	target: usize
} 

#[derive(Debug, PartialEq, Eq)]
pub struct Crane {
	pub stacks: Vec<String>,
	operations: VecDeque<Operation>,
}

impl Crane {
	fn operate(&mut self) {
		let operation = self.operations.pop_front().unwrap();
		let split: String = self.stacks[operation.source - 1].take(operation.quantity).unwrap();
		self.stacks[operation.target - 1].insert_str(0, &split);
	}
}
```

The `take` function was my first foray into using `Trait` to extend a core type:

```rust
trait Take<T> {
	fn take(&mut self, n: usize) -> Option<T>;
}

impl Take<String> for String {
	fn take(&mut self, n: usize) -> Option<String> {
		if n <= self.len() {
			let split = String::from(&self[..n]);
			self.replace_range(..n, "");
			return Some(split);
		}
		None
	}
}
```

But this didn't work, because my take function took the _top_ off the string, and then replaced it in the original order, so instead of going from:

```bash
      P
N     Z
C  D  B
```

to:

```bash   
N     
C     P
P     Z
Z  D  B
```

I was doing:

```bash   
N     
C     
Z     
P  D  B
```

A subtle difference, but very important for the final result. In the end, I updated `operate` to reverse the strings before prepending them to the stack:

```rust
fn operate(&mut self) {
	let operation = self.operations.pop_front().unwrap();
	let split: String = self.stacks[operation.source - 1]
		.take(operation.quantity)
		.unwrap()
		.chars()
		.rev()
		.collect();
	self.stacks[operation.target - 1].insert_str(0, &split);
}
```

## Part two

Interestingly... Part two's problem was the same, but I was to retain the original insertion order of the stack. Well, well, well, look how the tables have turned. My earlier cockup has become my superpower.

All I had to do was revert my little change from earlier, returning `operate` back to it's original state, and that was it!

Day 5 was a toughie for me, but mostly because I tried to be clever but really wasn't. Next time, I'll use an actual Stack - even if I need to write the operations for it myself.
