Advent of Rust // Day 5
Today’s puzzle was another one where the solutions for the two parts differed only in a minuscule detail.
fn part_one(input: &str) -> String {
return process_stacks_and_return_top_items(input, crane_mover_9000);
}
fn part_two(input: &str) -> String {
return process_stacks_and_return_top_items(input, crane_mover_9001);
}
fn process_stacks_and_return_top_items(input: &str, processor: fn(stacks: &mut Stacks, instruction: Instruction)) -> String {
let (stack_input, instruction_input) = input.split_once("\n\n").unwrap();
let mut stacks = stacks_from_input(stack_input);
instruction_input.lines()
.map(Instruction::from_string)
.for_each(|ins| processor(&mut stacks, ins));
return stacks.keys()
.sorted()
.map(|k| stacks.get(k).unwrap().last().unwrap())
.join("");
}
For part one, it was just popping and pushing items from one stack to another:
fn crane_mover_9000(stacks: &mut Stacks, instruction: Instruction) {
for _i in 0..instruction.count {
let item = stacks.get_mut(&instruction.from).unwrap().pop().unwrap();
stacks.get_mut(&instruction.to).unwrap().push(item);
}
}
For part two, it was moving multiple stacks at once:
fn crane_mover_9001(stacks: &mut Stacks, instruction: Instruction) {
let from_stack = stacks.get_mut(&instruction.from).unwrap();
let from_size = from_stack.len() - instruction.count as usize;
let items: Vec<String> = from_stack.drain(from_size..).collect();
stacks.get_mut(&instruction.to).unwrap().extend_from_slice(&items);
}
Dealing with pointers and ownership is still one of the biggest issues I have with Rust. Firstly, because I haven’t had to deal with pointers in probably two decades and I have gotten used to the convenience of not giving a fuck. Secondly, I still haven’t read the fucking manual. Anyway. I wanted to check out parser combinators in Rust today, but I spent too much time fiddling with mutable pointers, so I took the path of least resistance and went back to using regexes:
struct Instruction {
count: u32,
from: u32,
to: u32,
}
impl Instruction {
fn from_string(input: &str) -> Instruction {
let re = Regex::new(r"^move (\d+) from (\d+) to (\d+)$").unwrap();
let captures = re.captures(input).unwrap();
return Instruction {
count: captures[1].parse().unwrap(),
from: captures[2].parse().unwrap(),
to: captures[3].parse().unwrap(),
};
}
}
type Stacks = HashMap<u32, Vec<String>>;
fn stacks_from_input(input: &str) -> Stacks {
let re = Regex::new(r"( {3}|\[.])").unwrap();
let mut stacks: Stacks = HashMap::new();
for line in input.lines().rev().dropping(1) {
for (index, capture) in re.captures_iter(line).enumerate() {
if capture[1].trim() == "" {
continue;
}
let key = (index + 1) as u32;
if !stacks.contains_key(&key) {
stacks.insert(key, Vec::new());
}
let string = String::from(&capture[1][1..=1]);
stacks.get_mut(&key).unwrap().push(string);
}
}
return stacks;
}
The full source and solutions for the others puzzles of Advent of Code can be found in my GitHub repository.
Comments
You can leave a comment by replying to this post on Mastodon.