From ca423942c862b888576a9620751c7e6b19b57e48 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Tue, 11 Feb 2025 16:25:01 -0500 Subject: [PATCH] remove HashMap --- src/board.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/board.rs b/src/board.rs index bdd0ee7..37253bc 100644 --- a/src/board.rs +++ b/src/board.rs @@ -4,7 +4,8 @@ use crate::{ }; use arrayvec::ArrayVec; use lazy_static::lazy_static; -use std::{cmp::Ordering, collections::HashMap, fmt}; +use std::{cmp::Ordering, fmt}; + pub const BOARD_SIZE: usize = 8; /// A chain of positions across the board @@ -13,10 +14,26 @@ type Chain = ArrayVec<(usize, usize), BOARD_SIZE>; /// A collection of chains (up vert, down vert, left horiz, right horiz, diagonals....) type ChainCollection = ArrayVec; +/// Map of all points on the board against some type T +/// Used to index like so: example[i][j] +/// with each coordinate +type PosMap = ArrayVec, BOARD_SIZE>; + lazy_static! { /// Precompute all possible chains for each position on the board - pub static ref ADJ_LOOKUP: HashMap<(usize, usize), ChainCollection> = { - let mut output = HashMap::new(); + pub static ref ADJ_LOOKUP: PosMap = { + let mut output = ArrayVec::new(); + + // populate arrayvec as we index it [i][j] + for _ in 0..BOARD_SIZE { + let mut a = ArrayVec::new(); + // [j] + for _ in 0..BOARD_SIZE { + a.push(ArrayVec::new()); + } + output.push(a); + } + for (i, j) in Board::all_positions() { let (i_chain, j_chain) = ( split_from(0..=BOARD_SIZE - 1, i), @@ -40,7 +57,8 @@ lazy_static! { // handle diagonals chains.extend(diag_raw(i_chain, j_chain).map(Iterator::collect)); - output.insert((i, j), chains); + + output[i][j] = chains; } output @@ -181,12 +199,10 @@ impl Board { // NOTE! got it down to 24.86% (61.1% decrease) with allocator optimizations // IDEAS: early-exit from each chain so we don't have to call `diag` (which allocs a lot and uses a lot of cycles) fn propegate_from_dry(&self, i: usize, j: usize, starting_color: Piece) -> Vec<(usize, usize)> { - let chains = ADJ_LOOKUP.get(&(i, j)).unwrap(); - // Longest chain is (BOARD_SIZE - 2) as there needs to be the two pieces containing it - let mut fill: Vec<(usize, usize)> = Vec::with_capacity((BOARD_SIZE - 2) * chains.len()); + let mut fill: Vec<(usize, usize)> = Vec::with_capacity((BOARD_SIZE - 2) * 8); - for chain in chains { + for chain in &ADJ_LOOKUP[i][j] { for (chain_length, &(new_i, new_j)) in chain.iter().enumerate() { let Some(piece) = self.get(new_i, new_j) else { // chain interupted by blank space