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

Implement AddAssign for DnaRef

Changed files
+83 -24
dna2rna
+80 -20
dna2rna/src/dna.rs
···
use std::collections::VecDeque;
use std::ops::Add;
+
use std::ops::AddAssign;
use std::ops::Deref;
use std::ops::Index;
use std::rc::Rc;
···
let (a, b) = &node.children;
if n < a.len() {
let (x, y) = a.split(n);
-
(x, y + b.clone())
+
(x, y + b)
} else if n == a.len() {
(a.clone(), b.clone())
} else {
let (x, y) = b.split(n - a.len());
-
(a.clone() + x, y)
+
(a + x, y)
}
}
Dna::ThreeNode(node) => {
let (a, b, c) = &node.children;
if n < a.len() {
let (x, y) = a.split(n);
-
(x, y + b.clone() + c.clone())
+
(x, y + b + c)
} else if n == a.len() {
-
(a.clone(), b.clone() + c.clone())
+
(a.clone(), b + c)
} else if n - a.len() < b.len() {
let (x, y) = b.split(n - a.len());
-
(a.clone() + x, y + c.clone())
+
(a + x, y + c)
} else if n == a.len() + b.len() {
-
(a.clone() + b.clone(), c.clone())
+
(a + b, c.clone())
} else {
let (x, y) = c.split(n - a.len() - b.len());
-
(a.clone() + b.clone() + x, y)
+
(a + b + x, y)
}
}
}
···
Two(DnaRef, DnaRef),
}
-
fn add_helper(lhs: DnaRef, rhs: DnaRef) -> AddState {
+
fn add_helper(lhs: &DnaRef, rhs: &DnaRef) -> AddState {
if lhs.depth() == rhs.depth() {
-
AddState::Two(lhs, rhs)
+
AddState::Two(lhs.clone(), rhs.clone())
} else if lhs.depth() < rhs.depth() {
-
match &*rhs {
+
match &**rhs {
Dna::Empty => unreachable!(),
-
Dna::Leaf(_) => AddState::One(rhs),
+
Dna::Leaf(_) => AddState::One(rhs.clone()),
Dna::TwoNode(node) => {
let (a, b) = &node.children;
-
match add_helper(lhs, a.clone()) {
+
match add_helper(lhs, a) {
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()) {
+
match add_helper(lhs, a) {
AddState::One(x) => {
AddState::One(DnaRef::from_three_children(x, b.clone(), c.clone()))
}
···
}
}
} else {
-
match &*lhs {
+
match &**lhs {
Dna::Empty => unreachable!(),
Dna::Leaf(_) => AddState::One(lhs.clone()),
Dna::TwoNode(node) => {
let (a, b) = &node.children;
-
match add_helper(b.clone(), rhs) {
+
match add_helper(b, 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) {
+
match add_helper(c, rhs) {
AddState::One(x) => {
AddState::One(DnaRef::from_three_children(a.clone(), b.clone(), x))
}
···
}
}
-
impl Add for DnaRef {
-
type Output = Self;
+
impl Add<DnaRef> for DnaRef {
+
type Output = DnaRef;
+
+
fn add(self, other: DnaRef) -> DnaRef {
+
match add_helper(&self, &other) {
+
AddState::One(a) => a,
+
AddState::Two(a, b) => DnaRef::from_two_children(a, b),
+
}
+
}
+
}
-
fn add(self, other: Self) -> Self {
+
impl Add<&DnaRef> for DnaRef {
+
type Output = DnaRef;
+
+
fn add(self, other: &DnaRef) -> DnaRef {
+
match add_helper(&self, other) {
+
AddState::One(a) => a,
+
AddState::Two(a, b) => DnaRef::from_two_children(a, b),
+
}
+
}
+
}
+
+
impl Add<DnaRef> for &DnaRef {
+
type Output = DnaRef;
+
+
fn add(self, other: DnaRef) -> DnaRef {
+
match add_helper(self, &other) {
+
AddState::One(a) => a,
+
AddState::Two(a, b) => DnaRef::from_two_children(a, b),
+
}
+
}
+
}
+
+
impl Add<&DnaRef> for &DnaRef {
+
type Output = DnaRef;
+
+
fn add(self, other: &DnaRef) -> DnaRef {
match add_helper(self, other) {
AddState::One(a) => a,
-
AddState::Two(a, b) => Self::from_two_children(a, b),
+
AddState::Two(a, b) => DnaRef::from_two_children(a, b),
+
}
+
}
+
}
+
+
impl AddAssign<DnaRef> for DnaRef {
+
fn add_assign(&mut self, other: DnaRef) {
+
match add_helper(self, &other) {
+
AddState::One(a) => {
+
*self = a;
+
}
+
AddState::Two(a, b) => {
+
*self = Self::from_two_children(a, b);
+
}
+
}
+
}
+
}
+
+
impl AddAssign<&DnaRef> for DnaRef {
+
fn add_assign(&mut self, other: &DnaRef) {
+
match add_helper(self, other) {
+
AddState::One(a) => {
+
*self = a;
+
}
+
AddState::Two(a, b) => {
+
*self = Self::from_two_children(a, b);
+
}
}
}
}
+3 -4
dna2rna/src/match_replace.rs
···
for t in template.into_iter() {
match t {
TemplateItem::Base(b) => {
-
// TODO: Implement AddAssign
-
replace = replace + DnaRef::from_base(b);
+
replace += DnaRef::from_base(b);
}
TemplateItem::Ref(n, l) => {
let (start, end) = matched.groups[n];
let (_, rhs) = dna.split(start);
let (group, _) = rhs.split(end - start);
-
replace = replace + protect(group, l);
+
replace += protect(group, l);
}
TemplateItem::Len(n) => {
let (start, end) = matched.groups[n];
-
replace = replace + asnat(end - start);
+
replace += asnat(end - start);
}
}
}