From a6a2cd30933710fd3c30dbd5fcbb666ac5a07607 Mon Sep 17 00:00:00 2001 From: Bas Dado Date: Mon, 5 Dec 2022 20:43:19 +0100 Subject: [PATCH] [TWEAK] Performance improvement by dropping the need for a hashmap and using the stack indices directly --- Cargo.lock | 7 +++++++ Cargo.toml | 3 ++- src/day5.rs | 24 +++++++++++++++--------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 01d5af2..bdbf4e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ name = "advent-of-code-2022-rust" version = "0.1.0" dependencies = [ "lazy_static", + "nohash-hasher", "regex", "rustc-hash", ] @@ -32,6 +33,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "regex" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index 1c83c59..d9d4cd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,5 @@ edition = "2021" [dependencies] regex = "1" lazy_static = "1.4.0" -rustc-hash = "1.1.0" \ No newline at end of file +rustc-hash = "1.1.0" +nohash-hasher = "0.2.0" \ No newline at end of file diff --git a/src/day5.rs b/src/day5.rs index 848adaa..e3789dd 100644 --- a/src/day5.rs +++ b/src/day5.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; +use nohash_hasher::{BuildNoHashHasher, NoHashHasher}; use rustc_hash::FxHashMap; use crate::day_solver::DaySolver; @@ -25,15 +27,14 @@ impl StackInstruction { #[derive(Debug, Clone)] pub struct Day5 { stacks: Vec>, - stack_ids_rev: FxHashMap, instructions: Vec } impl Day5 { fn execute_instruction_part1(&mut self, instr: &StackInstruction) { for _ in 0..instr.amount { - let moving_crate = self.stacks[self.stack_ids_rev[&instr.from]].pop().unwrap(); - self.stacks[self.stack_ids_rev[&instr.to]].push(moving_crate); + let moving_crate = self.stacks[instr.from as usize].pop().unwrap(); + self.stacks[instr.to as usize].push(moving_crate); } } @@ -48,11 +49,12 @@ impl Day5 { fn execute_instruction_part2(&mut self, instr: &StackInstruction) { - let from_stack = &self.stacks[self.stack_ids_rev[&instr.from]]; + // TODO prevent copying into a Vec here (we don't need a stack allocation...) + let from_stack = &self.stacks[instr.from as usize]; let from_stack_remaining = from_stack.len() - instr.amount as usize; let to_move: Vec = from_stack.iter().skip(from_stack_remaining).cloned().collect(); - self.stacks[self.stack_ids_rev[&instr.to]].extend(to_move); - self.stacks[self.stack_ids_rev[&instr.from]].truncate(from_stack_remaining); + self.stacks[instr.to as usize].extend(to_move); + self.stacks[instr.from as usize].truncate(from_stack_remaining); } fn execute_instructions_part2(&self) -> Day5 { @@ -87,15 +89,19 @@ impl Day5 { } let stack_ids: Vec = stack_id_strs.iter().map(|s| s.parse::().unwrap()).collect(); - let mut stacks: Vec> = vec![Vec::with_capacity(stack_lines.len() - 1); stack_id_idxs.len()]; + let mut stacks: Vec> = vec![Vec::with_capacity(stack_lines.len() - 1); + stack_ids.iter().max().unwrap().to_owned() as usize + 1]; for stack_line in stack_lines.iter().rev().skip(1) { stack_id_idxs.iter().enumerate() - .for_each(|(i, stack_id_idx)| if let Some(c) = stack_line.chars().nth(stack_id_idx.to_owned()).filter(|c| !c.is_whitespace()) { stacks[i].push(c) }) + .for_each(|(i, stack_id_idx)| if let Some(c) = stack_line.chars() + .nth(stack_id_idx.to_owned()) + .filter(|c| !c.is_whitespace()) { + stacks[stack_ids[i] as usize].push(c) + }) } return Day5 { stacks, - stack_ids_rev: FxHashMap::from_iter(stack_ids.iter().enumerate().map(|(k, v)| (v.clone(), k))), instructions: instruction_lines.iter().map(|s| StackInstruction::parse(s)).collect() }; }