-
Notifications
You must be signed in to change notification settings - Fork 18
/
persistent_array.rs
118 lines (107 loc) · 3.6 KB
/
persistent_array.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
pub mod persistent_array {
use std::{convert::TryInto, rc::Rc};
#[derive(Clone)]
pub struct Node<T: Clone, const N: usize> {
data: Option<T>,
children: [Option<Rc<Node<T, N>>>; N],
}
impl<T: Clone, const N: usize> Node<T, N> {
pub fn new(data: Option<T>, children: [Option<Rc<Node<T, N>>>; N]) -> Self {
Self { data, children }
}
}
impl<T: Clone, const N: usize> Default for Node<T, N> {
fn default() -> Self {
Self {
data: None,
children: default_array(),
}
}
}
pub fn set<T: Clone, const N: usize>(
index: usize,
data: T,
node: Option<Rc<Node<T, N>>>,
) -> Rc<Node<T, N>> {
if index == 0 {
match node {
Some(node) => {
let new_node = Node::new(Some(data), node.children.clone());
Rc::new(new_node)
}
None => Rc::new(Node::new(Some(data), default_array())),
}
} else {
let child = match node
.as_ref()
.and_then::<&Rc<Node<T, N>>, _>(|node| node.children[index % N].as_ref())
{
Some(next_node) => set(index / N, data, Some(next_node.clone())),
None => set(index / N, data, None),
};
let mut new_node = match node {
Some(node) => node.as_ref().clone(),
None => Node::default(),
};
new_node.children[index % N] = Some(child);
Rc::new(new_node)
}
}
pub fn get<T: Clone, const N: usize>(index: usize, node: &Rc<Node<T, N>>) -> Option<T> {
if index == 0 {
node.data.clone()
} else {
match node.children[index % N].as_ref() {
Some(next_node) => get(index / N, next_node),
None => None,
}
}
}
fn default_array<T: Clone, const N: usize>() -> [Option<Rc<Node<T, N>>>; N] {
let mut children = Vec::with_capacity(N);
for _ in 0..N {
children.push(None);
}
children.try_into().unwrap_or_else(|_| panic!())
}
}
#[cfg(test)]
mod tests {
use super::persistent_array::{get, set, Node};
use rand::distributions::Uniform;
use rand::{thread_rng, Rng};
use std::rc::Rc;
#[test]
fn test_persistent_array() {
let mut rng = thread_rng();
let n: usize = 20;
let mut vs = vec![vec![None; n]];
let mut nodes = vec![Rc::new(Node::<_, 20>::default())];
for _ in 0..10000 {
let pick = rng.sample(Uniform::from(0..vs.len()));
let mut new_vec = vs[pick].clone();
let node = nodes[pick].clone();
let pos = rng.sample(Uniform::from(0..n));
let value: i64 = rng.gen();
new_vec[pos] = Some(value);
let new_node = set(pos, value, Some(node));
for i in 0..n {
let expected = new_vec[i];
let actual = get(i, &new_node);
assert_eq!(expected, actual);
}
vs.push(new_vec.clone());
nodes.push(new_node.clone());
let value: i64 = rng.gen();
new_vec[pos] = Some(value);
let new_node = set(pos, value, Some(new_node));
for i in 0..n {
let expected = new_vec[i];
let actual = get(i, &new_node);
assert_eq!(expected, actual);
}
vs.push(new_vec.clone());
nodes.push(new_node);
}
}
}