#![allow(dead_code, unused)]
use std::fmt::Debug;
use std::collections::hash_map::Entry;
use std::fmt::{LowerExp, Write};
use std::hash::Hash;
use std::collections::{HashMap, HashSet};
use std::cmp::Ord;
use std::println;
#[derive(Debug, PartialEq)]
pub enum TordError {
IncorrectOrdering,
RelationalCycle
}
impl std::fmt::Display for TordError{
fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
TordError::IncorrectOrdering => w.write_str("Incorrect ordering"),
TordError::RelationalCycle => w.write_str("Relational cycle detected")
}
}
}
#[derive(Debug)]
pub struct Tord<T: Hash + PartialEq + Eq + PartialOrd + Clone + Debug> {
relations: HashMap<T, HashSet<T>>,
}
impl<T: Hash + PartialEq + Eq + PartialOrd + Clone + Debug> Tord<T> {
pub fn new() -> Self {
Self {
relations: HashMap::new()
}
}
pub fn insert(&mut self, lower: T, higher: T) -> Result<(), TordError> {
if lower == higher {
return Ok(());
}
let res = match self.relations.get(&higher) {
Some(e) => e.contains(&lower),
None => false,
};
if res {
return Ok(());
}
let res = match self.relations.get(&lower) {
Some(e) => e.contains(&higher),
None => false,
};
if res {
return Err(TordError::IncorrectOrdering);
}
{
match self.relations.entry(higher.clone()) {
Entry::Occupied(mut v) => {
v.get_mut().insert(lower.clone());
},
Entry::Vacant(e) => {
let mut hs = HashSet::new();
hs.insert(lower.clone());
e.insert(hs);
}
}
}
{
if let Some(vals) = self.relations.get(&lower) {
let c = vals.clone();
let hset = self.relations.get_mut(&higher).unwrap();
for val in c.iter() {
if *val == higher {
return Err(TordError::RelationalCycle);
}
hset.insert(val.clone());
}
}
}
{
let mut lesser_vec = vec![];
self.lessers(&mut lesser_vec, lower.clone());
if let Some(vals) = self.relations.get_mut(&higher) {
for val in lesser_vec.iter() {
if *val == higher {
return Err(TordError::RelationalCycle);
}
vals.insert(val.clone());
}
}
for (k, v) in self.relations.iter_mut() {
if v.contains(&higher) {
for val in lesser_vec.iter() {
v.insert(val.clone());
}
}
}
}
return Ok(());
}
pub fn check_relation(&self, lower: T, higher: T) -> Option<bool> {
if lower == higher {
return Some(true);
}
match self.relations.get(&higher) {
Some(v) => return Some(v.contains(&lower)),
None => return None,
}
}
pub fn size(&self) -> usize {
self.relations.len()
}
fn lessers(&mut self, result: &mut Vec<T>, lower: T) {
if result.contains(&lower) {
return;
}
match self.relations.get(&lower.clone()) {
None => return,
Some(lesser_vals) => {
let lesser_vals = lesser_vals.clone();
for val in lesser_vals {
if !result.contains(&val) {
result.push(val.clone());
self.lessers(result, val);
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn insert() {
let mut tord = Tord::new();
tord.insert(5, 6);
assert_eq!(tord.size(), 1);
tord.insert(6, 10);
assert_eq!(tord.size(), 2);
tord.insert(10, 1);
assert_eq!(tord.size(), 3);
}
#[test]
fn check_relation() {
let mut tord = Tord::new();
tord.insert(5, 6);
tord.insert(6, 10);
tord.insert(10, 1);
tord.insert(0, 0);
assert_eq!(tord.check_relation(0, 0), Some(true));
assert_eq!(tord.check_relation(5, 6), Some(true));
assert_eq!(tord.check_relation(6, 5), None);
}
#[test]
fn relational_cycles() {
let mut tord = Tord::new();
println!("1. {:?}", tord);
assert_eq!(tord.insert(2, 3).is_ok(), true);
println!("2. {:?}", tord);
assert_eq!(tord.insert(0, 1).is_ok(), true);
println!("3. {:?}", tord);
assert_eq!(tord.insert(1, 2).is_ok(), true);
println!("4. {:?}", tord);
assert_eq!(tord.insert(3, 0).unwrap_err(), TordError::IncorrectOrdering);
println!("5. {:?}", tord);
}
}