what am i doing

This commit is contained in:
lda committed 2025-01-20 11:02:27 +07:00
1 parent af82016d1c
commit fbd6cff526
8 files changed
+795 -31

No files matched your search

+56
View File
@@ -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-"
+607
View File
@@ -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;
// }
+68
View File
@@ -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("", "");
}
}
View File
Whitespace-only changes.
+9 -14
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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(())
}
}