ICFP 2007 Contest: https://web.archive.org/web/20090301164728/https://save-endo.cs.uu.nl/

Use Index trait instead of index method

Changed files
+90 -93
dna2rna
src
+90 -93
dna2rna/src/dna.rs
···
use std::collections::VecDeque;
use std::ops::Add;
use std::ops::Deref;
+
use std::ops::Index;
use std::rc::Rc;
#[derive(Clone)]
···
}
}
-
// Use Index trait instead
-
pub fn index(&self, n: usize) -> char {
-
debug_assert!(n < self.len());
-
-
match &**self {
-
Dna::Empty => unreachable!(),
-
Dna::Leaf(c) => *c,
-
Dna::TwoNode(node) => {
-
let (a, b) = &node.children;
-
if n < a.len() {
-
a.index(n)
-
} else {
-
b.index(n - a.len())
-
}
-
}
-
Dna::ThreeNode(node) => {
-
let (a, b, c) = &node.children;
-
if n < a.len() {
-
a.index(n)
-
} else if n < a.len() + b.len() {
-
b.index(n - a.len())
-
} else {
-
c.index(n - a.len() - b.len())
-
}
-
}
-
}
+
pub fn iter<'a>(&'a self) -> DnaIterator<'a> {
+
let mut stack = Vec::new();
+
stack.push(self);
+
DnaIterator { stack }
}
pub fn split(&self, n: usize) -> (DnaRef, DnaRef) {
debug_assert!(n <= self.len());
match &**self {
-
Dna::Empty => (Self::new(), Self::new()),
+
Dna::Empty => (DnaRef::new(), DnaRef::new()),
Dna::Leaf(c) => {
if n == 0 {
-
(Self::new(), Self::from_char(*c))
+
(DnaRef::new(), DnaRef::from_char(*c))
} else {
-
(Self::from_char(*c), Self::new())
+
(DnaRef::from_char(*c), DnaRef::new())
}
}
Dna::TwoNode(node) => {
···
(a.clone(), b.clone() + c.clone())
} else if n - a.len() < b.len() {
let (x, y) = b.split(n - a.len());
-
(a.clone() + x, y + c.clone())
+
(a.clone() + x, y + c.clone())
} else if n == a.len() + b.len() {
-
(a.clone() + b.clone(), c.clone())
+
(a.clone() + b.clone(), c.clone())
} else {
let (x, y) = c.split(n - a.len() - b.len());
-
(a.clone() + b.clone() + x, y)
+
(a.clone() + b.clone() + x, y)
}
}
}
}
-
-
pub fn iter<'a>(&'a self) -> DnaIterator<'a> {
-
let mut stack = Vec::new();
-
stack.push(self);
-
DnaIterator { stack }
-
}
}
impl Deref for DnaRef {
···
Two(DnaRef, DnaRef),
}
-
fn add_helper(lhs: DnaRef, rhs: DnaRef) -> AddState {
-
if lhs.depth() == rhs.depth() {
-
AddState::Two(lhs, rhs)
-
} else if lhs.depth() < rhs.depth() {
-
match &*rhs {
-
Dna::Empty => unreachable!(),
-
Dna::Leaf(_) => unreachable!(),
-
Dna::TwoNode(node) => {
-
let (a, b) = &node.children;
-
match add_helper(lhs, a.clone()) {
-
AddState::One(x) => {
-
AddState::One(DnaRef::from_two_children(x, b.clone()))
-
}
-
AddState::Two(x, y) => {
-
AddState::One(DnaRef::from_three_children(x, y, b.clone()))
-
}
+
fn add_helper(lhs: DnaRef, rhs: DnaRef) -> AddState {
+
if lhs.depth() == rhs.depth() {
+
AddState::Two(lhs, rhs)
+
} else if lhs.depth() < rhs.depth() {
+
match &*rhs {
+
Dna::Empty => unreachable!(),
+
Dna::Leaf(_) => unreachable!(),
+
Dna::TwoNode(node) => {
+
let (a, b) = &node.children;
+
match add_helper(lhs, a.clone()) {
+
AddState::One(x) => AddState::One(DnaRef::from_two_children(x, b.clone())),
+
AddState::Two(x, y) => {
+
AddState::One(DnaRef::from_three_children(x, y, b.clone()))
}
}
-
Dna::ThreeNode(node) => {
-
let (a, b, c) = &node.children;
-
match add_helper(lhs, a.clone()) {
-
AddState::One(x) => {
-
AddState::One(DnaRef::from_three_children(x, b.clone(), c.clone()))
-
}
-
AddState::Two(x, y) => AddState::Two(
-
DnaRef::from_two_children(x, y),
-
DnaRef::from_two_children(b.clone(), c.clone()),
-
),
+
}
+
Dna::ThreeNode(node) => {
+
let (a, b, c) = &node.children;
+
match add_helper(lhs, a.clone()) {
+
AddState::One(x) => {
+
AddState::One(DnaRef::from_three_children(x, b.clone(), c.clone()))
}
+
AddState::Two(x, y) => AddState::Two(
+
DnaRef::from_two_children(x, y),
+
DnaRef::from_two_children(b.clone(), c.clone()),
+
),
}
}
-
} else {
-
match &*lhs {
-
Dna::Empty => unreachable!(),
-
Dna::Leaf(_) => unreachable!(),
-
Dna::TwoNode(node) => {
-
let (a, b) = &node.children;
-
match add_helper(b.clone(), rhs) {
-
AddState::One(x) => {
-
AddState::One(DnaRef::from_two_children(a.clone(), x))
-
}
-
AddState::Two(x, y) => {
-
AddState::One(DnaRef::from_three_children(a.clone(), x, y))
-
}
+
}
+
} else {
+
match &*lhs {
+
Dna::Empty => unreachable!(),
+
Dna::Leaf(_) => unreachable!(),
+
Dna::TwoNode(node) => {
+
let (a, b) = &node.children;
+
match add_helper(b.clone(), rhs) {
+
AddState::One(x) => AddState::One(DnaRef::from_two_children(a.clone(), x)),
+
AddState::Two(x, y) => {
+
AddState::One(DnaRef::from_three_children(a.clone(), x, y))
}
}
-
Dna::ThreeNode(node) => {
-
let (a, b, c) = &node.children;
-
match add_helper(c.clone(), rhs) {
-
AddState::One(x) => {
-
AddState::One(DnaRef::from_three_children(a.clone(), b.clone(), x))
-
}
-
AddState::Two(x, y) => AddState::Two(
-
DnaRef::from_two_children(a.clone(), b.clone()),
-
DnaRef::from_two_children(x, y),
-
),
+
}
+
Dna::ThreeNode(node) => {
+
let (a, b, c) = &node.children;
+
match add_helper(c.clone(), rhs) {
+
AddState::One(x) => {
+
AddState::One(DnaRef::from_three_children(a.clone(), b.clone(), x))
}
+
AddState::Two(x, y) => AddState::Two(
+
DnaRef::from_two_children(a.clone(), b.clone()),
+
DnaRef::from_two_children(x, y),
+
),
}
}
}
}
+
}
impl Add for DnaRef {
-
type Output = Self;
+
type Output = Self;
fn add(self, other: Self) -> Self {
match add_helper(self, other) {
···
}
}
+
impl Index<usize> for DnaRef {
+
type Output = char;
+
+
fn index(&self, n: usize) -> &Self::Output {
+
debug_assert!(n < self.len());
+
+
match &**self {
+
Dna::Empty => unreachable!(),
+
Dna::Leaf(c) => c,
+
Dna::TwoNode(node) => {
+
let (a, b) = &node.children;
+
if n < a.len() {
+
a.index(n)
+
} else {
+
b.index(n - a.len())
+
}
+
}
+
Dna::ThreeNode(node) => {
+
let (a, b, c) = &node.children;
+
if n < a.len() {
+
a.index(n)
+
} else if n < a.len() + b.len() {
+
b.index(n - a.len())
+
} else {
+
c.index(n - a.len() - b.len())
+
}
+
}
+
}
+
}
+
}
+
#[cfg(test)]
mod tests {
use super::*;
···
let s = "ICFP";
let dna: DnaRef = DnaRef::from_string(s);
for (i, c) in s.chars().enumerate() {
-
assert_eq!(dna.index(i), c);
+
assert_eq!(dna[i], c);
}
}
···
fn test_concat() {
let lhs = DnaRef::from_string("ABCD");
let rhs = DnaRef::from_string("WXYZ");
-
assert_eq!(
-
(lhs + rhs).iter().collect::<String>(),
-
"ABCDWXYZ"
-
);
+
assert_eq!((lhs + rhs).iter().collect::<String>(), "ABCDWXYZ");
}
#[test]