It's a tree

This commit is contained in:
Aode (Lion) 2022-02-10 14:44:58 -06:00
commit 629075f94d
4 changed files with 155 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

8
Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "a-tree"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

63
examples/generate.rs Normal file
View file

@ -0,0 +1,63 @@
use a_tree::Tree;
#[derive(Debug, PartialEq, Eq, Hash)]
enum Direction {
Up,
Down,
Left,
Right,
}
#[derive(Debug, Default)]
struct Coordinates {
x: usize,
y: usize,
}
const ALL_DIRECTIONS: [Direction; 4] = [
Direction::Up,
Direction::Down,
Direction::Left,
Direction::Right,
];
fn next_level(value: &Coordinates) -> Vec<(Direction, Coordinates)> {
ALL_DIRECTIONS
.into_iter()
.filter_map(|direction| {
let new_coords = match direction {
Direction::Up => Coordinates {
x: value.x,
y: value.y + 1,
},
Direction::Right => Coordinates {
x: value.x + 1,
y: value.y,
},
Direction::Down if value.y > 0 => Coordinates {
x: value.x,
y: value.y - 1,
},
Direction::Left if value.x > 0 => Coordinates {
x: value.x - 1,
y: value.y,
},
_ => return None,
};
Some((direction, new_coords))
})
.collect()
}
fn main() {
let mut tree = Tree::generations(Coordinates::default(), 3, next_level);
println!("{:#?}", tree);
println!("{:?}", tree.leaves());
tree.retain(|item| item.x > 0 && item.y > 0);
println!("{:#?}", tree);
println!("{:?}", tree.leaves());
}

82
src/lib.rs Normal file
View file

@ -0,0 +1,82 @@
use std::collections::HashMap;
use std::hash::Hash;
#[derive(Debug)]
pub struct Tree<K, T> {
value: T,
children: HashMap<K, Tree<K, T>>,
}
impl<K, T> Tree<K, T>
where
K: Eq + Hash,
{
pub fn new(item: T) -> Self {
Tree {
value: item,
children: HashMap::new(),
}
}
pub fn generations<F>(start: T, depth: usize, callback: F) -> Self
where
F: Fn(&T) -> Vec<(K, T)> + Copy,
{
let mut children = HashMap::new();
if depth != 0 {
for (key, value) in (callback)(&start) {
let child = Self::generations(value, depth - 1, callback);
children.insert(key, child);
}
}
Tree {
value: start,
children,
}
}
pub fn leaves(&self) -> Vec<(Vec<&K>, &T)> {
self.do_leaves(vec![])
}
fn do_leaves<'a>(&'a self, path: Vec<&'a K>) -> Vec<(Vec<&'a K>, &'a T)> {
if self.children.is_empty() {
vec![(path, &self.value)]
} else {
self.children
.iter()
.flat_map(|(key, child)| {
let mut path = path.clone();
path.push(key);
child.do_leaves(path)
})
.collect()
}
}
pub fn retain<C>(&mut self, callback: C)
where
C: Fn(&T) -> bool + Copy,
{
self.children.retain(|_key, child| {
child.retain(callback);
if child.children.is_empty() {
(callback)(&child.value)
} else {
true
}
});
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}