split_from and diag use iterators not vectors

This commit is contained in:
Simon Gardling 2025-02-10 15:38:16 -05:00
parent bd5cc2ea52
commit 13f5b29dac
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D
5 changed files with 38 additions and 26 deletions

1
Cargo.lock generated
View File

@ -152,6 +152,7 @@ dependencies = [
name = "othello" name = "othello"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"either",
"num", "num",
"rand", "rand",
"rayon", "rayon",

View File

@ -8,6 +8,7 @@ edition = "2021"
debug = true debug = true
[dependencies] [dependencies]
either = "1.13.0"
num = "0.4" num = "0.4"
rand = "0.9" rand = "0.9"
rayon = "1.10" rayon = "1.10"

View File

@ -151,7 +151,7 @@ impl Board {
chains.extend(j_chain.map(|range| range.into_iter().map(|j| (i, j)).collect())); chains.extend(j_chain.map(|range| range.into_iter().map(|j| (i, j)).collect()));
// handle diagonals // handle diagonals
chains.extend(diag(i, j, 0, 0, BOARD_SIZE - 1, BOARD_SIZE - 1)); chains.extend(diag(i, j, 0, 0, BOARD_SIZE - 1, BOARD_SIZE - 1).map(Iterator::collect));
let mut fill: Vec<(usize, usize)> = Vec::with_capacity(chains.iter().map(Vec::len).sum()); let mut fill: Vec<(usize, usize)> = Vec::with_capacity(chains.iter().map(Vec::len).sum());

View File

@ -248,7 +248,7 @@ pub struct ComplexAgent {
impl ComplexAgent { impl ComplexAgent {
pub fn new(color: Piece) -> Self { pub fn new(color: Piece) -> Self {
const MAX_DEPTH: usize = 6; const MAX_DEPTH: usize = 7;
Self { Self {
color, color,
future_moves: FutureMoves::new(color, MAX_DEPTH), future_moves: FutureMoves::new(color, MAX_DEPTH),

View File

@ -1,31 +1,38 @@
use either::Either;
use std::{iter::Rev, ops::RangeInclusive}; use std::{iter::Rev, ops::RangeInclusive};
pub fn split_from<T>(min: T, max: T, x: T) -> [Vec<T>; 2] pub fn split_from<T>(min: T, max: T, x: T) -> [impl Iterator<Item = T> + Clone; 2]
where where
T: num::Integer + Copy, T: num::Integer + Copy,
RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator, RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator,
Rev<RangeInclusive<T>>: Iterator<Item = T>, Rev<RangeInclusive<T>>: Iterator<Item = T>,
{ {
// check that x is in range let in_range = (x >= min) && (x <= max);
if min > x || x > max {
return [const { Vec::new() }; 2];
}
// RangeInclusive (1..=0), has 0 elements
let base = Either::Right(T::one()..=T::zero());
[ [
if x > min + T::one() { if in_range && x > min + T::one() {
(min..=(x - T::one())).rev().collect() Either::Left((min..=(x - T::one())).rev())
} else { } else {
Vec::new() base.clone()
}, },
if x + T::one() < max { if in_range && x + T::one() < max {
((x + T::one())..=max).collect() Either::Right((x + T::one())..=max)
} else { } else {
Vec::new() base
}, },
] ]
} }
pub fn diag<T>(i: T, j: T, min_i: T, min_j: T, max_i: T, max_j: T) -> [Vec<(T, T)>; 4] pub fn diag<T>(
i: T,
j: T,
min_i: T,
min_j: T,
max_i: T,
max_j: T,
) -> [impl Iterator<Item = (T, T)>; 4]
where where
T: num::Integer + Copy, T: num::Integer + Copy,
RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator, RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator,
@ -34,13 +41,7 @@ where
let i_chains = split_from(min_i, max_i, i); let i_chains = split_from(min_i, max_i, i);
let j_chains = split_from(min_j, max_j, j); let j_chains = split_from(min_j, max_j, j);
[(0, 0), (1, 1), (1, 0), (0, 1)].map(|(a, b)| { [(0, 0), (1, 1), (1, 0), (0, 1)].map(|(a, b)| i_chains[a].clone().zip(j_chains[b].clone()))
i_chains[a]
.iter()
.cloned()
.zip(j_chains[b].clone())
.collect()
})
} }
#[cfg(test)] #[cfg(test)]
@ -49,15 +50,24 @@ mod test {
#[test] #[test]
fn split_test() { fn split_test() {
assert_eq!(split_from(0, 6, 2), [vec![1, 0], vec![3, 4, 5, 6]]); assert_eq!(
split_from(0, 6, 2).map(Iterator::collect::<Vec<usize>>),
[vec![1, 0], vec![3, 4, 5, 6]]
);
assert_eq!(split_from(0, 6, 0), [vec![], vec![1, 2, 3, 4, 5, 6]]); assert_eq!(
split_from(0, 6, 0).map(Iterator::collect::<Vec<usize>>),
[vec![], vec![1, 2, 3, 4, 5, 6]]
);
assert_eq!(split_from(0, 6, 6), [vec![5, 4, 3, 2, 1, 0], vec![]]); assert_eq!(
split_from(0, 6, 6).map(Iterator::collect::<Vec<usize>>),
[vec![5, 4, 3, 2, 1, 0], vec![]]
);
// test out-of-bounds and also generics // test out-of-bounds and also generics
assert_eq!( assert_eq!(
split_from::<i16>(-1i16, 4i16, 10i16), split_from::<i16>(-1i16, 4i16, 10i16).map(Iterator::collect::<Vec<i16>>),
[const { Vec::new() }; 2] [const { Vec::new() }; 2]
); );
} }
@ -65,7 +75,7 @@ mod test {
#[test] #[test]
fn diag_test() { fn diag_test() {
assert_eq!( assert_eq!(
diag(2, 3, 0, 0, 7, 7), diag(2, 3, 0, 0, 7, 7).map(Iterator::collect::<Vec<(usize, usize)>>),
[ [
vec![(1, 2), (0, 1)], vec![(1, 2), (0, 1)],
vec![(3, 4), (4, 5), (5, 6), (6, 7)], vec![(3, 4), (4, 5), (5, 6), (6, 7)],