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"
version = "0.1.0"
dependencies = [
"either",
"num",
"rand",
"rayon",

View File

@ -8,6 +8,7 @@ edition = "2021"
debug = true
[dependencies]
either = "1.13.0"
num = "0.4"
rand = "0.9"
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()));
// 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());

View File

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

View File

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