[TWEAK] Performance improvement by dropping the need for a hashmap and using the stack indices directly

This commit is contained in:
2022-12-05 20:43:19 +01:00
parent 324d5ab02b
commit a6a2cd3093
3 changed files with 24 additions and 10 deletions

7
Cargo.lock generated
View File

@@ -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"

View File

@@ -10,3 +10,4 @@ edition = "2021"
regex = "1"
lazy_static = "1.4.0"
rustc-hash = "1.1.0"
nohash-hasher = "0.2.0"

View File

@@ -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<Vec<char>>,
stack_ids_rev: FxHashMap<u8, usize>,
instructions: Vec<StackInstruction>
}
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<char> = 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<u8> = stack_id_strs.iter().map(|s| s.parse::<u8>().unwrap()).collect();
let mut stacks: Vec<Vec<char>> = vec![Vec::with_capacity(stack_lines.len() - 1); stack_id_idxs.len()];
let mut stacks: Vec<Vec<char>> = 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()
};
}