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 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 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 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 pub fn to_string(&self) -> String { 167 self.iter().map(|b| Base::to_char(&b)).collect::<String>() 168 } 169} 170 171impl Deref for DnaRef { 172 type Target = Dna; 173 174 fn deref(&self) -> &Self::Target { 175 match self { 176 DnaRef::DnaRef(r) => &*r, 177 } 178 } 179} 180 181struct DnaRefIter<I> 182where 183 I: Iterator<Item = DnaRef>, 184{ 185 iter: I, 186 buf: VecDeque<DnaRef>, 187} 188 189impl<I> DnaRefIter<I> 190where 191 I: Iterator<Item = DnaRef>, 192{ 193 fn new(iter: I) -> DnaRefIter<I> { 194 DnaRefIter { 195 iter: iter, 196 buf: VecDeque::with_capacity(5), 197 } 198 } 199} 200 201impl<I> Iterator for DnaRefIter<I> 202where 203 I: Iterator<Item = DnaRef>, 204{ 205 type Item = DnaRef; 206 fn next(&mut self) -> Option<Self::Item> { 207 while self.buf.len() < 5 { 208 let Some(x) = self.iter.next() else { 209 break; 210 }; 211 212 self.buf.push_back(x); 213 } 214 215 if self.buf.len() == 5 || self.buf.len() == 3 { 216 let a = self.buf.pop_front().unwrap(); 217 let b = self.buf.pop_front().unwrap(); 218 let c = self.buf.pop_front().unwrap(); 219 220 return Some(DnaRef::from_three_children(a, b, c)); 221 } else if self.buf.len() == 4 || self.buf.len() == 2 { 222 let a = self.buf.pop_front().unwrap(); 223 let b = self.buf.pop_front().unwrap(); 224 225 return Some(DnaRef::from_two_children(a, b)); 226 } else { 227 return None; 228 } 229 } 230} 231 232impl FromIterator<DnaRef> for DnaRef { 233 fn from_iter<I: IntoIterator<Item = DnaRef>>(iter: I) -> DnaRef { 234 // We need some kind of buffer no matter what, even if we aggregate as we go. 235 // This implementation does the easy thing and just repeatedly collects into a Vec. 236 let mut cur: Vec<DnaRef> = iter.into_iter().collect::<Vec<_>>(); 237 while cur.len() > 1 { 238 cur = DnaRefIter::new(cur.into_iter()).collect(); 239 } 240 241 match cur.pop() { 242 Some(dna) => dna, 243 None => DnaRef::new(), 244 } 245 } 246} 247 248pub struct DnaIterator<'a> { 249 stack: Vec<&'a DnaRef>, 250} 251 252impl<'a> Iterator for DnaIterator<'a> { 253 type Item = Base; 254 255 fn next(&mut self) -> Option<Self::Item> { 256 while let Some(node) = self.stack.pop() { 257 match &**node { 258 Dna::Empty => return None, 259 Dna::Leaf(c) => return Some(*c), 260 Dna::TwoNode(node) => { 261 let (a, b) = &node.children; 262 self.stack.push(b); 263 self.stack.push(a); 264 } 265 Dna::ThreeNode(node) => { 266 let (a, b, c) = &node.children; 267 self.stack.push(c); 268 self.stack.push(b); 269 self.stack.push(a); 270 } 271 } 272 } 273 274 return None; 275 } 276} 277 278enum AddState { 279 One(DnaRef), 280 Two(DnaRef, DnaRef), 281} 282 283fn add_helper(lhs: DnaRef, rhs: DnaRef) -> AddState { 284 if lhs.depth() == rhs.depth() { 285 AddState::Two(lhs, rhs) 286 } else if lhs.depth() < rhs.depth() { 287 match &*rhs { 288 Dna::Empty => unreachable!(), 289 Dna::Leaf(_) => AddState::One(rhs), 290 Dna::TwoNode(node) => { 291 let (a, b) = &node.children; 292 match add_helper(lhs, a.clone()) { 293 AddState::One(x) => AddState::One(DnaRef::from_two_children(x, b.clone())), 294 AddState::Two(x, y) => { 295 AddState::One(DnaRef::from_three_children(x, y, b.clone())) 296 } 297 } 298 } 299 Dna::ThreeNode(node) => { 300 let (a, b, c) = &node.children; 301 match add_helper(lhs, a.clone()) { 302 AddState::One(x) => { 303 AddState::One(DnaRef::from_three_children(x, b.clone(), c.clone())) 304 } 305 AddState::Two(x, y) => AddState::Two( 306 DnaRef::from_two_children(x, y), 307 DnaRef::from_two_children(b.clone(), c.clone()), 308 ), 309 } 310 } 311 } 312 } else { 313 match &*lhs { 314 Dna::Empty => unreachable!(), 315 Dna::Leaf(_) => AddState::One(lhs.clone()), 316 Dna::TwoNode(node) => { 317 let (a, b) = &node.children; 318 match add_helper(b.clone(), rhs) { 319 AddState::One(x) => AddState::One(DnaRef::from_two_children(a.clone(), x)), 320 AddState::Two(x, y) => { 321 AddState::One(DnaRef::from_three_children(a.clone(), x, y)) 322 } 323 } 324 } 325 Dna::ThreeNode(node) => { 326 let (a, b, c) = &node.children; 327 match add_helper(c.clone(), rhs) { 328 AddState::One(x) => { 329 AddState::One(DnaRef::from_three_children(a.clone(), b.clone(), x)) 330 } 331 AddState::Two(x, y) => AddState::Two( 332 DnaRef::from_two_children(a.clone(), b.clone()), 333 DnaRef::from_two_children(x, y), 334 ), 335 } 336 } 337 } 338 } 339} 340 341impl Add for DnaRef { 342 type Output = Self; 343 344 fn add(self, other: Self) -> Self { 345 match add_helper(self, other) { 346 AddState::One(a) => a, 347 AddState::Two(a, b) => Self::from_two_children(a, b), 348 } 349 } 350} 351 352impl Index<usize> for DnaRef { 353 type Output = Base; 354 355 fn index(&self, n: usize) -> &Self::Output { 356 debug_assert!(n < self.len()); 357 358 match &**self { 359 Dna::Empty => unreachable!(), 360 Dna::Leaf(c) => c, 361 Dna::TwoNode(node) => { 362 let (a, b) = &node.children; 363 if n < a.len() { 364 a.index(n) 365 } else { 366 b.index(n - a.len()) 367 } 368 } 369 Dna::ThreeNode(node) => { 370 let (a, b, c) = &node.children; 371 if n < a.len() { 372 a.index(n) 373 } else if n < a.len() + b.len() { 374 b.index(n - a.len()) 375 } else { 376 c.index(n - a.len() - b.len()) 377 } 378 } 379 } 380 } 381} 382 383#[cfg(test)] 384mod tests { 385 use super::*; 386 387 #[test] 388 fn test_empty() { 389 let dna: DnaRef = DnaRef::new(); 390 assert_eq!(dna.len(), 0); 391 } 392 393 #[test] 394 fn test_to_from_string() { 395 let dna: DnaRef = DnaRef::from_string("ICFP"); 396 assert_eq!(dna.to_string(), "ICFP"); 397 } 398 399 #[test] 400 fn test_index() { 401 let s = "ICFP"; 402 let dna: DnaRef = DnaRef::from_string(s); 403 assert_eq!(dna[0], Base::I); 404 assert_eq!(dna[1], Base::C); 405 assert_eq!(dna[2], Base::F); 406 assert_eq!(dna[3], Base::P); 407 } 408 409 #[test] 410 fn test_add() { 411 let lhs = DnaRef::from_string("IIIC"); 412 let rhs = DnaRef::from_string("PFFF"); 413 assert_eq!((lhs + rhs).to_string(), "IIICPFFF"); 414 } 415 416 #[test] 417 fn test_split() { 418 let dna = DnaRef::from_string("IIICPFFF"); 419 let (lhs, rhs) = dna.split(4); 420 assert_eq!(lhs.to_string(), "IIIC"); 421 assert_eq!(rhs.to_string(), "PFFF"); 422 } 423}