ICFP 2007 Contest: https://web.archive.org/web/20090301164728/https://save-endo.cs.uu.nl/
1use std::collections::VecDeque;
2use std::ops::Add;
3use std::ops::Deref;
4use std::ops::Index;
5use std::rc::Rc;
6
7#[derive(Copy, Clone, PartialEq, Debug)]
8pub enum Base {
9 I,
10 C,
11 F,
12 P,
13}
14
15#[derive(Clone, Debug)]
16pub enum Dna {
17 Empty,
18 Leaf(Base),
19 TwoNode(TwoNode),
20 ThreeNode(ThreeNode),
21}
22
23#[derive(Clone, Debug)]
24// Wrap Rc in a single-value enum so I can implement traits for it.
25pub enum DnaRef {
26 DnaRef(Rc<Dna>),
27}
28
29#[derive(Clone, Debug)]
30pub struct TwoNode {
31 len: usize,
32 depth: usize,
33 children: (DnaRef, DnaRef),
34}
35
36#[derive(Clone, Debug)]
37pub struct ThreeNode {
38 len: usize,
39 depth: usize,
40 children: (DnaRef, DnaRef, DnaRef),
41}
42
43impl Base {
44 pub fn from_char(c: char) -> Option<Base> {
45 match c {
46 'I' => Some(Base::I),
47 'C' => Some(Base::C),
48 'F' => Some(Base::F),
49 'P' => Some(Base::P),
50 _ => None,
51 }
52 }
53
54 pub fn to_char(&self) -> char {
55 match self {
56 Base::I => 'I',
57 Base::C => 'C',
58 Base::F => 'F',
59 Base::P => 'P',
60 }
61 }
62}
63
64impl DnaRef {
65 pub fn new() -> Self {
66 Self::DnaRef(Rc::new(Dna::Empty))
67 }
68
69 pub fn from_base(b: Base) -> Self {
70 Self::DnaRef(Rc::new(Dna::Leaf(b)))
71 }
72
73 fn from_two_children(a: DnaRef, b: DnaRef) -> Self {
74 debug_assert_eq!(a.depth(), b.depth());
75 Self::DnaRef(Rc::new(Dna::TwoNode(TwoNode {
76 len: a.len() + b.len(),
77 depth: a.depth() + 1,
78 children: (a, b),
79 })))
80 }
81
82 fn from_three_children(a: DnaRef, b: DnaRef, c: DnaRef) -> Self {
83 debug_assert_eq!(a.depth(), b.depth());
84 debug_assert_eq!(a.depth(), c.depth());
85 Self::DnaRef(Rc::new(Dna::ThreeNode(ThreeNode {
86 len: a.len() + b.len() + c.len(),
87 depth: a.depth() + 1,
88 children: (a, b, c),
89 })))
90 }
91
92 pub fn from_string(s: &str) -> Self {
93 s.chars()
94 .filter_map(|c| Base::from_char(c))
95 .map(|b| DnaRef::from_base(b))
96 .collect::<DnaRef>()
97 }
98
99 pub fn len(&self) -> usize {
100 match &**self {
101 Dna::Empty => 0,
102 Dna::Leaf(_) => 1,
103 Dna::TwoNode(node) => node.len,
104 Dna::ThreeNode(node) => node.len,
105 }
106 }
107
108 fn depth(&self) -> usize {
109 match &**self {
110 Dna::Empty => 0,
111 Dna::Leaf(_) => 1,
112 Dna::TwoNode(node) => node.depth,
113 Dna::ThreeNode(node) => node.depth,
114 }
115 }
116
117 pub fn iter<'a>(&'a self) -> DnaIterator<'a> {
118 let mut stack = Vec::new();
119 stack.push(self);
120 DnaIterator { stack }
121 }
122
123 pub fn split(&self, n: usize) -> (DnaRef, DnaRef) {
124 debug_assert!(n <= self.len());
125 match &**self {
126 Dna::Empty => (DnaRef::new(), DnaRef::new()),
127 Dna::Leaf(b) => {
128 if n == 0 {
129 (DnaRef::new(), DnaRef::from_base(*b))
130 } else {
131 (DnaRef::from_base(*b), DnaRef::new())
132 }
133 }
134 Dna::TwoNode(node) => {
135 let (a, b) = &node.children;
136 if n < a.len() {
137 let (x, y) = a.split(n);
138 (x, y + b.clone())
139 } else if n == a.len() {
140 (a.clone(), b.clone())
141 } else {
142 let (x, y) = b.split(n - a.len());
143 (a.clone() + x, y)
144 }
145 }
146 Dna::ThreeNode(node) => {
147 let (a, b, c) = &node.children;
148 if n < a.len() {
149 let (x, y) = a.split(n);
150 (x, y + b.clone() + c.clone())
151 } else if n == a.len() {
152 (a.clone(), b.clone() + c.clone())
153 } else if n - a.len() < b.len() {
154 let (x, y) = b.split(n - a.len());
155 (a.clone() + x, y + c.clone())
156 } else if n == a.len() + b.len() {
157 (a.clone() + b.clone(), c.clone())
158 } else {
159 let (x, y) = c.split(n - a.len() - b.len());
160 (a.clone() + b.clone() + x, y)
161 }
162 }
163 }
164 }
165
166 #[cfg(test)]
167 pub fn to_string(&self) -> String {
168 self.iter().map(|b| Base::to_char(&b)).collect::<String>()
169 }
170}
171
172impl Deref for DnaRef {
173 type Target = Dna;
174
175 fn deref(&self) -> &Self::Target {
176 match self {
177 DnaRef::DnaRef(r) => &*r,
178 }
179 }
180}
181
182struct DnaRefIter<I>
183where
184 I: Iterator<Item = DnaRef>,
185{
186 iter: I,
187 buf: VecDeque<DnaRef>,
188}
189
190impl<I> DnaRefIter<I>
191where
192 I: Iterator<Item = DnaRef>,
193{
194 fn new(iter: I) -> DnaRefIter<I> {
195 DnaRefIter {
196 iter: iter,
197 buf: VecDeque::with_capacity(5),
198 }
199 }
200}
201
202impl<I> Iterator for DnaRefIter<I>
203where
204 I: Iterator<Item = DnaRef>,
205{
206 type Item = DnaRef;
207 fn next(&mut self) -> Option<Self::Item> {
208 while self.buf.len() < 5 {
209 let Some(x) = self.iter.next() else {
210 break;
211 };
212
213 self.buf.push_back(x);
214 }
215
216 if self.buf.len() == 5 || self.buf.len() == 3 {
217 let a = self.buf.pop_front().unwrap();
218 let b = self.buf.pop_front().unwrap();
219 let c = self.buf.pop_front().unwrap();
220
221 return Some(DnaRef::from_three_children(a, b, c));
222 } else if self.buf.len() == 4 || self.buf.len() == 2 {
223 let a = self.buf.pop_front().unwrap();
224 let b = self.buf.pop_front().unwrap();
225
226 return Some(DnaRef::from_two_children(a, b));
227 } else {
228 return None;
229 }
230 }
231}
232
233impl FromIterator<DnaRef> for DnaRef {
234 fn from_iter<I: IntoIterator<Item = DnaRef>>(iter: I) -> DnaRef {
235 // We need some kind of buffer no matter what, even if we aggregate as we go.
236 // This implementation does the easy thing and just repeatedly collects into a Vec.
237 let mut cur: Vec<DnaRef> = iter.into_iter().collect::<Vec<_>>();
238 while cur.len() > 1 {
239 cur = DnaRefIter::new(cur.into_iter()).collect();
240 }
241
242 match cur.pop() {
243 Some(dna) => dna,
244 None => DnaRef::new(),
245 }
246 }
247}
248
249pub struct DnaIterator<'a> {
250 stack: Vec<&'a DnaRef>,
251}
252
253impl<'a> Iterator for DnaIterator<'a> {
254 type Item = Base;
255
256 fn next(&mut self) -> Option<Self::Item> {
257 while let Some(node) = self.stack.pop() {
258 match &**node {
259 Dna::Empty => return None,
260 Dna::Leaf(c) => return Some(*c),
261 Dna::TwoNode(node) => {
262 let (a, b) = &node.children;
263 self.stack.push(b);
264 self.stack.push(a);
265 }
266 Dna::ThreeNode(node) => {
267 let (a, b, c) = &node.children;
268 self.stack.push(c);
269 self.stack.push(b);
270 self.stack.push(a);
271 }
272 }
273 }
274
275 return None;
276 }
277}
278
279enum AddState {
280 One(DnaRef),
281 Two(DnaRef, DnaRef),
282}
283
284fn add_helper(lhs: DnaRef, rhs: DnaRef) -> AddState {
285 if lhs.depth() == rhs.depth() {
286 AddState::Two(lhs, rhs)
287 } else if lhs.depth() < rhs.depth() {
288 match &*rhs {
289 Dna::Empty => unreachable!(),
290 Dna::Leaf(_) => AddState::One(rhs),
291 Dna::TwoNode(node) => {
292 let (a, b) = &node.children;
293 match add_helper(lhs, a.clone()) {
294 AddState::One(x) => AddState::One(DnaRef::from_two_children(x, b.clone())),
295 AddState::Two(x, y) => {
296 AddState::One(DnaRef::from_three_children(x, y, b.clone()))
297 }
298 }
299 }
300 Dna::ThreeNode(node) => {
301 let (a, b, c) = &node.children;
302 match add_helper(lhs, a.clone()) {
303 AddState::One(x) => {
304 AddState::One(DnaRef::from_three_children(x, b.clone(), c.clone()))
305 }
306 AddState::Two(x, y) => AddState::Two(
307 DnaRef::from_two_children(x, y),
308 DnaRef::from_two_children(b.clone(), c.clone()),
309 ),
310 }
311 }
312 }
313 } else {
314 match &*lhs {
315 Dna::Empty => unreachable!(),
316 Dna::Leaf(_) => AddState::One(lhs.clone()),
317 Dna::TwoNode(node) => {
318 let (a, b) = &node.children;
319 match add_helper(b.clone(), rhs) {
320 AddState::One(x) => AddState::One(DnaRef::from_two_children(a.clone(), x)),
321 AddState::Two(x, y) => {
322 AddState::One(DnaRef::from_three_children(a.clone(), x, y))
323 }
324 }
325 }
326 Dna::ThreeNode(node) => {
327 let (a, b, c) = &node.children;
328 match add_helper(c.clone(), rhs) {
329 AddState::One(x) => {
330 AddState::One(DnaRef::from_three_children(a.clone(), b.clone(), x))
331 }
332 AddState::Two(x, y) => AddState::Two(
333 DnaRef::from_two_children(a.clone(), b.clone()),
334 DnaRef::from_two_children(x, y),
335 ),
336 }
337 }
338 }
339 }
340}
341
342impl Add for DnaRef {
343 type Output = Self;
344
345 fn add(self, other: Self) -> Self {
346 match add_helper(self, other) {
347 AddState::One(a) => a,
348 AddState::Two(a, b) => Self::from_two_children(a, b),
349 }
350 }
351}
352
353impl Index<usize> for DnaRef {
354 type Output = Base;
355
356 fn index(&self, n: usize) -> &Self::Output {
357 debug_assert!(n < self.len());
358
359 match &**self {
360 Dna::Empty => unreachable!(),
361 Dna::Leaf(c) => c,
362 Dna::TwoNode(node) => {
363 let (a, b) = &node.children;
364 if n < a.len() {
365 a.index(n)
366 } else {
367 b.index(n - a.len())
368 }
369 }
370 Dna::ThreeNode(node) => {
371 let (a, b, c) = &node.children;
372 if n < a.len() {
373 a.index(n)
374 } else if n < a.len() + b.len() {
375 b.index(n - a.len())
376 } else {
377 c.index(n - a.len() - b.len())
378 }
379 }
380 }
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387
388 #[test]
389 fn test_empty() {
390 let dna: DnaRef = DnaRef::new();
391 assert_eq!(dna.len(), 0);
392 }
393
394 #[test]
395 fn test_to_from_string() {
396 let dna: DnaRef = DnaRef::from_string("ICFP");
397 assert_eq!(dna.to_string(), "ICFP");
398 }
399
400 #[test]
401 fn test_index() {
402 let s = "ICFP";
403 let dna: DnaRef = DnaRef::from_string(s);
404 assert_eq!(dna[0], Base::I);
405 assert_eq!(dna[1], Base::C);
406 assert_eq!(dna[2], Base::F);
407 assert_eq!(dna[3], Base::P);
408 }
409
410 #[test]
411 fn test_add() {
412 let lhs = DnaRef::from_string("IIIC");
413 let rhs = DnaRef::from_string("PFFF");
414 assert_eq!((lhs + rhs).to_string(), "IIICPFFF");
415 }
416
417 #[test]
418 fn test_split() {
419 let dna = DnaRef::from_string("IIICPFFF");
420 let (lhs, rhs) = dna.split(4);
421 assert_eq!(lhs.to_string(), "IIIC");
422 assert_eq!(rhs.to_string(), "PFFF");
423 }
424}