use num_derive::FromPrimitive;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("node is missing")]
NodeMissing,
#[error("node already exists")]
NodeExists,
#[error("out of range")]
OutOfRange,
#[error("there is no cursor")]
NoCursor,
#[error("tree connection is broken")]
BrokenConnection,
#[error("root node or broken connection")]
BrokenConnectionOrRoot,
#[error("non-root node or broken connection")]
BrokenConnectionOrNotRoot,
}
#[derive(FromPrimitive, Clone, Copy)]
pub enum Side {
Left = 0,
Right = 1,
}
#[derive(Clone)]
struct Node {
val: usize,
symbol: Option<usize>,
up: Option<usize>,
down: [Option<usize>; 2],
}
pub struct Tree {
roots: Vec<Option<usize>>,
curs: Option<usize>,
pool: Vec<Node>,
}
impl Tree {
pub fn create(len: usize, symbols: usize) -> Self {
let roots: Vec<Option<usize>> = vec![None; symbols];
let mut pool: Vec<Node> = Vec::new();
for i in 0..len {
pool.push(Node {
val: i,
symbol: None,
up: None,
down: [None, None],
});
}
Self {
roots,
curs: None,
pool,
}
}
fn chk_cursor(&self) -> Result<usize, Error> {
match self.curs {
None => Err(Error::NoCursor),
Some(curs) => match curs < self.pool.len() {
true => Ok(curs),
false => Err(Error::OutOfRange),
},
}
}
pub fn get_cursor(&self) -> Option<usize> {
self.curs
}
pub fn set_cursor(&mut self, curs: usize) -> Result<(), Error> {
match curs < self.pool.len() {
true => {
self.curs = Some(curs);
Ok(())
}
false => Err(Error::OutOfRange),
}
}
pub fn set_cursor_to_root(&mut self, symbol: usize) -> Result<(), Error> {
match self.roots[symbol] {
None => Err(Error::NodeMissing),
Some(v) => {
self.curs = Some(v);
Ok(())
}
}
}
#[allow(dead_code)]
pub fn up(&mut self) -> Result<usize, Error> {
match self.pool[self.chk_cursor()?].up {
None => Err(Error::NodeMissing),
Some(v) => {
self.curs = Some(v);
Ok(v)
}
}
}
pub fn down(&mut self, side: Side) -> Result<usize, Error> {
match self.pool[self.chk_cursor()?].down[side as usize] {
None => Err(Error::NodeMissing),
Some(v) => {
self.curs = Some(v);
Ok(v)
}
}
}
pub fn terminus(&mut self, side: Side) -> Result<usize, Error> {
let mut term = self.chk_cursor()?;
while let Ok(curs) = self.down(side) {
term = curs;
}
Ok(term)
}
pub fn get_down(&self) -> Result<[Option<usize>; 2], Error> {
let curs = self.chk_cursor()?;
Ok(self.pool[curs].down)
}
pub fn get_parent_and_side(&mut self) -> Result<(usize, Side), Error> {
let curs = self.chk_cursor()?;
if let Some(parent) = self.pool[curs].up {
return match self.pool[parent].down {
[Some(v), _] if v == curs => Ok((parent, Side::Left)),
[_, Some(v)] if v == curs => Ok((parent, Side::Right)),
_ => Err(Error::BrokenConnection),
};
}
Err(Error::BrokenConnectionOrRoot)
}
pub fn get_symbol(&mut self) -> Result<usize, Error> {
let curs = self.chk_cursor()?;
if let Some(symbol) = self.pool[curs].symbol {
return match self.roots[symbol] {
Some(v) if v == curs => Ok(symbol),
_ => Err(Error::BrokenConnection),
};
}
Err(Error::BrokenConnectionOrNotRoot)
}
pub fn is_root(&self) -> Result<bool, Error> {
let curs = self.chk_cursor()?;
Ok(self.pool[curs].up.is_none())
}
#[allow(dead_code)]
pub fn is_leaf(&self) -> Result<bool, Error> {
let curs = self.chk_cursor()?;
Ok(self.pool[curs].down == [None, None])
}
pub fn is_free(&self, curs: usize) -> Result<bool, Error> {
match (self.pool[curs].symbol, self.pool[curs].up, self.pool[curs].down) {
(None, None, _) => Ok(true),
_ => Ok(false),
}
}
pub fn spawn(&mut self, val: usize, side: Side) -> Result<(), Error> {
if val >= self.pool.len() {
return Err(Error::OutOfRange);
}
let curs = self.chk_cursor()?;
if self.pool[curs].down[side as usize].is_some() {
eprintln!(
"spawn: cannot overwrite {}",
self.pool[curs].down[side as usize].unwrap()
);
return Err(Error::NodeExists);
}
self.pool[curs].down[side as usize] = Some(val);
self.pool[val].up = Some(curs);
self.pool[val].down = [None, None];
Ok(())
}
pub fn spawn_root(&mut self, symbol: usize, curs: usize) -> Result<(), Error> {
if symbol >= self.roots.len() || curs >= self.pool.len() {
return Err(Error::OutOfRange);
}
if self.is_free(curs)? {
self.roots[symbol] = Some(curs);
self.pool[curs].symbol = Some(symbol);
self.pool[curs].up = None;
self.pool[curs].down = [None, None];
return Ok(());
}
eprintln!("spawn_root: cannot overwrite {}", curs);
Err(Error::NodeExists)
}
pub fn drop(&mut self) -> Result<(), Error> {
let curs = self.chk_cursor()?;
let maybe_parent = self.pool[curs].up;
let maybe_symbol = self.pool[curs].symbol;
if self.down(Side::Left).is_ok() {
self.drop()?;
self.set_cursor(curs)?;
}
if self.down(Side::Right).is_ok() {
self.drop()?;
self.set_cursor(curs)?;
}
if let Some(parent) = maybe_parent {
let (_, side) = self.get_parent_and_side()?;
self.pool[parent].down[side as usize] = None;
self.curs = Some(parent);
}
if let Some(symbol) = maybe_symbol {
self.roots[symbol] = None;
self.curs = None;
}
self.pool[curs].symbol = None;
self.pool[curs].up = None;
self.pool[curs].down = [None, None];
Ok(())
}
pub fn drop_branch(&mut self, side: Side) -> Result<(), Error> {
if self.down(side).is_ok() {
self.drop()?;
}
Ok(())
}
pub fn cut_upward(&mut self) -> Result<(), Error> {
let (parent, side) = self.get_parent_and_side()?;
self.pool[parent].down[side as usize] = None;
self.pool[self.curs.unwrap()].up = None;
Ok(())
}
#[allow(dead_code)]
pub fn cut_downward(&mut self, side: Side) -> Result<(), Error> {
let curs: usize = self.chk_cursor()?;
if let Some(son) = self.pool[curs].down[side as usize] {
self.pool[curs].down[side as usize] = None;
self.pool[son].up = None;
}
Ok(())
}
pub fn move_node(&mut self, new_parent: usize, side: Side, force: bool) -> Result<(), Error> {
let curs: usize = self.chk_cursor()?;
match (self.pool[new_parent].down[side as usize], force) {
(None, _) => {
if self.pool[curs].up.is_some() {
self.cut_upward()?; }
}
(Some(_), true) => {
if self.pool[curs].up.is_some() {
self.cut_upward()?; }
self.set_cursor(new_parent)?;
self.drop_branch(side)?;
self.set_cursor(curs)?;
}
_ => {
eprintln!(
"move: cannot overwrite {}",
self.pool[new_parent].down[side as usize].unwrap()
);
return Err(Error::NodeExists);
}
}
self.pool[new_parent].down[side as usize] = Some(curs);
self.pool[curs].up = Some(new_parent);
Ok(())
}
pub fn move_node_to_root(&mut self, symbol: usize, force: bool) -> Result<(), Error> {
let curs: usize = self.chk_cursor()?;
match (self.roots[symbol], force) {
(None, _) => {
if self.pool[curs].up.is_some() {
self.cut_upward()?; }
}
(Some(old_root), true) => {
if self.pool[curs].up.is_some() {
self.cut_upward()?; }
self.set_cursor(old_root)?;
self.drop()?;
self.set_cursor(curs)?;
}
(Some(old_root), false) => {
eprintln!("move: cannot overwrite root {}", old_root);
return Err(Error::NodeExists);
}
}
self.roots[symbol] = Some(curs);
self.pool[curs].up = None;
self.pool[curs].symbol = Some(symbol);
Ok(())
}
pub fn change_value(&mut self, new_val: usize, force: bool) -> Result<(), Error> {
let old_val = self.chk_cursor()?;
if new_val == old_val {
return Ok(());
}
match (self.is_free(new_val)?, force) {
(true, _) => {}
(false, false) => {
eprintln!("cannot change node value to {}", new_val);
return Err(Error::NodeExists);
}
(false, true) => {
self.set_cursor(new_val)?;
self.drop()?;
self.set_cursor(old_val)?;
}
}
if let Some(symbol) = self.pool[old_val].symbol {
self.roots[symbol] = Some(new_val);
}
if let Some(parent) = self.pool[old_val].up {
let (_, side) = self.get_parent_and_side()?;
self.pool[parent].down[side as usize] = Some(new_val);
}
if let Some(child) = self.pool[old_val].down[0] {
self.pool[child].up = Some(new_val);
}
if let Some(child) = self.pool[old_val].down[1] {
self.pool[child].up = Some(new_val);
}
self.pool[new_val] = self.pool[old_val].clone();
self.pool[new_val].val = new_val;
self.pool[old_val] = Node {
val: old_val,
symbol: None,
up: None,
down: [None, None],
};
self.curs = Some(new_val);
Ok(())
}
}