what am i doing
This commit is contained in:
1 parent
af82016d1c
commit
fbd6cff526
8 files changed
+795
-31
No files matched your search
@@ -0,0 +1,56 @@
|
||||
Source String: AGTACGCA
|
||||
Target String: TATGC
|
||||
Edit Distance: 4
|
||||
Edit Sequence:
|
||||
Step 1: Delete 'A'
|
||||
Step 2: Delete 'G'
|
||||
Step 3: Match 'T'
|
||||
Step 4: Match 'A'
|
||||
Step 5: Substitute 'C' with 'T'
|
||||
Step 6: Match 'G'
|
||||
Step 7: Match 'C'
|
||||
Step 8: Delete 'A'
|
||||
|
||||
Reconstructed:
|
||||
from: AGTACGCA,
|
||||
to: TATGC
|
||||
this is the d
|
||||
0 1 2 3 4 5
|
||||
0 1 2 3 4 5
|
||||
bih Insert 'T' Insert 'A' Insert 'T' Insert 'G' Insert 'C'
|
||||
|
||||
0 1 2 3 4 5
|
||||
1 1 1 2 3 4
|
||||
Delete 'A' Substitute 'A' with 'T' Match 'A' Insert 'T' Insert 'G' Insert 'C'
|
||||
|
||||
0 1 2 3 4 5
|
||||
2 2 2 2 2 3
|
||||
Delete 'G' Delete 'G' Delete 'G' Substitute 'G' with 'T' Match 'G' Insert 'C'
|
||||
|
||||
0 1 2 3 4 5
|
||||
3 2 3 2 3 3
|
||||
Delete 'T' Match 'T' Delete 'T' Match 'T' Delete 'T' Substitute 'T' with 'C'
|
||||
|
||||
0 1 2 3 4 5
|
||||
4 3 2 3 3 4
|
||||
Delete 'A' Delete 'A' Match 'A' Delete 'A' Substitute 'A' with 'G' Delete 'A'
|
||||
|
||||
0 1 2 3 4 5
|
||||
5 4 3 3 4 3
|
||||
Delete 'C' Delete 'C' Delete 'C' Substitute 'C' with 'T' Delete 'C' Match 'C'
|
||||
|
||||
0 1 2 3 4 5
|
||||
6 5 4 4 3 4
|
||||
Delete 'G' Delete 'G' Delete 'G' Delete 'G' Match 'G' Delete 'G'
|
||||
|
||||
0 1 2 3 4 5
|
||||
7 6 5 5 4 3
|
||||
Delete 'C' Delete 'C' Delete 'C' Delete 'C' Delete 'C' Match 'C'
|
||||
|
||||
0 1 2 3 4 5
|
||||
8 7 6 6 5 4
|
||||
Delete 'A' Delete 'A' Delete 'A' Delete 'A' Delete 'A' Delete 'A'
|
||||
|
||||
Alignment:
|
||||
"AGTACGCA"
|
||||
"--TATGC-"
|
||||
@@ -0,0 +1,607 @@
|
||||
use std::ops::Range;
|
||||
|
||||
/// a vec like struct, where everything is ever increasing and not by anything more than one.
|
||||
///
|
||||
/// so you can have 1, 2, 3, 4, 5 but not 0, 1, 1, 1, 3
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct DB {
|
||||
/// inner starts from index 0 but inner\[0\] is the point where DB::vec is 1
|
||||
inner: Vec<u32>,
|
||||
len: u32,
|
||||
}
|
||||
|
||||
impl DB {
|
||||
fn verify_increasing(&self) {
|
||||
assert!(
|
||||
matches!(
|
||||
self.inner.iter().try_fold(&u32::MIN, |lastele, current| {
|
||||
if current > lastele {
|
||||
Some(current)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
Some(_)
|
||||
), // what the fuck is this
|
||||
"the inner vec should be ever increasing, which it is not"
|
||||
);
|
||||
}
|
||||
fn verify_len(&self) {
|
||||
let selflen = self.len();
|
||||
assert!(self.inner.last().unwrap_or(&0) < &selflen
|
||||
&& !self.inner.iter().any(|f| f >= &selflen),
|
||||
|
||||
"the inner vector elements denote at what indexes the DB::vec(&self) vec value jumps up by one, and so any inner elements should not exceed self.len(), which some of them do");
|
||||
}
|
||||
fn verify(&self) {
|
||||
self.verify_len();
|
||||
self.verify_increasing();
|
||||
}
|
||||
fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
fn with_len(len: u32) -> Self {
|
||||
Self {
|
||||
len,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
fn push(&mut self, val: u32) {
|
||||
let last = self.last().unwrap_or_default();
|
||||
if val == last + 1 {
|
||||
self.inner.push(self.len());
|
||||
self.len += 1;
|
||||
} else if val == last {
|
||||
self.len += 1;
|
||||
} else {
|
||||
panic!("trying value {val} is not equal or one bigger than current last {last}");
|
||||
}
|
||||
}
|
||||
fn last(&self) -> Option<u32> {
|
||||
if self.len() > 0 {
|
||||
Some(self.inner.len() as _)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn pop(&mut self) -> Option<u32> {
|
||||
let returnvalue = self.last();
|
||||
if let Some(_) = returnvalue {
|
||||
if let Some(bro) = self.inner.last() {
|
||||
if self.len() - bro == 1 {
|
||||
self.inner.pop();
|
||||
} else if self.len() < *bro {
|
||||
panic!("run DB::verify_len(&self) ")
|
||||
}
|
||||
self.len -= 1;
|
||||
} else {
|
||||
// self.len.checked_sub(1);
|
||||
self.len -= 1
|
||||
}
|
||||
}
|
||||
return returnvalue;
|
||||
}
|
||||
fn len(&self) -> u32 {
|
||||
self.len
|
||||
}
|
||||
/// at looks the same as [`DB::vec`](DB::vec)(&self).[`get`](core::slice::get)(ind as usize)
|
||||
fn get(&self, ind: u32) -> Option<u32> {
|
||||
if self.len() <= ind {
|
||||
// panic!("index {ind} >= len {selflen} which is ugly")
|
||||
return None;
|
||||
}
|
||||
self.inner
|
||||
.iter()
|
||||
.rposition(|f| ind >= *f) // imagine got 7 > 4, and 4 is at index 2, so the value of 7 is 2
|
||||
.map(|c| c as u32 + 1) // hack
|
||||
.or(Some(0))
|
||||
}
|
||||
fn range_of(&self, ele: u32) -> Option<Range<u32>> {
|
||||
if ele == 0 {
|
||||
Some(0..*self.inner.get(0).unwrap_or(&self.len()))
|
||||
} else if ele > self.last().unwrap_or_default() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
*self.inner.get(ele as usize - 1).unwrap_or(&self.len())
|
||||
..*self.inner.get(ele as usize).unwrap_or(&self.len()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// the same with range of we have
|
||||
|
||||
///index can be numbers in output.0, and output.1 tell you to select the bigger number at .0.1
|
||||
///
|
||||
/// output: (two numbers that can be, can be the same), (should be the other number; should be appending)
|
||||
///
|
||||
/// must check for in len() range by yourself
|
||||
fn available_values(&self, ind: u32) -> (Option<[u32; 2]>, Option<bool>) {
|
||||
// let mut last_ind: u32 = 0;
|
||||
for (&cur_ind, cur_val) in // ([0].iter()).chain
|
||||
(self.inner.iter()).chain([self.len()].iter()).zip(1u32..)
|
||||
{
|
||||
// exactly at 3 == 3
|
||||
if ind == cur_ind {
|
||||
// bug if vec[0] = 0 // no more
|
||||
// if cur_val == 0 {
|
||||
// // at 0 where there is nothing before it
|
||||
// return (Some([0, 0]), None);
|
||||
// } else {
|
||||
// at exactly eg 3, 8, 49, or the end where you can have another
|
||||
// end
|
||||
let choose = if cur_val >= self.inner.len() as _
|
||||
|| cur_ind + 1 < self.inner[cur_val as usize]
|
||||
// not immediate
|
||||
{
|
||||
Some(true)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
return (Some([cur_val - 1, cur_val]), choose);
|
||||
// }
|
||||
} else if ind + 1 == cur_ind {
|
||||
// right before a number you can change the value and it is still ever increasing
|
||||
// not immediate (not sandwiched)
|
||||
// if cur_val - 2 passes then cur_val is not self.inner.len() (??)
|
||||
let choose = if (cur_val - 1)
|
||||
.checked_sub(1)
|
||||
.and_then(|c| self.inner.get(c as usize))
|
||||
.map(|c| *c < ind)
|
||||
.unwrap_or(0 < ind)
|
||||
|| cur_ind == self.len()
|
||||
// end
|
||||
{
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
return (Some([cur_val - 1, cur_val]), choose);
|
||||
} else if ind < cur_ind {
|
||||
// at the first instance where cur_ind > ind is where you know we have crossed it
|
||||
// also it passed the == and -1 check.
|
||||
// also it cant be bigger than cur_ind making it the last ind actually
|
||||
// so we use the last val that corresponds
|
||||
return (Some([cur_val - 1, cur_val - 1]), None);
|
||||
}
|
||||
// last_ind = cur_ind;
|
||||
}
|
||||
|
||||
(None, None)
|
||||
}
|
||||
|
||||
fn change(&mut self, ind: u32, val: u32) {
|
||||
let (avail, up) = self.available_values(ind);
|
||||
if let (Some(avail), Some(up)) = (avail, up) {
|
||||
if val == avail[0] && up {
|
||||
if self.inner.len() == val as _ {
|
||||
self.inner.push(ind);
|
||||
} else {
|
||||
self.inner.get_mut(val as usize).map(|e| *e += 1);
|
||||
};
|
||||
// } else if val == avail[0] && !up {
|
||||
// self.inner.get_mut(val as usize).map(|e| *e -= 1);
|
||||
} else if val == avail[1] && !up {
|
||||
self.inner
|
||||
.get_mut(avail[0] as usize)
|
||||
.map(|e| *e -= 1)
|
||||
.unwrap_or_else(|| self.inner.push(ind));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn vec(&self) -> Vec<u32> {
|
||||
let mut count = (0..).into_iter();
|
||||
self.inner
|
||||
.iter()
|
||||
.chain([self.len()].iter())
|
||||
.scan(0u32, |c, f| {
|
||||
let r = Some(vec![count.next().unwrap(); (*f - *c) as usize]);
|
||||
*c = *f;
|
||||
return r;
|
||||
})
|
||||
.flatten()
|
||||
.collect()
|
||||
}
|
||||
fn try_from_vec(v: Vec<u32>) -> Option<Self> {
|
||||
// let mut count = (0..).into_iter();
|
||||
let len = v.len() as _;
|
||||
let mut inner: Vec<u32> = vec![];
|
||||
let mut c = 0u32;
|
||||
for (i, f) in v.iter().enumerate() {
|
||||
if c + 1 == *f {
|
||||
inner.push(i as _);
|
||||
} else if c + 1 < *f || c > *f {
|
||||
return None;
|
||||
};
|
||||
c = *f;
|
||||
}
|
||||
Some(Self { inner, len })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::DB;
|
||||
#[test]
|
||||
fn db_to_vec() {
|
||||
let c = vec![0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4];
|
||||
let ctodb = vec![4, 8, 12, 14];
|
||||
let clen = 16;
|
||||
assert_eq!(clen as usize, c.len());
|
||||
let ctodb = DB {
|
||||
inner: ctodb,
|
||||
len: clen,
|
||||
};
|
||||
ctodb.verify();
|
||||
assert_eq!(ctodb.vec(), c);
|
||||
}
|
||||
#[test]
|
||||
fn pop_and_get() {
|
||||
let ctodb = vec![4, 8, 12, 14];
|
||||
let clen = 17;
|
||||
let mut db = DB {
|
||||
inner: ctodb,
|
||||
len: clen,
|
||||
};
|
||||
assert_eq!(db.get(4), Some(1));
|
||||
assert_eq!(db.get(12), Some(3));
|
||||
assert_eq!(db.get(18), None);
|
||||
assert_eq!(db.get(0), Some(0));
|
||||
assert_eq!(db.get(17), None);
|
||||
assert_eq!(db.get(16), Some(4));
|
||||
// assert_eq!(db.pop(), Some(4));
|
||||
|
||||
// println!("len:{} inner: {:?} vec: {:?}",db.len(), db.inner, db.vec());
|
||||
// while let Some(_) = db.pop() {
|
||||
// println!("len:{} inner: {:?} vec: {:?}",db.len(), db.inner, db.vec());
|
||||
|
||||
// };
|
||||
let mut vec = db.vec();
|
||||
while db.len() > 0 {
|
||||
assert_eq!(db.pop(), vec.pop())
|
||||
}
|
||||
assert_eq!(db.pop(), vec.pop());
|
||||
assert_eq!(db.len(), 0);
|
||||
}
|
||||
#[test]
|
||||
fn last() {
|
||||
let db = DB::new();
|
||||
assert_eq!(db.len(), 0);
|
||||
assert!(matches!(db.last(), None));
|
||||
|
||||
let db = DB::with_len(1);
|
||||
assert!(matches!(db.last(), Some(0)));
|
||||
|
||||
// assert!(db.pop() == 0);
|
||||
// assert_eq!(db.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn range_of() {
|
||||
let ctodb = vec![4, 7, 9, 12, 15, 23, 27, 31, 38, 41];
|
||||
let clen = 49;
|
||||
let mut db = DB {
|
||||
inner: ctodb,
|
||||
len: clen,
|
||||
};
|
||||
assert_eq!(db.range_of(0), Some(0..4));
|
||||
assert_eq!(db.range_of(1), Some(4..7));
|
||||
assert_eq!(db.range_of(11), None);
|
||||
assert_eq!(db.range_of(10), Some(41..clen));
|
||||
assert_eq!(db.pop(), Some(10));
|
||||
assert_eq!(db.range_of(10), Some(41..clen - 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push() {
|
||||
let mut db = DB::new();
|
||||
let mut c = vec![];
|
||||
let mut push = |i| {
|
||||
db.push(i);
|
||||
c.push(i);
|
||||
};
|
||||
for _ in 0..6 {
|
||||
push(0);
|
||||
}
|
||||
for _ in 0..3 {
|
||||
push(1);
|
||||
}
|
||||
for _ in 0..5 {
|
||||
push(2);
|
||||
}
|
||||
for _ in 0..2 {
|
||||
push(3);
|
||||
}
|
||||
for _ in 0..1 {
|
||||
push(4);
|
||||
}
|
||||
assert_eq!(db.vec(), c)
|
||||
}
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn invalid_push() {
|
||||
let mut db = DB::new();
|
||||
// dbg!(&db.inner);
|
||||
db.push(1);
|
||||
// dbg!(&db.inner);
|
||||
for _ in 3..=11 {
|
||||
db.push(1)
|
||||
}
|
||||
|
||||
// dbg!(&db.inner);
|
||||
// dbg!(db.vec());
|
||||
db.push(2);
|
||||
dbg!(db.len() != 0);
|
||||
db.push(4);
|
||||
}
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn invalid_push_2() {
|
||||
let mut db = DB::new();
|
||||
// dbg!(&db.inner);
|
||||
|
||||
db.push(0);
|
||||
db.push(1);
|
||||
// dbg!(&db.inner);
|
||||
// dbg!(db.vec());
|
||||
db.push(2);
|
||||
dbg!(db.len() != 0);
|
||||
db.push(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn change() {
|
||||
let mut c = vec![0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4];
|
||||
let ctodb = vec![4, 8, 12, 14];
|
||||
|
||||
let mut ctodb = DB {
|
||||
inner: ctodb,
|
||||
len: c.len() as _,
|
||||
};
|
||||
let mut change = |i, v| {
|
||||
ctodb.change(i, v);
|
||||
c[i as usize] = v;
|
||||
};
|
||||
change(13, 3);
|
||||
change(3, 1);
|
||||
change(7, 2);
|
||||
|
||||
assert_eq!(ctodb.inner, DB::try_from_vec(c).unwrap().inner)
|
||||
}
|
||||
#[test]
|
||||
fn from_vec() {
|
||||
let c = vec![0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4];
|
||||
let ctodb = vec![4, 8, 12, 14];
|
||||
|
||||
let ctodb = DB {
|
||||
inner: ctodb,
|
||||
len: c.len() as _,
|
||||
};
|
||||
let c2 = DB::try_from_vec(c).unwrap();
|
||||
assert_eq!(ctodb.inner, c2.inner);
|
||||
assert_eq!(ctodb.len, c2.len);
|
||||
}
|
||||
#[test]
|
||||
fn avail() {
|
||||
let c = vec![0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4];
|
||||
let ctodb = vec![4, 8, 12, 14];
|
||||
|
||||
let ctodb = DB {
|
||||
inner: ctodb,
|
||||
len: c.len() as _,
|
||||
};
|
||||
assert_eq!(ctodb.available_values(3), (Some([0, 1]), Some(false)));
|
||||
assert_eq!(ctodb.available_values(7), (Some([1, 2]), Some(false)));
|
||||
assert_eq!(ctodb.available_values(13), (Some([3, 4]), Some(false)));
|
||||
|
||||
assert_eq!(ctodb.available_values(0), (Some([0, 0]), None));
|
||||
assert_eq!(ctodb.available_values(4), (Some([0, 1]), Some(true)));
|
||||
assert_eq!(ctodb.available_values(11), (Some([2, 3]), Some(false)));
|
||||
assert_eq!(ctodb.available_values(12), (Some([2, 3]), Some(true)));
|
||||
assert_eq!(ctodb.available_values(15), (Some([4, 5]), Some(false)));
|
||||
assert_eq!(ctodb.available_values(16), (Some([4, 5]), Some(true)));
|
||||
assert_eq!(ctodb.available_values(17), (None, None));
|
||||
}
|
||||
#[test]
|
||||
fn avail_hard() {
|
||||
let c = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13];
|
||||
let db = DB::try_from_vec(c).unwrap();
|
||||
assert_eq!(db.available_values(0), (Some([0, 1]), None));
|
||||
assert_eq!(db.available_values(1), (Some([1, 2]), None));
|
||||
assert_eq!(db.available_values(11), (Some([11, 12]), None));
|
||||
assert_eq!(db.available_values(12), (Some([12, 13]), Some(true)));
|
||||
assert_eq!(db.available_values(13), (Some([13, 13]), None));
|
||||
assert_eq!(db.available_values(15), (Some([13, 13]), None));
|
||||
assert_eq!(db.available_values(16), (Some([13, 14]), Some(false)));
|
||||
assert_eq!(db.available_values(17), (Some([13, 14]), Some(true)));
|
||||
}
|
||||
#[test]
|
||||
fn change_hard() {
|
||||
let mut c = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13];
|
||||
let mut db = DB::try_from_vec(c.clone()).unwrap();
|
||||
let change = |d: &mut DB, c: &mut Vec<u32>, i, v| {
|
||||
d.change(i, v);
|
||||
c[i as usize] = v;
|
||||
};
|
||||
|
||||
change(&mut db, &mut c, 12, 12);
|
||||
change(&mut db, &mut c, 16, 14);
|
||||
{
|
||||
println!("f: {c:?}");
|
||||
assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
||||
}
|
||||
|
||||
change(&mut db, &mut c, 13, 12);
|
||||
change(&mut db, &mut c, 14, 12);
|
||||
change(&mut db, &mut c, 11, 11);
|
||||
change(&mut db, &mut c, 12, 11);
|
||||
change(&mut db, &mut c, 13, 11);
|
||||
change(&mut db, &mut c, 10, 10);
|
||||
change(&mut db, &mut c, 11, 10);
|
||||
change(&mut db, &mut c, 12, 10);
|
||||
change(&mut db, &mut c, 9, 9);
|
||||
change(&mut db, &mut c, 10, 9);
|
||||
{
|
||||
println!("m: {:?}", db);
|
||||
print!("{c:?}");
|
||||
println!(", {:?}", DB::try_from_vec(c.clone()).unwrap().vec());
|
||||
}
|
||||
change(&mut db, &mut c, 11, 9);
|
||||
change(&mut db, &mut c, 8, 8);
|
||||
change(&mut db, &mut c, 9, 8);
|
||||
change(&mut db, &mut c, 10, 8);
|
||||
change(&mut db, &mut c, 7, 7);
|
||||
change(&mut db, &mut c, 8, 7);
|
||||
// change(&mut db, &mut c, 9, 7);
|
||||
{
|
||||
println!("m: {:?}", db);
|
||||
print!("{c:?}");
|
||||
println!(", {:?}", DB::try_from_vec(c.clone()).unwrap().vec());
|
||||
}
|
||||
change(&mut db, &mut c, 6, 6);
|
||||
change(&mut db, &mut c, 7, 6);
|
||||
// change(&mut db, &mut c, 8, 6);
|
||||
change(&mut db, &mut c, 5, 5);
|
||||
change(&mut db, &mut c, 6, 5);
|
||||
// change(&mut db, &mut c, 7, 5);
|
||||
change(&mut db, &mut c, 4, 4);
|
||||
change(&mut db, &mut c, 5, 4);
|
||||
// change(&mut db, &mut c, 6, 4);
|
||||
change(&mut db, &mut c, 3, 3);
|
||||
change(&mut db, &mut c, 4, 3);
|
||||
// change(&mut db, &mut c, 5, 3);
|
||||
change(&mut db, &mut c, 2, 2);
|
||||
change(&mut db, &mut c, 3, 2);
|
||||
// change(&mut db, &mut c, 4, 2);
|
||||
change(&mut db, &mut c, 1, 1);
|
||||
// change(&mut db, &mut c, 2, 1);
|
||||
// change(&mut db, &mut c, 3, 1);
|
||||
change(&mut db, &mut c, 0, 0);
|
||||
// change(&mut db, &mut c, 1, 0);
|
||||
// change(&mut db, &mut c, 2, 0);
|
||||
{
|
||||
let db2 = DB::try_from_vec(c.clone()).unwrap();
|
||||
println!("e: {c:?}, {:?}", db2.vec());
|
||||
println!("{:?}", db);
|
||||
assert_eq!(db, db2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // [0,0,0,1,1,1,2,2,3] 9
|
||||
// // 0,1,2,3,4,5,6,7,8
|
||||
// // [ 3, 6, 8]
|
||||
// fn change(&mut self, ind: u32, to: u32) {
|
||||
// // change means that the index is valid: 0..self.len(), if anything other than that crash
|
||||
// let Some(vec_ind_plus_one) = self.get(ind) else {
|
||||
// panic!("index not cool")
|
||||
// };
|
||||
// // vec_ind_plus_one is from 1 to self.inner.len(),
|
||||
// // // index is valid
|
||||
// let last_ = self.inner.len() as u32; // last element == last index + 1
|
||||
// assert!(if last_ == 0 {
|
||||
// vec_ind_plus_one == 0
|
||||
// } else {
|
||||
// vec_ind_plus_one <= last_
|
||||
// });
|
||||
// // // panic if to is too big
|
||||
// if to > last_ + 1 {
|
||||
// panic!("pushing something too big: {to} is way big compared to biggest number {last_}")
|
||||
// }
|
||||
// // // to is now ok
|
||||
// assert!(to <= last_ + 1);
|
||||
// // // if vec has 0 size, all cases
|
||||
// if last_ == 0 {
|
||||
// if to == 0 {
|
||||
// return;
|
||||
// } else if to != 1 {
|
||||
// panic!("{to} way bigger than {vec_ind_plus_one} which is not cool")
|
||||
// }
|
||||
|
||||
// // everything is 0, index is valid
|
||||
// self.inner.push(ind);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// assert_ne!(vec_ind_plus_one, 0);
|
||||
// assert_ne!(last_, 0);
|
||||
|
||||
// // vec[vec_ind] is going to be the first number that we care about
|
||||
// let vec_ind = vec_ind_plus_one - 1;
|
||||
// let ind_this = self.inner[vec_ind as usize];
|
||||
// assert!(ind_this <= ind);
|
||||
// let Some(&ind_next) = self.inner.get(vec_ind_plus_one as usize) else {
|
||||
// // ind is in range of ind_this..self.len()
|
||||
// assert_eq!(ind_this, last_);
|
||||
// // if to == vec_ind + 1 {
|
||||
// // // this is the case here
|
||||
// // }
|
||||
// if ind == self.len() - 1 && to == last_ + 1 {
|
||||
// self.inner.push(ind);
|
||||
// return;
|
||||
// }
|
||||
// // if to > last_ + 1 {
|
||||
// // panic!("uh we done this before")
|
||||
// // }
|
||||
// else if to == last_ - 1 && ind_this == ind {
|
||||
// // if let Some(c) = self.inner.last_mut() {
|
||||
// // *c += 1;
|
||||
// // }
|
||||
// // else {
|
||||
// // unreachable!()
|
||||
// // }
|
||||
// // or
|
||||
// self.inner[to as usize] += 1;
|
||||
// return;
|
||||
// } else if !(to == last_ && ind_this < ind) {
|
||||
// panic!("ever increasing vec")
|
||||
// }
|
||||
// return;
|
||||
// };
|
||||
|
||||
// assert!(ind < ind_next);
|
||||
// let ideal_to = vec_ind_plus_one;
|
||||
|
||||
// if to == ideal_to && (ind_this..ind_next).contains(&ind) {
|
||||
// return;
|
||||
// } else if to == ideal_to + 1 && ind == ind_next - 1 {
|
||||
// self.inner[to as usize] -= 1;
|
||||
// return;
|
||||
// } else if ind_this > 0 {
|
||||
// }
|
||||
|
||||
// // // vec is NOT 0 size now
|
||||
// // // let &last_changing_index = self
|
||||
// // // .inner
|
||||
// // // .last()
|
||||
// // // .expect("somehow this panics; self.inner.len() != 0");
|
||||
|
||||
// // // for the range of the last element (DB::vec from first element == last_ to end)
|
||||
|
||||
// // // if ind is strictly bigger than inner.last() and to is equal to last_
|
||||
// // // if ind > last_changing_index && to == last_ {
|
||||
// // // self.inner.push(ind);
|
||||
// // // return;
|
||||
// // // }
|
||||
|
||||
// // //literally the last element
|
||||
|
||||
// // // if to is 0
|
||||
// // // and vec is not 0, so vec[0] has to exist
|
||||
// // if to == 0 {
|
||||
// // // if nothing
|
||||
// // if ind < self.inner[0] {
|
||||
// // return;
|
||||
// // }
|
||||
// // if ind == self.inner[0] {
|
||||
// // self.inner[0] += 1;
|
||||
// // return;
|
||||
// // }
|
||||
// // }
|
||||
// // // if to is not 0,
|
||||
// // else if true {
|
||||
// // }
|
||||
|
||||
// // return;
|
||||
// }
|
||||
@@ -0,0 +1,68 @@
|
||||
mod db;
|
||||
|
||||
pub fn lcs_gen(str1: &str, str2: &str) -> Vec<Vec<u32>> {
|
||||
let c1: Vec<char> = str1.chars().collect();
|
||||
let c1len = c1.len();
|
||||
let c2: Vec<char> = str2.chars().collect();
|
||||
let c2len = c2.len();
|
||||
let mut db: Vec<Vec<u32>> = vec![vec![0; c2len + 1]; c1len + 1];
|
||||
if c1len * c2len == 0 {
|
||||
// for i in &db {
|
||||
// println!("{i:?}")
|
||||
// }
|
||||
return db;
|
||||
}
|
||||
for i in 1..=c1len {
|
||||
for j in 1..=c2len {
|
||||
if c1[i - 1] == c2[j - 1] {
|
||||
db[i][j] = db[i - 1][j - 1] + 1;
|
||||
} else {
|
||||
db[i][j] = db[i][j - 1].max(db[i - 1][j])
|
||||
}
|
||||
}
|
||||
}
|
||||
// for i in &db {
|
||||
// println!("{i:?}")
|
||||
// }
|
||||
db
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::lcs_gen;
|
||||
#[test]
|
||||
fn test_normal_case() {
|
||||
lcs_gen("asjhdgasdhj", "gajhdgashjd");
|
||||
// lcs_gen("", "");
|
||||
}
|
||||
#[test]
|
||||
|
||||
fn test_wiki() {
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// ε M Z J A W X U
|
||||
// 0 ε 0 0 0 0 0 0 0 0
|
||||
// 1 X 0 0 0 0 0 0 1 1
|
||||
// 2 M 0 1 1 1 1 1 1 1
|
||||
// 3 J 0 1 1 2 2 2 2 2
|
||||
// 4 Y 0 1 1 2 2 2 2 2
|
||||
// 5 A 0 1 1 2 3 3 3 3
|
||||
// 6 U 0 1 1 2 3 3 3 4
|
||||
// 7 Z 0 1 2 2 3 3 3 4
|
||||
|
||||
let s = vec![
|
||||
vec![0, 0, 0, 0, 0, 0, 0, 0],
|
||||
vec![0, 0, 0, 0, 0, 0, 1, 1],
|
||||
vec![0, 1, 1, 1, 1, 1, 1, 1],
|
||||
vec![0, 1, 1, 2, 2, 2, 2, 2],
|
||||
vec![0, 1, 1, 2, 2, 2, 2, 2],
|
||||
vec![0, 1, 1, 2, 3, 3, 3, 3],
|
||||
vec![0, 1, 1, 2, 3, 3, 3, 4],
|
||||
vec![0, 1, 2, 2, 3, 3, 3, 4],
|
||||
];
|
||||
assert_eq!(lcs_gen("XMJYAUZ", "MZJAWXU"), s)
|
||||
}
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
lcs_gen("", "");
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
@@ -1,9 +1,11 @@
|
||||
//! # Generalized Levenshtein Distance
|
||||
//! This is a simple generalized Levenshtein Distance implementation.
|
||||
//!
|
||||
//! very much breaking btw
|
||||
|
||||
/// costs for different edit operations
|
||||
///
|
||||
/// each with the letters involved: so you can further tweak the cost in ur own [`CustomCost`]s impl
|
||||
/// each with the elements involved: so you can further tweak the cost in ur own [`CustomCost`]s impl
|
||||
/// position? idk
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum EditOperation<T> {
|
||||
@@ -70,11 +72,7 @@ impl<T> From<&EditOperation<T>> for MiniEditOperation {
|
||||
}
|
||||
}
|
||||
trait ToEditOperation {
|
||||
fn full<T>(
|
||||
&self,
|
||||
maybe_s1: Option<T>,
|
||||
maybe_s2: Option<T>,
|
||||
) -> Result<EditOperation<T>,()>;
|
||||
fn full<T>(&self, maybe_s1: Option<T>, maybe_s2: Option<T>) -> Result<EditOperation<T>, ()>;
|
||||
}
|
||||
|
||||
impl ToEditOperation for MiniEditOperation {
|
||||
@@ -342,12 +340,8 @@ pub fn edit_sequence<T: Clone>(
|
||||
}
|
||||
}
|
||||
funny.push(
|
||||
MiniEditOperation::full(
|
||||
&op.operation,
|
||||
seq1.get(i).cloned(),
|
||||
seq2.get(j).cloned(),
|
||||
)
|
||||
.unwrap(),
|
||||
MiniEditOperation::full(&op.operation, seq1.get(i).cloned(), seq2.get(j).cloned())
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -355,7 +349,8 @@ pub fn edit_sequence<T: Clone>(
|
||||
funny
|
||||
}
|
||||
|
||||
pub fn generate_alignment<T: Clone + Debug>(
|
||||
// bye
|
||||
fn _generate_alignment<T: Clone + Debug>(
|
||||
operations: &[Vec<Option<CostOperation<EditOperation<T>>>>],
|
||||
) -> (Vec<T>, Vec<T>) {
|
||||
let mut aligned_seq1 = Vec::new();
|
||||
@@ -398,7 +393,7 @@ pub fn generate_alignment<T: Clone + Debug>(
|
||||
/// calculate distance, also get u the [`edit_sequence`]
|
||||
/// use this one
|
||||
///
|
||||
/// what this does is call this ass [`levenshtein_with_operations`] and then the [`edit_sequence`] from the generated dp table
|
||||
/// what this does is call this ass [`generalized_levenshtein`] and then the [`edit_sequence`] from the generated dp table
|
||||
pub fn levenstein_distance<T: PartialEq + Clone + Debug>(
|
||||
seq1: &[T],
|
||||
seq2: &[T],
|
||||
|
||||
+5
-14
@@ -94,7 +94,7 @@ pub fn levenshtein_with_operations(
|
||||
) -> (i32, Vec<Vec<CostOperation>>) {
|
||||
let chars1: Vec<char> = str1.chars().collect();
|
||||
let chars2: Vec<char> = str2.chars().collect();
|
||||
let len1: usize = chars1.len();
|
||||
let len1 = chars1.len();
|
||||
let len2 = chars2.len();
|
||||
let mut dp = vec![
|
||||
vec![
|
||||
@@ -193,22 +193,15 @@ pub fn edit_sequence(dp: &[Vec<CostOperation>]) -> Vec<EditOperation> {
|
||||
|
||||
while i > 0 || j > 0 {
|
||||
if let Some(operation) = &dp[i][j].operation {
|
||||
funny.push(*operation);
|
||||
match operation {
|
||||
EditOperation::Insert { .. } => {
|
||||
funny.push(*operation);
|
||||
j -= 1;
|
||||
}
|
||||
EditOperation::Delete { .. } => {
|
||||
funny.push(*operation);
|
||||
i -= 1;
|
||||
}
|
||||
EditOperation::Substitute { .. } => {
|
||||
funny.push(*operation);
|
||||
i -= 1;
|
||||
j -= 1;
|
||||
}
|
||||
EditOperation::Match { .. } => {
|
||||
funny.push(*operation);
|
||||
EditOperation::Substitute { .. } | EditOperation::Match { .. } => {
|
||||
i -= 1;
|
||||
j -= 1;
|
||||
}
|
||||
@@ -221,9 +214,7 @@ pub fn edit_sequence(dp: &[Vec<CostOperation>]) -> Vec<EditOperation> {
|
||||
|
||||
/// alignment
|
||||
/// is ass dont use
|
||||
pub fn generate_alignment(
|
||||
operations: &[Vec<CostOperation>],
|
||||
) -> (String, String) {
|
||||
pub fn generate_alignment(operations: &[Vec<CostOperation>]) -> (String, String) {
|
||||
let mut aligned_str1 = String::new();
|
||||
let mut aligned_str2 = String::new();
|
||||
|
||||
@@ -507,4 +498,4 @@ mod tests {
|
||||
assert_eq!(aligned_str1, "test");
|
||||
assert_eq!(aligned_str2, "test");
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -3,7 +3,7 @@ use lda_strdist::{
|
||||
generate_alignment, levenshtein_with_operations, levenstein_distance, reconstruct_from,
|
||||
reconstruct_to, EditCost,
|
||||
},
|
||||
wrapper_::EditOperationVec,
|
||||
wrapper_::{EditOperationVec, CostOperationVec},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
@@ -24,6 +24,10 @@ fn main() {
|
||||
|
||||
let (d2, dp) = levenshtein_with_operations(str1, str2, &EditCost::default());
|
||||
assert!(d2 == distance);
|
||||
println!("this is the d");
|
||||
for i in &dp {
|
||||
println!("{}", CostOperationVec(i))
|
||||
}
|
||||
let (al1, al2) = generate_alignment(&dp);
|
||||
println!("Alignment:\n{:#?}\n{:#?}", al1, al2);
|
||||
}
|
||||
+45
-2
@@ -5,8 +5,51 @@ pub struct EditOperationVec<'e>(pub &'e Vec<EditOperation>);
|
||||
impl std::fmt::Display for EditOperationVec<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for (i, op) in self.0.iter().enumerate() {
|
||||
writeln!(f, "Step {}: {}", i + 1, op)?;
|
||||
writeln!(f, "Step {}: {}\t", i + 1, op)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use crate::levenshtein::CostOperation;
|
||||
|
||||
pub struct CostOperationVec<'e>(pub &'e Vec<CostOperation>);
|
||||
|
||||
impl std::fmt::Display for CostOperationVec<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let tab_len = 4; // do not be 0
|
||||
debug_assert_ne!(tab_len, 0);
|
||||
let mut indexprinter: Vec<String> = Vec::new();
|
||||
let mut costprint: Vec<String> = Vec::new();
|
||||
let mut operationprint: Vec<String> = Vec::new();
|
||||
for (ind, c) in self.0.iter().enumerate() {
|
||||
let (cost, op) = (c.cost, c.operation);
|
||||
let mut strind = ind.to_string();
|
||||
let mut strcost = cost.to_string();
|
||||
let mut strop = match op {
|
||||
Some(c) => c.to_string(),
|
||||
None => "bih".to_string(),
|
||||
};
|
||||
let longest = strind.len().max(strcost.len()).max(strop.len());
|
||||
let tabl = (longest + tab_len - 1) / tab_len; // these two lines
|
||||
let longer = tabl * tab_len + tab_len - 1; // work so idc
|
||||
let tabind = (longer - strind.len()) / tab_len;
|
||||
let tabcost = (longer - strcost.len()) / tab_len;
|
||||
let tabop = (longer - strop.len()) / tab_len;
|
||||
strind.push_str(&"\t".repeat(tabind));
|
||||
strcost.push_str(&"\t".repeat(tabcost));
|
||||
strop.push_str(&"\t".repeat(tabop));
|
||||
indexprinter.push(strind);
|
||||
costprint.push(strcost);
|
||||
operationprint.push(strop);
|
||||
}
|
||||
indexprinter.iter().try_for_each(|c| write!(f, "{c}"))?;
|
||||
writeln!(f)?;
|
||||
costprint.iter().try_for_each(|c| write!(f, "{c}"))?;
|
||||
writeln!(f)?;
|
||||
operationprint.iter().try_for_each(|c| write!(f, "{c}"))?;
|
||||
writeln!(f)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user