Change snake type to a tuple of two values
This commit is contained in:
parent
74e2805a95
commit
c0e37a9c67
1 changed files with 21 additions and 31 deletions
|
|
@ -132,16 +132,6 @@ impl IndexMut<isize> for V {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `Snake` is a sequence of diagonal edges in the edit graph. Normally
|
|
||||||
/// a snake has a start end end point (and it is possible for a snake to have
|
|
||||||
/// a length of zero, meaning the start and end points are the same) however
|
|
||||||
/// we do not need the end point which is why it's not implemented here.
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Snake {
|
|
||||||
x_start: usize,
|
|
||||||
y_start: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn max_d(len1: usize, len2: usize) -> usize {
|
fn max_d(len1: usize, len2: usize) -> usize {
|
||||||
// XXX look into reducing the need to have the additional '+ 1'
|
// XXX look into reducing the need to have the additional '+ 1'
|
||||||
(len1 + len2 + 1) / 2 + 1
|
(len1 + len2 + 1) / 2 + 1
|
||||||
|
|
@ -199,12 +189,17 @@ fn split_at(range: Range<usize>, at: usize) -> (Range<usize>, Range<usize>) {
|
||||||
(range.start..at, at..range.end)
|
(range.start..at, at..range.end)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The divide part of a divide-and-conquer strategy. A D-path has D+1 snakes
|
/// A `Snake` is a sequence of diagonal edges in the edit graph. Normally
|
||||||
// some of which may be empty. The divide step requires finding the ceil(D/2) +
|
/// a snake has a start end end point (and it is possible for a snake to have
|
||||||
// 1 or middle snake of an optimal D-path. The idea for doing so is to
|
/// a length of zero, meaning the start and end points are the same) however
|
||||||
// simultaneously run the basic algorithm in both the forward and reverse
|
/// we do not need the end point which is why it's not implemented here.
|
||||||
// directions until furthest reaching forward and reverse paths starting at
|
///
|
||||||
// opposing corners 'overlap'.
|
/// The divide part of a divide-and-conquer strategy. A D-path has D+1 snakes
|
||||||
|
/// some of which may be empty. The divide step requires finding the ceil(D/2) +
|
||||||
|
/// 1 or middle snake of an optimal D-path. The idea for doing so is to
|
||||||
|
/// simultaneously run the basic algorithm in both the forward and reverse
|
||||||
|
/// directions until furthest reaching forward and reverse paths starting at
|
||||||
|
/// opposing corners 'overlap'.
|
||||||
fn find_middle_snake<Old, New>(
|
fn find_middle_snake<Old, New>(
|
||||||
old: &Old,
|
old: &Old,
|
||||||
old_range: Range<usize>,
|
old_range: Range<usize>,
|
||||||
|
|
@ -213,7 +208,7 @@ fn find_middle_snake<Old, New>(
|
||||||
vf: &mut V,
|
vf: &mut V,
|
||||||
vb: &mut V,
|
vb: &mut V,
|
||||||
deadline: Option<Instant>,
|
deadline: Option<Instant>,
|
||||||
) -> Option<Snake>
|
) -> Option<(usize, usize)>
|
||||||
where
|
where
|
||||||
Old: Index<usize> + ?Sized,
|
Old: Index<usize> + ?Sized,
|
||||||
New: Index<usize> + ?Sized,
|
New: Index<usize> + ?Sized,
|
||||||
|
|
@ -278,10 +273,7 @@ where
|
||||||
// TODO optimize this so we don't have to compare against n
|
// TODO optimize this so we don't have to compare against n
|
||||||
if vf[k] + vb[-(k - delta)] >= n {
|
if vf[k] + vb[-(k - delta)] >= n {
|
||||||
// Return the snake
|
// Return the snake
|
||||||
return Some(Snake {
|
return Some((x0 + old_range.start, y0 + new_range.start));
|
||||||
x_start: x0 + old_range.start,
|
|
||||||
y_start: y0 + new_range.start,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -314,10 +306,7 @@ where
|
||||||
// TODO optimize this so we don't have to compare against n
|
// TODO optimize this so we don't have to compare against n
|
||||||
if vb[k] + vf[-(k - delta)] >= n {
|
if vb[k] + vf[-(k - delta)] >= n {
|
||||||
// Return the snake
|
// Return the snake
|
||||||
return Some(Snake {
|
return Some((n - x + old_range.start, m - y + new_range.start));
|
||||||
x_start: n - x + old_range.start,
|
|
||||||
y_start: m - y + new_range.start,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -377,7 +366,7 @@ where
|
||||||
new_range.start,
|
new_range.start,
|
||||||
new_range.end - new_range.start,
|
new_range.end - new_range.start,
|
||||||
)?;
|
)?;
|
||||||
} else if let Some(snake) = find_middle_snake(
|
} else if let Some((x_start, y_start)) = find_middle_snake(
|
||||||
old,
|
old,
|
||||||
old_range.clone(),
|
old_range.clone(),
|
||||||
new,
|
new,
|
||||||
|
|
@ -386,8 +375,8 @@ where
|
||||||
vb,
|
vb,
|
||||||
deadline,
|
deadline,
|
||||||
) {
|
) {
|
||||||
let (old_a, old_b) = split_at(old_range, snake.x_start);
|
let (old_a, old_b) = split_at(old_range, x_start);
|
||||||
let (new_a, new_b) = split_at(new_range, snake.y_start);
|
let (new_a, new_b) = split_at(new_range, y_start);
|
||||||
conquer(d, old, old_a, new, new_a, vf, vb, deadline)?;
|
conquer(d, old, old_a, new, new_a, vf, vb, deadline)?;
|
||||||
conquer(d, old, old_b, new, new_b, vf, vb, deadline)?;
|
conquer(d, old, old_b, new, new_b, vf, vb, deadline)?;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -417,9 +406,10 @@ fn test_find_middle_snake() {
|
||||||
let max_d = max_d(a.len(), b.len());
|
let max_d = max_d(a.len(), b.len());
|
||||||
let mut vf = V::new(max_d);
|
let mut vf = V::new(max_d);
|
||||||
let mut vb = V::new(max_d);
|
let mut vb = V::new(max_d);
|
||||||
let snake = find_middle_snake(a, 0..a.len(), b, 0..b.len(), &mut vf, &mut vb, None).unwrap();
|
let (x_start, y_start) =
|
||||||
assert_eq!(snake.x_start, 4);
|
find_middle_snake(a, 0..a.len(), b, 0..b.len(), &mut vf, &mut vb, None).unwrap();
|
||||||
assert_eq!(snake.y_start, 1);
|
assert_eq!(x_start, 4);
|
||||||
|
assert_eq!(y_start, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue