use rand::Rng;
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
enum TreeGenMode {
Perfect(usize),
Full,
FullRanged(usize),
}
#[derive(PartialEq, Eq, Debug)]
pub struct TreeGen<'a, R>
where R: 'a + Rng
{
mode: TreeGenMode,
rng: &'a mut R,
min_depth: usize,
max_depth: usize,
}
impl<'a, R> TreeGen<'a, R>
where R: 'a + Rng
{
pub fn perfect(rng: &mut R, min_depth: usize, max_depth: usize) -> TreeGen<R> {
let chosen_depth = rng.gen_range(min_depth, max_depth + 1);
TreeGen {
rng: rng,
mode: TreeGenMode::Perfect(chosen_depth),
min_depth: min_depth,
max_depth: max_depth,
}
}
pub fn full(rng: &mut R, min_depth: usize, max_depth: usize) -> TreeGen<R> {
TreeGen {
rng: rng,
mode: TreeGenMode::Full,
min_depth: min_depth,
max_depth: max_depth,
}
}
pub fn full_ranged(rng: &mut R, min_depth: usize, max_depth: usize) -> TreeGen<R> {
let chosen_depth = rng.gen_range(min_depth, max_depth + 1);
TreeGen {
rng: rng,
mode: TreeGenMode::FullRanged(chosen_depth),
min_depth: min_depth,
max_depth: max_depth,
}
}
pub fn half_and_half(rng: &mut R, min_depth: usize, max_depth: usize) -> TreeGen<R> {
if rng.gen() {
Self::perfect(rng, min_depth, max_depth)
} else {
Self::full_ranged(rng, min_depth, max_depth)
}
}
pub fn have_reached_a_leaf(&mut self, current_depth: usize) -> bool {
match self.mode {
TreeGenMode::Perfect(chosen_depth) => current_depth == chosen_depth,
TreeGenMode::Full => {
let depth_interval = self.max_depth - self.min_depth;
current_depth == self.max_depth ||
(current_depth >= self.min_depth) && self.gen_weighted_bool(depth_interval as u32)
}
TreeGenMode::FullRanged(chosen_depth) => {
let depth_interval = chosen_depth - self.min_depth;
current_depth == chosen_depth ||
(current_depth >= self.min_depth) && self.gen_weighted_bool(depth_interval as u32)
}
}
}
}
impl<'a, R> Rng for TreeGen<'a, R>
where R: 'a + Rng
{
fn next_u32(&mut self) -> u32 {
self.rng.next_u32()
}
fn next_u64(&mut self) -> u64 {
self.rng.next_u64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.rng.fill_bytes(dest)
}
}