1use std::rc::Rc;
2
3use crate::Set;
4use rust_fp_categories::Empty;
5
6#[derive(Debug, Clone, PartialEq, PartialOrd)]
7pub enum Tree<A> {
8 Empty,
9 Cons(Rc<Self>, A, Rc<Self>),
10}
11
12impl<A> Tree<A> {
13 pub fn single(value: A) -> Self {
14 Self::cons(Tree::Empty, value, Tree::Empty)
15 }
16
17 pub fn cons(left: Self, value: A, right: Self) -> Self {
18 Tree::Cons(Rc::new(left), value, Rc::new(right))
19 }
20}
21
22impl<A> Empty for Tree<A> {
23 fn empty() -> Self {
24 Tree::Empty
25 }
26
27 fn is_empty(&self) -> bool {
28 match self {
29 &Tree::Empty => true,
30 &Tree::Cons(..) => false,
31 }
32 }
33}
34
35impl<A: Clone + PartialEq + PartialOrd> Set<A> for Tree<A> {
36 fn insert(self, value: A) -> Self {
37 fn insert_to<A: Clone + PartialEq + PartialOrd>(x: A, s: &Tree<A>) -> Option<Tree<A>> {
38 match s {
39 &Tree::Empty => Some(Tree::cons(Tree::Empty, x, Tree::Empty)),
40 &Tree::Cons(ref a, ref y, ref b) => {
41 if x < *y {
42 insert_to(x, a)
43 .map(|a: Tree<A>| Tree::Cons(Rc::new(a), y.clone(), b.clone()))
44 } else if *y < x {
45 insert_to(x, b)
46 .map(|b: Tree<A>| Tree::Cons(a.clone(), y.clone(), Rc::new(b)))
47 } else {
48 None
49 }
50 }
51 }
52 }
53 insert_to(value, &self).unwrap_or(self)
54 }
55
56 fn member(&self, value: A) -> bool {
57 fn member1<A: Clone + PartialEq + PartialOrd>(x: A, last: Option<A>, ss: &Tree<A>) -> bool {
58 match ss {
59 &Tree::Empty => last.iter().any(|y| x == *y),
60 &Tree::Cons(ref a, ref y, ref b) => {
61 if x < *y {
62 member1(x, last, a.as_ref())
63 } else {
64 member1(x, Some(y.clone()), b.as_ref())
65 }
66 }
67 }
68 }
69 member1(value, None, self)
70 }
71
72 fn size(&self) -> usize {
73 match self {
74 &Tree::Empty => 0,
75 &Tree::Cons(ref a, _, ref b) => 1 + a.size() + b.size(),
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use crate::{Set, StackError, Tree};
83
84 #[test]
85 fn test_size() -> Result<(), StackError> {
86 assert_eq!(Tree::single(1).size(), 1);
87 Ok(())
88 }
89}