1use std::collections::{HashMap, VecDeque};
2use std::hash::Hash;
3
4#[derive(Clone, Debug, Eq, PartialEq)]
5pub struct Tree<T> {
6 pub item: T,
7 pub children: Vec<Tree<T>>,
8}
9
10impl<T> Tree<T> {
11 pub fn new(item: T, children: Vec<Tree<T>>) -> Tree<T> {
12 Tree { item, children }
13 }
14
15 pub fn singleton(item: T) -> Tree<T> {
16 Tree::new(item, vec![])
17 }
18
19 pub fn lookup(&self, path: Path) -> Option<&T> {
21 match path.split_front() {
22 None => Some(&self.item),
23 Some((index, child_path)) => match self.children.get(index) {
24 None => None,
25 Some(child_tree) => child_tree.lookup(child_path),
26 },
27 }
28 }
29
30 pub fn path_map_map<U>(&self, f: &dyn Fn(&T) -> U) -> TreePathMap<U>
36 where
37 U: Eq + Hash,
38 {
39 let mut map = TreePathMap::new();
40 let root_path = Path::new();
41 map.insert(f(&self.item), root_path.clone());
42 map.insert_children_map(&self.children, &root_path, f);
43 map
44 }
45}
46
47impl<T> Tree<T>
48where
49 T: Clone + Eq + Hash,
50{
51 pub fn path_map(&self) -> TreePathMap<T> {
53 self.path_map_map(&|i| i.clone())
54 }
55}
56
57#[derive(Clone, Debug, Default, Eq, PartialEq)]
59pub struct Path(pub VecDeque<usize>);
60
61impl Path {
62 pub fn split_front(mut self) -> Option<(usize, Path)> {
63 let option_front_elem: Option<usize> = self.0.pop_front();
64 match option_front_elem {
65 None => None,
66 Some(i) => Some((i, self)),
67 }
68 }
69
70 pub fn push_back(&mut self, value: usize) {
71 self.0.push_back(value);
72 }
73
74 pub fn new() -> Self {
75 Path(VecDeque::new())
76 }
77}
78
79impl<T> From<T> for Path
80where
81 T: Into<VecDeque<usize>>,
82{
83 fn from(other: T) -> Path {
84 Path(other.into())
85 }
86}
87
88#[derive(Clone, Debug, Default, Eq, PartialEq)]
91pub struct TreePathMap<U>(HashMap<U, Vec<Path>>)
92where
93 U: Eq + Hash;
94
95impl<U> TreePathMap<U>
96where
97 U: Eq + Hash,
98{
99 pub fn new() -> TreePathMap<U> {
100 TreePathMap(HashMap::new())
101 }
102
103 pub fn insert(&mut self, k: U, path: Path) {
105 self.0
106 .entry(k)
107 .and_modify(|paths| paths.push(path.clone()))
108 .or_insert_with(|| vec![path]);
109 }
110
111 pub fn lookup_first(&self, k: &U) -> Option<&Path> {
113 let option_paths: Option<&Vec<Path>> = self.0.get(k);
114 option_paths.and_then(|vec: &Vec<Path>| vec.first())
115 }
116}
117
118impl<U> TreePathMap<U>
119where
120 U: Eq + Hash,
121{
122 fn insert_children_map<T>(
126 &mut self,
127 children: &[Tree<T>],
128 path: &Path,
129 f: &dyn Fn(&T) -> U,
130 ) {
131 for (i, child) in children.iter().enumerate() {
132 let mut child_path = path.clone();
133 child_path.push_back(i);
134 self.insert(f(&child.item), child_path.clone());
135 self.insert_children_map(&child.children, &child_path, f);
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 use std::ops::Deref;
145
146 #[test]
147 fn test_path_split_front_empty() {
148 let res = Path::new().split_front();
149 assert_eq!(res, None);
150 }
151
152 #[test]
153 fn test_path_push_back() {
154 let mut path = Path::new();
155 path.push_back(1);
156 path.push_back(2);
157 path.push_back(3);
158
159 let mut actual_vec = VecDeque::new();
160 actual_vec.push_back(1);
161 actual_vec.push_back(2);
162 actual_vec.push_back(3);
163 let actual_path = Path(actual_vec);
164
165 assert_eq!(path, actual_path);
166 }
167
168 #[test]
169 fn test_path_split_front_nonempty() {
170 let mut path = Path::new();
171 path.push_back(1);
172 path.push_back(2);
173 path.push_back(3);
174 let res = path.split_front();
175
176 let mut actual_path = Path::new();
177 actual_path.push_back(2);
178 actual_path.push_back(3);
179
180 let actual = Some((1, actual_path));
181
182 assert_eq!(res, actual);
183 }
184
185 #[test]
186 fn test_lookup_no_item() {
187 let tree = Tree::new(
188 "root",
189 vec![
190 Tree::singleton("0"),
191 Tree::singleton("1"),
192 Tree::new(
193 "2",
194 vec![Tree::singleton("2-0"), Tree::singleton("2-1")],
195 ),
196 ],
197 );
198
199 let path1 = vec![3].into();
200 let path2 = vec![0, 1].into();
201 let path3 = vec![1, 0].into();
202 let path4 = vec![2, 2].into();
203 let path5 = vec![2, 0, 3].into();
204 let path6 = vec![0, 1, 2, 3, 4].into();
205
206 assert_eq!(tree.lookup(path1), None);
207 assert_eq!(tree.lookup(path2), None);
208 assert_eq!(tree.lookup(path3), None);
209 assert_eq!(tree.lookup(path4), None);
210 assert_eq!(tree.lookup(path5), None);
211 assert_eq!(tree.lookup(path6), None);
212 }
213
214 #[test]
215 fn test_lookup_find_item() {
216 let tree: Tree<String> = Tree::new(
217 "root".into(),
218 vec![
219 Tree::singleton("0".into()),
220 Tree::singleton("1".into()),
221 Tree::new(
222 "2".into(),
223 vec![
224 Tree::singleton("2-0".into()),
225 Tree::new(
226 "2-1".into(),
227 vec![
228 Tree::singleton("2-1-0".into()),
229 Tree::singleton("2-1-1".into()),
230 ],
231 ),
232 ],
233 ),
234 ],
235 );
236
237 let path_root = vec![].into();
238 let path0 = vec![0].into();
239 let path1 = vec![1].into();
240 let path2 = vec![2].into();
241 let path2_0 = vec![2, 0].into();
242 let path2_1 = vec![2, 1].into();
243 let path2_1_0 = vec![2, 1, 0].into();
244 let path2_1_1 = vec![2, 1, 1].into();
245
246 assert_eq!(tree.lookup(path_root).map(String::deref), Some("root"));
247 assert_eq!(tree.lookup(path0).map(String::deref), Some("0"));
248 assert_eq!(tree.lookup(path1).map(String::deref), Some("1"));
249 assert_eq!(tree.lookup(path2).map(String::deref), Some("2"));
250 assert_eq!(tree.lookup(path2_0).map(String::deref), Some("2-0"));
251 assert_eq!(tree.lookup(path2_1).map(String::deref), Some("2-1"));
252 assert_eq!(tree.lookup(path2_1_0).map(String::deref), Some("2-1-0"));
253 assert_eq!(tree.lookup(path2_1_1).map(String::deref), Some("2-1-1"));
254 }
255
256 #[test]
257 fn test_tree_path_map_from_tree_all_unique() {
258 let tree: Tree<String> = Tree::new(
259 "root".into(),
260 vec![
261 Tree::singleton("0".into()),
262 Tree::singleton("1".into()),
263 Tree::new(
264 "2".into(),
265 vec![
266 Tree::singleton("2-0".into()),
267 Tree::new(
268 "2-1".into(),
269 vec![
270 Tree::singleton("2-1-0".into()),
271 Tree::singleton("2-1-1".into()),
272 ],
273 ),
274 ],
275 ),
276 ],
277 );
278
279 let res_tree_path_map: TreePathMap<String> = tree.path_map();
280
281 let mut actual_tree_path_map: HashMap<String, Vec<Path>> =
282 HashMap::new();
283
284 actual_tree_path_map.insert("root".into(), vec![Path::new()]);
285 actual_tree_path_map.insert("0".into(), vec![vec![0].into()]);
286 actual_tree_path_map.insert("1".into(), vec![vec![1].into()]);
287 actual_tree_path_map.insert("2".into(), vec![vec![2].into()]);
288 actual_tree_path_map.insert("2-0".into(), vec![vec![2, 0].into()]);
289 actual_tree_path_map.insert("2-1".into(), vec![vec![2, 1].into()]);
290 actual_tree_path_map.insert("2-1-0".into(), vec![vec![2, 1, 0].into()]);
291 actual_tree_path_map.insert("2-1-1".into(), vec![vec![2, 1, 1].into()]);
292
293 assert_eq!(res_tree_path_map, TreePathMap(actual_tree_path_map));
294 }
295
296 #[test]
297 fn test_tree_path_map_from_tree() {
298 let tree: Tree<String> = Tree::new(
299 "cat".into(), vec![
301 Tree::singleton("dog".into()), Tree::singleton("cat".into()), Tree::new(
304 "mouse".into(), vec![
306 Tree::singleton("fish".into()), Tree::new(
308 "fish".into(), vec![
310 Tree::singleton("dog".into()), Tree::singleton("cat".into()), ],
313 ),
314 ],
315 ),
316 ],
317 );
318
319 let res_tree_path_map: TreePathMap<String> = tree.path_map();
320
321 let mut actual_tree_path_map: HashMap<String, Vec<Path>> =
322 HashMap::new();
323
324 actual_tree_path_map.insert(
325 "cat".into(),
326 vec![Path::new(), vec![1].into(), vec![2, 1, 1].into()],
327 );
328 actual_tree_path_map
329 .insert("dog".into(), vec![vec![0].into(), vec![2, 1, 0].into()]);
330 actual_tree_path_map.insert("mouse".into(), vec![vec![2].into()]);
331 actual_tree_path_map
332 .insert("fish".into(), vec![vec![2, 0].into(), vec![2, 1].into()]);
333
334 assert_eq!(res_tree_path_map, TreePathMap(actual_tree_path_map));
335 }
336}