1#![macro_use]
2use std::cmp::Ordering;
3use std::slice::Iter;
4
5#[derive(PartialEq, Eq, Clone, Debug)]
6pub enum List<T> {
7 Cons(T, Box<List<T>>),
8 Nil,
9}
10
11pub use List::{Cons, Nil};
12
13#[macro_export]
14macro_rules! ls[
15 [] => (List::Nil);
16 [$x:expr] => (List::Cons($x, Box::new(List::Nil)));
17 [$x:expr, $($xs:expr),+] => (List::Cons($x, Box::new(ls![$($xs),+])));
18];
19
20impl<T: Clone> From<Iter<'_, T>> for List<T> {
21 fn from(iter: Iter<'_, T>) -> Self {
22 let mut list = ls![];
23 for x in iter {
24 list = list.append(x.clone());
25 }
26
27 list
28 }
29}
30
31impl<T: Clone> From<&[T]> for List<T> {
32 fn from(array: &[T]) -> Self {
33 List::from(array.iter()).map(|x| x)
34 }
35}
36
37impl<T: Eq> List<T> {
38 pub fn new<A>() -> Self {
39 Nil
40 }
41
42 pub fn is_empty(&self) -> bool {
43 self.eq(&Nil)
44 }
45 pub fn null(&self) -> bool {
46 self.is_empty()
47 }
48
49 pub fn len(&self) -> u32 {
50 fn aux<T>(xs: &List<T>, size: u32) -> u32 {
51 match *xs {
52 Nil => size,
53 Cons(_, ref tail) => aux(tail, size + 1),
54 }
55 };
56
57 aux(self, 0)
58 }
59}
60
61impl<T: Clone> List<T> {
62 pub fn prepend(self, x: T) -> Self {
63 Cons(x, Box::new(self))
64 }
65
66 pub fn append(self, item: T) -> Self {
67 match self {
68 Nil => ls![item],
69 Cons(head, tail) => tail.append(item).prepend(head),
70 }
71 }
72
73 pub fn concat(self, other: Self) -> Self {
74 match self {
75 Nil => other,
76 Cons(head, tail) => tail.concat(other).prepend(head),
77 }
78 }
79
80 pub fn get(&self, index: u32) -> Option<&T> {
81 match self {
82 Nil => None,
83 Cons(head, _) if index == 0 => Some(head),
84 Cons(_, ref tail) => tail.get(index - 1),
85 }
86 }
87
88 pub fn head(&self) -> Option<&T> {
89 self.get(0)
90 }
91
92 pub fn tail(&self) -> Self {
93 match self {
94 Nil => (*self).clone(),
95 Cons(_, ref tail) => unsafe {
96 let t = (*tail).clone();
97 (*Box::into_raw(t)).clone()
98 },
99 }
100 }
101
102 pub fn foldl<R>(self, func: impl Fn(R, T) -> R + Copy, init: R) -> R {
103 match self {
104 Nil => init,
105 Cons(x, tail) => tail.foldl(func, func(init, x)),
106 }
107 }
108
109 pub fn foldr<R>(self, func: impl Fn(T, R) -> R + Copy, init: R) -> R {
110 match self {
111 Nil => init,
112 Cons(x, tail) => func(x, tail.foldr(func, init)),
113 }
114 }
115
116 pub fn reverse(self) -> List<T> {
117 fn aux<T>(xs: List<T>, ys: List<T>) -> List<T> {
118 match ys {
119 Nil => xs,
120 Cons(y, tail) => aux(Cons(y, Box::new(xs)), *tail),
121 }
122 };
123 aux(Nil, self)
124 }
125
126 pub fn map<R>(self, func: impl Fn(T) -> R + Copy) -> List<R> {
127 match self {
128 Nil => Nil,
129 Cons(x, tail) => Cons(func(x), Box::new(tail.map(func))),
130 }
131 }
132
133 pub fn filter(self, func: impl Fn(&T) -> bool + Copy) -> Self {
134 match self {
135 Nil => self,
136 Cons(x, tail) => {
137 if func(&x) {
138 Cons(x, Box::new(tail.filter(func)))
139 } else {
140 tail.filter(func)
141 }
142 }
143 }
144 }
145
146 fn chop(self, ign: u32) -> Self {
147 if ign == 0 {
148 self
149 } else {
150 match self {
151 Cons(_, tx) => tx.chop(ign - 1),
152 _ => panic!("TODO: meaningful error message"),
153 }
154 }
155 }
156
157 pub fn qsort_by(self, cmpfn: impl Fn(&T, &T) -> Ordering + Copy) -> Self {
158 match self {
159 Nil => self,
160 Cons(head, tail) => {
161 let smaller = tail
162 .clone()
163 .filter(|x| cmpfn(x, &head) == Ordering::Less)
164 .qsort_by(cmpfn);
165 let bigger = tail
166 .filter(|x| cmpfn(x, &head) != Ordering::Less)
167 .qsort_by(cmpfn);
168
169 smaller.append(head).concat(bigger)
170 }
171 }
172 }
173}
174
175impl<T> List<T>
176where
177 T: Copy,
178 T: Ord,
179{
180 pub fn qsort(self) -> Self {
181 self.qsort_by(|x, y| x.cmp(y))
182 }
183
184 pub fn sort(&self) -> Self {
185 self.sort_by(|x, y| x.cmp(y))
186 }
187
188 pub fn sort_by(&self, cmpfn: impl Fn(&T, &T) -> Ordering + Copy) -> Self {
189 let ln = self.len();
190 if ln <= 1 {
191 return self.clone();
192 }
193 let l1 = self.clone().chop(ln / 2);
194 let l2 = self.clone().reverse().chop(ln - (ln / 2));
195 l1.sort_by(cmpfn).merge(cmpfn, &l2.sort_by(cmpfn))
196 }
197
198 pub fn partition(self, p: fn(T) -> bool) -> (Self, Self) {
199 fn aux<T: Clone + Copy + Eq + Ord>(
200 yes: List<T>,
201 no: List<T>,
202 p: fn(T) -> bool,
203 xs: List<T>,
204 ) -> (List<T>, List<T>) {
205 match xs {
206 Nil => (yes, no),
207 Cons(x, tx) => {
208 if p(x) {
209 aux(yes.append(x), no, p, *tx)
213 } else {
214 aux(yes, no.append(x), p, *tx)
216 }
217 }
218 }
219 };
220 aux(Nil, Nil, p, self)
221 }
222
223 pub fn merge(&self, cmpfn: impl Fn(&T, &T) -> Ordering + Copy, ys: &List<T>) -> Self {
224 match (self, ys) {
225 (Nil, l) => l.clone(),
226 (l, Nil) => l.clone(),
227 (Cons(x, tx), Cons(y, ty)) => {
228 let cmp = cmpfn(x, y);
229 if cmp == Ordering::Equal || cmp == Ordering::Less {
230 Cons(*x, Box::new(ys.merge(cmpfn, &**tx)))
231 } else {
232 Cons(*y, Box::new(self.merge(cmpfn, &**ty)))
233 }
234 }
235 }
236 }
237}