Compare commits
2
Commits
No files matched your search
@@ -4,3 +4,5 @@ version = "0.0.1"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
lda_ansi = { version = "0.0.1", path = "../lda_ansi" }
|
||||||
|
|
||||||
@@ -92,6 +92,7 @@ impl DB {
|
|||||||
Some(return_value)
|
Some(return_value)
|
||||||
}
|
}
|
||||||
/// Retrieves the value at a given index.
|
/// Retrieves the value at a given index.
|
||||||
|
///
|
||||||
/**
|
/**
|
||||||
get you know get it like its a traditional long ass vec
|
get you know get it like its a traditional long ass vec
|
||||||
|
|
||||||
@@ -102,12 +103,10 @@ impl DB {
|
|||||||
DB::vec(dp).get(ind as usize);
|
DB::vec(dp).get(ind as usize);
|
||||||
# }
|
# }
|
||||||
|
|
||||||
# fn main() {
|
|
||||||
let c = [0, 1, 1, 2, 3, 3, 3, 4, 4].to_vec();
|
let c = [0, 1, 1, 2, 3, 3, 3, 4, 4].to_vec();
|
||||||
let dp = DB::try_from_vec(c.clone()).expect("source vector with wrong form");
|
let dp = DB::try_from_vec(c.clone()).expect("source vector with wrong form");
|
||||||
let ind = 5;
|
let ind = 5;
|
||||||
assert_eq!(DB::vec(&dp).get(ind as usize).cloned(), dp.get(ind));
|
assert_eq!(DB::vec(&dp).get(ind as usize).cloned(), dp.get(ind));
|
||||||
# }
|
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
pub fn get(&self, ind: u32) -> Option<u32> {
|
pub fn get(&self, ind: u32) -> Option<u32> {
|
||||||
@@ -256,414 +255,4 @@ impl DB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// working as intended: i am happy
|
mod test;
|
||||||
#[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,
|
|
||||||
};
|
|
||||||
assert!(ctodb.validate().is_ok());
|
|
||||||
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!(db.last().is_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).unwrap();
|
|
||||||
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).unwrap();
|
|
||||||
// dbg!(&db.inner);
|
|
||||||
for _ in 3..=11 {
|
|
||||||
db.push(1).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// dbg!(&db.inner);
|
|
||||||
// dbg!(db.vec());
|
|
||||||
db.push(2).unwrap();
|
|
||||||
dbg!(db.len() != 0);
|
|
||||||
assert!(db.push(4).is_err());
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
// #[should_panic]
|
|
||||||
fn invalid_push_2() {
|
|
||||||
let mut db = DB::new();
|
|
||||||
// dbg!(&db.inner);
|
|
||||||
|
|
||||||
db.push(0).unwrap();
|
|
||||||
db.push(1).unwrap();
|
|
||||||
// dbg!(&db.inner);
|
|
||||||
// dbg!(db.vec());
|
|
||||||
db.push(2).unwrap();
|
|
||||||
dbg!(db.len() != 0);
|
|
||||||
assert!(db.push(1).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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 = [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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn change_harder() {
|
|
||||||
let mut c = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 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;
|
|
||||||
};
|
|
||||||
{
|
|
||||||
println!("f: {c:?}");
|
|
||||||
assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
change(&mut db, &mut c, 12, 12);
|
|
||||||
println!("m: {:?}", db);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn prop_idk() {
|
|
||||||
let 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();
|
|
||||||
dbg!(&mut db).propagate_to_end(2, 2);
|
|
||||||
dbg!(&db);
|
|
||||||
println!("{:?}", db.vec());
|
|
||||||
assert_eq!(db.inner, vec![0, 1]);
|
|
||||||
let mut db = DB::try_from_vec(c.clone()).unwrap();
|
|
||||||
db.propagate_to_end(2, 3);
|
|
||||||
println!("{:?}", db.vec());
|
|
||||||
assert_eq!(db.inner, vec![0, 1, 2]);
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn prop() {
|
|
||||||
let base = [
|
|
||||||
0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 12, 13,
|
|
||||||
14, 15, 16, 17, 17, 18, 18, 18, 18, 18, 19, 20, 21, 21, 21, 21, 22, 23, 23, 24, 25, 26,
|
|
||||||
26, 26,
|
|
||||||
];
|
|
||||||
|
|
||||||
let prop = |bd: &mut DB, cc: &mut Vec<u32>, i, v: u32| {
|
|
||||||
cc.get_mut(i as usize..).unwrap().fill(v);
|
|
||||||
bd.propagate_to_end(i, v);
|
|
||||||
};
|
|
||||||
{
|
|
||||||
let mut c = base.to_vec();
|
|
||||||
let mut db = DB::try_from_vec(c.to_vec()).unwrap();
|
|
||||||
|
|
||||||
prop(&mut db, &mut c, 15, 7);
|
|
||||||
prop(&mut db, &mut c, 28, 8);
|
|
||||||
|
|
||||||
println!("{db:?}, {c:?}");
|
|
||||||
|
|
||||||
assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
|
||||||
assert_eq!(db.vec(), c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn prop_failcase() {
|
|
||||||
let base = [
|
|
||||||
0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 12, 13,
|
|
||||||
14, 15, 16, 17, 17, 18, 18, 18, 18, 18, 19, 20, 21, 21, 21, 21, 22, 23, 23, 24, 25, 26,
|
|
||||||
26, 26,
|
|
||||||
];
|
|
||||||
|
|
||||||
let prop = |bd: &mut DB, cc: &mut Vec<u32>, i, v: u32| {
|
|
||||||
cc.get_mut(i as usize..).unwrap().fill(v);
|
|
||||||
bd.propagate_to_end(i, v);
|
|
||||||
};
|
|
||||||
{
|
|
||||||
let mut c = base.to_vec();
|
|
||||||
let mut db = DB::try_from_vec(c.to_vec()).unwrap();
|
|
||||||
|
|
||||||
// prop(&mut db, &mut c, 12, 6);
|
|
||||||
prop(&mut db, &mut c, 28, 14);
|
|
||||||
|
|
||||||
println!("{db:?}, {c:?}");
|
|
||||||
|
|
||||||
assert_eq!(db.vec(), c);
|
|
||||||
assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,407 @@
|
|||||||
|
//! working as intended: i am happy
|
||||||
|
#![cfg(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,
|
||||||
|
};
|
||||||
|
assert!(ctodb.validate().is_ok());
|
||||||
|
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!(db.last().is_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).unwrap();
|
||||||
|
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).unwrap();
|
||||||
|
// dbg!(&db.inner);
|
||||||
|
for _ in 3..=11 {
|
||||||
|
db.push(1).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// dbg!(&db.inner);
|
||||||
|
// dbg!(db.vec());
|
||||||
|
db.push(2).unwrap();
|
||||||
|
dbg!(db.len() != 0);
|
||||||
|
assert!(db.push(4).is_err());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
// #[should_panic]
|
||||||
|
fn invalid_push_2() {
|
||||||
|
let mut db = DB::new();
|
||||||
|
// dbg!(&db.inner);
|
||||||
|
|
||||||
|
db.push(0).unwrap();
|
||||||
|
db.push(1).unwrap();
|
||||||
|
// dbg!(&db.inner);
|
||||||
|
// dbg!(db.vec());
|
||||||
|
db.push(2).unwrap();
|
||||||
|
dbg!(db.len() != 0);
|
||||||
|
assert!(db.push(1).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 = [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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn change_harder() {
|
||||||
|
let mut c = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 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;
|
||||||
|
};
|
||||||
|
{
|
||||||
|
println!("f: {c:?}");
|
||||||
|
assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
change(&mut db, &mut c, 12, 12);
|
||||||
|
println!("m: {:?}", db);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn prop_idk() {
|
||||||
|
let 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();
|
||||||
|
dbg!(&mut db).propagate_to_end(2, 2);
|
||||||
|
dbg!(&db);
|
||||||
|
println!("{:?}", db.vec());
|
||||||
|
assert_eq!(db.inner, vec![0, 1]);
|
||||||
|
let mut db = DB::try_from_vec(c.clone()).unwrap();
|
||||||
|
db.propagate_to_end(2, 3);
|
||||||
|
println!("{:?}", db.vec());
|
||||||
|
assert_eq!(db.inner, vec![0, 1, 2]);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn prop() {
|
||||||
|
let base = [
|
||||||
|
0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 12, 13, 14,
|
||||||
|
15, 16, 17, 17, 18, 18, 18, 18, 18, 19, 20, 21, 21, 21, 21, 22, 23, 23, 24, 25, 26, 26, 26,
|
||||||
|
];
|
||||||
|
|
||||||
|
let prop = |bd: &mut DB, cc: &mut Vec<u32>, i, v: u32| {
|
||||||
|
cc.get_mut(i as usize..).unwrap().fill(v);
|
||||||
|
bd.propagate_to_end(i, v);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
let mut c = base.to_vec();
|
||||||
|
let mut db = DB::try_from_vec(c.to_vec()).unwrap();
|
||||||
|
|
||||||
|
prop(&mut db, &mut c, 15, 7);
|
||||||
|
prop(&mut db, &mut c, 28, 8);
|
||||||
|
|
||||||
|
println!("{db:?}, {c:?}");
|
||||||
|
|
||||||
|
assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
||||||
|
assert_eq!(db.vec(), c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn prop_failcase() {
|
||||||
|
let base = [
|
||||||
|
0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 12, 13, 14,
|
||||||
|
15, 16, 17, 17, 18, 18, 18, 18, 18, 19, 20, 21, 21, 21, 21, 22, 23, 23, 24, 25, 26, 26, 26,
|
||||||
|
];
|
||||||
|
|
||||||
|
let prop = |bd: &mut DB, cc: &mut Vec<u32>, i, v: u32| {
|
||||||
|
cc.get_mut(i as usize..).unwrap().fill(v);
|
||||||
|
bd.propagate_to_end(i, v);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
let mut c = base.to_vec();
|
||||||
|
let mut db = DB::try_from_vec(c.to_vec()).unwrap();
|
||||||
|
|
||||||
|
// prop(&mut db, &mut c, 12, 6);
|
||||||
|
prop(&mut db, &mut c, 28, 14);
|
||||||
|
|
||||||
|
println!("{db:?}, {c:?}");
|
||||||
|
|
||||||
|
assert_eq!(db.vec(), c);
|
||||||
|
assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,761 +0,0 @@
|
|||||||
use std::{
|
|
||||||
error::Error,
|
|
||||||
fmt::{Debug, Display},
|
|
||||||
ops::Range,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A compressed representation of a sequence where adjacent values can only be equal
|
|
||||||
/// or increase by 1. For example: [0,0,0,1,1,2,3,3] is valid, but [0,2,1] is not.
|
|
||||||
///
|
|
||||||
/// This is particularly useful for storing dynamic programming rows in algorithms
|
|
||||||
/// like Longest Common Subsequence (LCS) where values can only stay the same or
|
|
||||||
/// increase by 1 between adjacent cells.
|
|
||||||
///
|
|
||||||
/// Internal representation:
|
|
||||||
/// - Instead of storing all values, stores only the indices where values increase
|
|
||||||
/// - For example, [0,0,0,1,1,2] is stored as inner=[3,5] with len=6
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use lda_strdist::common_subsequence::db2::DB; // adjust this
|
|
||||||
///
|
|
||||||
/// let mut db = DB::new();
|
|
||||||
/// db.push(0)?; // [0]
|
|
||||||
/// db.push(0)?; // [0,0]
|
|
||||||
/// db.push(1)?; // [0,0,1]
|
|
||||||
/// assert_eq!(db.get(2), Some(1));
|
|
||||||
/// ```
|
|
||||||
#[derive(Debug, Default, PartialEq, Clone)]
|
|
||||||
pub struct DB {
|
|
||||||
/// Indices where values increase by 1. Must be strictly increasing.
|
|
||||||
inner: Vec<u32>,
|
|
||||||
/// Total length of the sequence
|
|
||||||
len: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Errors that can occur during DB operations
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum DBError {
|
|
||||||
/// Value violates monotonic property (must be equal to or 1 more than previous)
|
|
||||||
InvalidValue { value: u32, previous: u32 },
|
|
||||||
/// Index out of bounds
|
|
||||||
IndexOutOfBounds { index: u32, len: u32 },
|
|
||||||
/// Invalid internal state (should never happen if invariants are maintained)
|
|
||||||
InvalidState(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for DBError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
Debug::fmt(&self, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for DBError {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DB {
|
|
||||||
/// Creates a new empty DB
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new DB with specified length, all values 0
|
|
||||||
pub fn with_len(len: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
len,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the length of the sequence
|
|
||||||
pub fn len(&self) -> u32 {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the sequence is empty
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.len == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the last value in the sequence
|
|
||||||
pub fn last_value(&self) -> Option<u32> {
|
|
||||||
if self.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.inner.len() as u32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Validates the internal state of the DB
|
|
||||||
pub fn validate(&self) -> Result<(), DBError> {
|
|
||||||
// Check that inner values are strictly increasing
|
|
||||||
if !self.inner.windows(2).all(|w| w[0] < w[1]) {
|
|
||||||
return Err(DBError::InvalidState(
|
|
||||||
"Inner vector must be strictly increasing".to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that all inner values are less than len
|
|
||||||
if let Some(&max) = self.inner.last() {
|
|
||||||
if max >= self.len {
|
|
||||||
return Err(DBError::InvalidState(
|
|
||||||
"Inner values must be less than len".to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Appends a value to the end of the sequence.
|
|
||||||
/// The value must be equal to or one more than the last value.
|
|
||||||
pub fn push(&mut self, val: u32) -> Result<(), DBError> {
|
|
||||||
let last = self.last_value().unwrap_or_default();
|
|
||||||
match val {
|
|
||||||
v if v == last + 1 => {
|
|
||||||
self.inner.push(self.len);
|
|
||||||
self.len += 1;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
v if v == last => {
|
|
||||||
self.len += 1;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Err(DBError::InvalidValue {
|
|
||||||
value: val,
|
|
||||||
previous: last,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Removes and returns the last value from the sequence
|
|
||||||
pub fn pop(&mut self) -> Option<u32> {
|
|
||||||
if self.len == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let value = self.last_value().unwrap();
|
|
||||||
if let Some(&last_change) = self.inner.last() {
|
|
||||||
if self.len - 1 == last_change {
|
|
||||||
self.inner.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.len -= 1;
|
|
||||||
Some(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the value at the specified index
|
|
||||||
pub fn get(&self, index: u32) -> Option<u32> {
|
|
||||||
if index >= self.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(
|
|
||||||
self.inner
|
|
||||||
.iter()
|
|
||||||
.rposition(|&change_idx| index >= change_idx)
|
|
||||||
.map_or(0, |pos| pos as u32 + 1),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the range of indices where a value appears
|
|
||||||
pub fn range_of(&self, value: u32) -> Option<Range<u32>> {
|
|
||||||
if value == 0 {
|
|
||||||
return Some(0..self.inner.first().copied().unwrap_or(self.len));
|
|
||||||
}
|
|
||||||
|
|
||||||
let value = value as usize;
|
|
||||||
if value > self.inner.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(
|
|
||||||
self.inner.get(value - 1).copied().unwrap_or(self.len)
|
|
||||||
..self.inner.get(value).copied().unwrap_or(self.len),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the available values that can be set at the given index,
|
|
||||||
/// along with a hint about which value might be preferred
|
|
||||||
pub fn available_values(&self, index: u32) -> Result<(Vec<u32>, Option<u32>), DBError> {
|
|
||||||
if index >= self.len() {
|
|
||||||
return Err(DBError::IndexOutOfBounds {
|
|
||||||
index,
|
|
||||||
len: self.len(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let current = self.get(index).unwrap();
|
|
||||||
let mut available = vec![current];
|
|
||||||
let mut preferred = None;
|
|
||||||
|
|
||||||
// Can decrease by 1 if:
|
|
||||||
// 1. Not at value 0
|
|
||||||
// 2. Not at the start of a range
|
|
||||||
if current > 0 && !self.inner.contains(&index) {
|
|
||||||
available.push(current - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can increase by 1 if:
|
|
||||||
// 1. At the end of a range
|
|
||||||
// 2. Not at maximum value
|
|
||||||
if let Some(range) = self.range_of(current) {
|
|
||||||
if index == range.end - 1 && current < self.inner.len() as u32 {
|
|
||||||
available.push(current + 1);
|
|
||||||
preferred = Some(current + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((available, preferred))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Changes the value at the given index, maintaining monotonicity
|
|
||||||
pub fn change(&mut self, index: u32, value: u32) -> Result<(), DBError> {
|
|
||||||
let (available, _) = self.available_values(index)?;
|
|
||||||
if !available.contains(&value) {
|
|
||||||
return Err(DBError::InvalidValue {
|
|
||||||
value,
|
|
||||||
previous: self.get(index).unwrap(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle value decrease
|
|
||||||
if let Some(current_range) = self.range_of(self.get(index).unwrap()) {
|
|
||||||
if current_range.start == index {
|
|
||||||
// Remove this breakpoint
|
|
||||||
if let Some(pos) = self.inner.iter().position(|&x| x == index) {
|
|
||||||
self.inner.remove(pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle value increase
|
|
||||||
if let Some(new_range) = self.range_of(value) {
|
|
||||||
if new_range.end == index {
|
|
||||||
self.inner.push(index);
|
|
||||||
self.inner.sort_unstable(); // Maintain sorted order
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts the compressed representation to a full vector
|
|
||||||
pub fn to_vec(&self) -> Vec<u32> {
|
|
||||||
let mut result = Vec::with_capacity(self.len() as usize);
|
|
||||||
let mut current_value = 0;
|
|
||||||
|
|
||||||
for i in 0..self.len() {
|
|
||||||
if self.inner.contains(&i) {
|
|
||||||
current_value += 1;
|
|
||||||
}
|
|
||||||
result.push(current_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a DB from a vector, validating monotonicity
|
|
||||||
pub fn try_from_vec(vec: Vec<u32>) -> Result<Self, DBError> {
|
|
||||||
let len = vec.len() as u32;
|
|
||||||
let mut inner = Vec::new();
|
|
||||||
let mut prev = None;
|
|
||||||
|
|
||||||
for (i, &value) in vec.iter().enumerate() {
|
|
||||||
match prev {
|
|
||||||
None => {
|
|
||||||
if value > 0 {
|
|
||||||
return Err(DBError::InvalidValue { value, previous: 0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(prev_val) => match value.checked_sub(prev_val) {
|
|
||||||
Some(0) => {}
|
|
||||||
Some(1) => inner.push(i as u32),
|
|
||||||
_ => {
|
|
||||||
return Err(DBError::InvalidValue {
|
|
||||||
value,
|
|
||||||
previous: prev_val,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
prev = Some(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let db = Self { inner, len };
|
|
||||||
db.validate()?;
|
|
||||||
Ok(db)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_basic_operations() {
|
|
||||||
let mut db = DB::new();
|
|
||||||
assert!(db.is_empty());
|
|
||||||
|
|
||||||
// Test push
|
|
||||||
db.push(0).unwrap();
|
|
||||||
db.push(0).unwrap();
|
|
||||||
db.push(1).unwrap();
|
|
||||||
assert_eq!(db.to_vec(), vec![0, 0, 1]);
|
|
||||||
|
|
||||||
// Test get
|
|
||||||
assert_eq!(db.get(0), Some(0));
|
|
||||||
assert_eq!(db.get(2), Some(1));
|
|
||||||
assert_eq!(db.get(3), None);
|
|
||||||
|
|
||||||
// Test pop
|
|
||||||
assert_eq!(db.pop(), Some(1));
|
|
||||||
assert_eq!(db.to_vec(), vec![0, 0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_invalid_operations() {
|
|
||||||
let mut db = DB::new();
|
|
||||||
|
|
||||||
// Test invalid push
|
|
||||||
db.push(0).unwrap();
|
|
||||||
assert!(matches!(
|
|
||||||
db.push(2),
|
|
||||||
Err(DBError::InvalidValue {
|
|
||||||
value: 2,
|
|
||||||
previous: 0
|
|
||||||
})
|
|
||||||
));
|
|
||||||
|
|
||||||
// Test invalid change
|
|
||||||
assert!(matches!(db.change(0, 2), Err(DBError::InvalidValue { .. })));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_range_of() {
|
|
||||||
let mut db = DB::new();
|
|
||||||
for _ in 0..3 {
|
|
||||||
db.push(0).unwrap();
|
|
||||||
}
|
|
||||||
db.push(1).unwrap();
|
|
||||||
db.push(1).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(db.range_of(0), Some(0..3));
|
|
||||||
assert_eq!(db.range_of(1), Some(3..5));
|
|
||||||
assert_eq!(db.range_of(2), None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// /// working as intended: i am happy
|
|
||||||
// #[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,
|
|
||||||
// };
|
|
||||||
// assert!(ctodb.validate().is_ok());
|
|
||||||
// assert_eq!(ctodb.to_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.to_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!(db.last_value().is_none());
|
|
||||||
|
|
||||||
// let db = DB::with_len(1);
|
|
||||||
// assert!(matches!(db.last_value(), 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).unwrap();
|
|
||||||
// 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.to_vec(), c)
|
|
||||||
// }
|
|
||||||
// #[test]
|
|
||||||
// // #[should_panic]
|
|
||||||
// fn invalid_push() {
|
|
||||||
// let mut db = DB::new();
|
|
||||||
// // dbg!(&db.inner);
|
|
||||||
// db.push(1).unwrap();
|
|
||||||
// // dbg!(&db.inner);
|
|
||||||
// for _ in 3..=11 {
|
|
||||||
// db.push(1).unwrap();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // dbg!(&db.inner);
|
|
||||||
// // dbg!(db.vec());
|
|
||||||
// db.push(2).unwrap();
|
|
||||||
// dbg!(db.len() != 0);
|
|
||||||
// assert!(db.push(4).is_err());
|
|
||||||
// }
|
|
||||||
// #[test]
|
|
||||||
// // #[should_panic]
|
|
||||||
// fn invalid_push_2() {
|
|
||||||
// let mut db = DB::new();
|
|
||||||
// // dbg!(&db.inner);
|
|
||||||
|
|
||||||
// db.push(0).unwrap();
|
|
||||||
// db.push(1).unwrap();
|
|
||||||
// // dbg!(&db.inner);
|
|
||||||
// // dbg!(db.vec());
|
|
||||||
// db.push(2).unwrap();
|
|
||||||
// dbg!(db.len() != 0);
|
|
||||||
// assert!(db.push(1).is_err());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[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 = [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 _,
|
|
||||||
// };
|
|
||||||
// ctodb.available_values(3).unwrap();
|
|
||||||
// ctodb.available_values(7).unwrap() ;
|
|
||||||
// dbg!(ctodb.available_values(13).unwrap());
|
|
||||||
|
|
||||||
// dbg!(ctodb.available_values(0).unwrap(),);
|
|
||||||
// dbg!(ctodb.available_values(4).unwrap(), );
|
|
||||||
// dbg!(ctodb.available_values(11).unwrap(), );
|
|
||||||
// dbg!(ctodb.available_values(12).unwrap(), );
|
|
||||||
// dbg!(ctodb.available_values(15).unwrap(), );
|
|
||||||
// dbg!(ctodb.available_values(16).unwrap(),);
|
|
||||||
// assert!(ctodb.available_values(17).is_err());
|
|
||||||
// }
|
|
||||||
// #[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();
|
|
||||||
// dbg!(db.available_values(0), );
|
|
||||||
// dbg!(db.available_values(1), );
|
|
||||||
// dbg!(db.available_values(11),);
|
|
||||||
// dbg!(db.available_values(12), );
|
|
||||||
// dbg!(db.available_values(13), );
|
|
||||||
// dbg!(db.available_values(15), );
|
|
||||||
// dbg!(db.available_values(16), );
|
|
||||||
// dbg!(db.available_values(17), );
|
|
||||||
// }
|
|
||||||
// #[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().to_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().to_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.to_vec());
|
|
||||||
// println!("{:?}", db);
|
|
||||||
// assert_eq!(db, db2);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn change_harder() {
|
|
||||||
// let mut c = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 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;
|
|
||||||
// };
|
|
||||||
// {
|
|
||||||
// println!("f: {c:?}");
|
|
||||||
// assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// change(&mut db, &mut c, 12, 12);
|
|
||||||
// println!("m: {:?}", db);
|
|
||||||
// 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().to_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().to_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.to_vec());
|
|
||||||
// println!("{:?}", db);
|
|
||||||
// assert_eq!(db, db2);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // #[test]
|
|
||||||
// // fn prop_idk() {
|
|
||||||
// // let 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();
|
|
||||||
// // dbg!(&mut db).propagate_to_end(2, 2);
|
|
||||||
// // dbg!(&db);
|
|
||||||
// // println!("{:?}", db.vec());
|
|
||||||
// // assert_eq!(db.inner, vec![0, 1]);
|
|
||||||
// // let mut db = DB::try_from_vec(c.clone()).unwrap();
|
|
||||||
// // db.propagate_to_end(2, 3);
|
|
||||||
// // println!("{:?}", db.vec());
|
|
||||||
// // assert_eq!(db.inner, vec![0, 1, 2]);
|
|
||||||
// // }
|
|
||||||
// // #[test]
|
|
||||||
// // fn prop() {
|
|
||||||
// // let base = [
|
|
||||||
// // 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 12, 13,
|
|
||||||
// // 14, 15, 16, 17, 17, 18, 18, 18, 18, 18, 19, 20, 21, 21, 21, 21, 22, 23, 23, 24, 25, 26,
|
|
||||||
// // 26, 26,
|
|
||||||
// // ];
|
|
||||||
|
|
||||||
// // let prop = |bd: &mut DB, cc: &mut Vec<u32>, i, v: u32| {
|
|
||||||
// // cc.get_mut(i as usize..).unwrap().fill(v);
|
|
||||||
// // bd.propagate_to_end(i, v);
|
|
||||||
// // };
|
|
||||||
// // {
|
|
||||||
// // let mut c = base.to_vec();
|
|
||||||
// // let mut db = DB::try_from_vec(c.to_vec()).unwrap();
|
|
||||||
|
|
||||||
// // prop(&mut db, &mut c, 15, 7);
|
|
||||||
// // prop(&mut db, &mut c, 28, 8);
|
|
||||||
|
|
||||||
// // println!("{db:?}, {c:?}");
|
|
||||||
|
|
||||||
// // assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
|
||||||
// // assert_eq!(db.vec(), c);
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// // #[test]
|
|
||||||
// // #[should_panic]
|
|
||||||
// // fn prop_failcase() {
|
|
||||||
// // let base = [
|
|
||||||
// // 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 12, 13,
|
|
||||||
// // 14, 15, 16, 17, 17, 18, 18, 18, 18, 18, 19, 20, 21, 21, 21, 21, 22, 23, 23, 24, 25, 26,
|
|
||||||
// // 26, 26,
|
|
||||||
// // ];
|
|
||||||
|
|
||||||
// // let prop = |bd: &mut DB, cc: &mut Vec<u32>, i, v: u32| {
|
|
||||||
// // cc.get_mut(i as usize..).unwrap().fill(v);
|
|
||||||
// // bd.propagate_to_end(i, v);
|
|
||||||
// // };
|
|
||||||
// // {
|
|
||||||
// // let mut c = base.to_vec();
|
|
||||||
// // let mut db = DB::try_from_vec(c.to_vec()).unwrap();
|
|
||||||
|
|
||||||
// // // prop(&mut db, &mut c, 12, 6);
|
|
||||||
// // prop(&mut db, &mut c, 28, 14);
|
|
||||||
|
|
||||||
// // println!("{db:?}, {c:?}");
|
|
||||||
|
|
||||||
// // assert_eq!(db.vec(), c);
|
|
||||||
// // assert_eq!(db, DB::try_from_vec(c.clone()).unwrap());
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
use std::cmp::Ordering;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub struct MonotonicSequence {
|
|
||||||
/// Stores (position, value) pairs where value increases
|
|
||||||
/// Always includes (0, initial_value) as first element
|
|
||||||
jumps: Vec<(usize, u32)>,
|
|
||||||
/// Length of the sequence
|
|
||||||
length: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum ChangeError {
|
|
||||||
/// Position beyond sequence length
|
|
||||||
OutOfBounds { pos: usize, length: usize },
|
|
||||||
/// Change would break monotonic property
|
|
||||||
InvalidChange {
|
|
||||||
pos: usize,
|
|
||||||
new_value: u32,
|
|
||||||
reason: String,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MonotonicSequence {
|
|
||||||
/// Create new sequence starting with given value
|
|
||||||
pub fn new(initial_value: u32, length: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
jumps: vec![(0, initial_value)],
|
|
||||||
length,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get value at position
|
|
||||||
pub fn get(&self, pos: usize) -> Option<u32> {
|
|
||||||
if pos >= self.length {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Binary search for last jump <= pos
|
|
||||||
match self.jumps.binary_search_by(|(jump_pos, _)| {
|
|
||||||
if *jump_pos <= pos {
|
|
||||||
Ordering::Less
|
|
||||||
} else {
|
|
||||||
Ordering::Greater
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
// Exact match found
|
|
||||||
Ok(idx) => Some(self.jumps[idx].1),
|
|
||||||
// No exact match, use last smaller value
|
|
||||||
Err(idx) if idx > 0 => Some(self.jumps[idx - 1].1),
|
|
||||||
// Position before first jump
|
|
||||||
Err(_) => Some(0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can we change value at position to new_value?
|
|
||||||
pub fn can_change(&self, pos: usize, new_value: u32) -> Result<bool, ChangeError> {
|
|
||||||
if pos >= self.length {
|
|
||||||
return Err(ChangeError::OutOfBounds {
|
|
||||||
pos,
|
|
||||||
length: self.length
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current value
|
|
||||||
let _current = self.get(pos).unwrap();
|
|
||||||
|
|
||||||
// Get value before (if any)
|
|
||||||
let value_before = if pos > 0 {
|
|
||||||
self.get(pos - 1).unwrap()
|
|
||||||
} else {
|
|
||||||
// If at start, can only change to 0 or 1
|
|
||||||
return Ok(new_value <= 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get value after (if any)
|
|
||||||
let value_after = if pos < self.length - 1 {
|
|
||||||
self.get(pos + 1).unwrap()
|
|
||||||
} else {
|
|
||||||
// If at end, just need to check previous value
|
|
||||||
return Ok(new_value >= value_before && new_value <= value_before + 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Main rules:
|
|
||||||
// 1. Can't decrease by more than 1 from previous
|
|
||||||
// 2. Can't increase by more than 1 from previous
|
|
||||||
// 3. Next value must be valid relative to new value
|
|
||||||
Ok(
|
|
||||||
new_value >= value_before &&
|
|
||||||
new_value <= value_before + 1 &&
|
|
||||||
value_after >= new_value &&
|
|
||||||
value_after <= new_value + 1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change value at position
|
|
||||||
pub fn change(&mut self, pos: usize, new_value: u32) -> Result<(), ChangeError> {
|
|
||||||
if !self.can_change(pos, new_value)? {
|
|
||||||
return Err(ChangeError::InvalidChange {
|
|
||||||
pos,
|
|
||||||
new_value,
|
|
||||||
reason: "Change would break monotonic property".to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find existing jump at this position (if any)
|
|
||||||
let existing_jump = self.jumps.iter()
|
|
||||||
.position(|(jump_pos, _)| *jump_pos == pos);
|
|
||||||
|
|
||||||
match existing_jump {
|
|
||||||
Some(idx) => {
|
|
||||||
// We have a jump here already
|
|
||||||
if self.get(pos - 1).unwrap() == new_value {
|
|
||||||
// New value same as previous - remove jump
|
|
||||||
self.jumps.remove(idx);
|
|
||||||
} else {
|
|
||||||
// Update jump value
|
|
||||||
self.jumps[idx].1 = new_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// No jump here yet
|
|
||||||
if self.get(pos - 1).unwrap() != new_value {
|
|
||||||
// Value different from previous - insert new jump
|
|
||||||
let insert_pos = self.jumps.partition_point(|(jump_pos, _)| *jump_pos < pos);
|
|
||||||
self.jumps.insert(insert_pos, (pos, new_value));
|
|
||||||
}
|
|
||||||
// If same as previous, no jump needed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert to regular vector
|
|
||||||
pub fn to_vec(&self) -> Vec<u32> {
|
|
||||||
let mut result = Vec::with_capacity(self.length);
|
|
||||||
let mut last_jump = 0;
|
|
||||||
let mut current_value = self.jumps[0].1;
|
|
||||||
|
|
||||||
for pos in 0..self.length {
|
|
||||||
// Check if we're at a new jump point
|
|
||||||
if last_jump + 1 < self.jumps.len() && pos == self.jumps[last_jump + 1].0 {
|
|
||||||
last_jump += 1;
|
|
||||||
current_value = self.jumps[last_jump].1;
|
|
||||||
}
|
|
||||||
result.push(current_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_basic_operations() {
|
|
||||||
// Create [0,0,1,1,2,2]
|
|
||||||
let mut seq = MonotonicSequence::new(0, 6);
|
|
||||||
seq.change(2, 1).unwrap();
|
|
||||||
seq.change(4, 2).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(seq.get(0), Some(0));
|
|
||||||
assert_eq!(seq.get(1), Some(0));
|
|
||||||
assert_eq!(seq.get(2), Some(1));
|
|
||||||
assert_eq!(seq.get(3), Some(1));
|
|
||||||
assert_eq!(seq.get(4), Some(2));
|
|
||||||
assert_eq!(seq.get(5), Some(2));
|
|
||||||
assert_eq!(seq.get(6), None);
|
|
||||||
|
|
||||||
assert_eq!(seq.to_vec(), vec![0,0,1,1,2,2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_invalid_changes() {
|
|
||||||
let mut seq = MonotonicSequence::new(0, 6);
|
|
||||||
seq.change(2, 1).unwrap();
|
|
||||||
seq.change(4, 2).unwrap();
|
|
||||||
|
|
||||||
// Can't decrease by more than 1
|
|
||||||
assert!(seq.can_change(4, 0).is_err());
|
|
||||||
|
|
||||||
// Can't increase by more than 1
|
|
||||||
assert!(seq.can_change(1, 2).is_err());
|
|
||||||
|
|
||||||
// Can't create invalid sequence
|
|
||||||
assert!(seq.change(3, 0).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_modify_jumps() {
|
|
||||||
let mut seq = MonotonicSequence::new(0, 6);
|
|
||||||
seq.change(2, 1).unwrap();
|
|
||||||
seq.change(4, 2).unwrap();
|
|
||||||
|
|
||||||
// Remove jump by setting to previous value
|
|
||||||
seq.change(2, 0).unwrap();
|
|
||||||
assert_eq!(seq.to_vec(), vec![0,0,0,0,2,2]);
|
|
||||||
|
|
||||||
// Move jump point
|
|
||||||
seq.change(3, 1).unwrap();
|
|
||||||
assert_eq!(seq.to_vec(), vec![0,0,0,1,2,2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,10 +3,6 @@ use monotonic_sequence::{MonotonicSequence, SequenceError};
|
|||||||
// use db2::{DBError, DB as DB2};
|
// use db2::{DBError, DB as DB2};
|
||||||
|
|
||||||
pub mod db;
|
pub mod db;
|
||||||
// #[allow(dead_code)]
|
|
||||||
// mod db2;
|
|
||||||
// #[allow(dead_code)]
|
|
||||||
// mod db3;
|
|
||||||
pub mod monotonic_sequence;
|
pub mod monotonic_sequence;
|
||||||
|
|
||||||
pub fn lcs_gen(str1: &str, str2: &str) -> Vec<Vec<u32>> {
|
pub fn lcs_gen(str1: &str, str2: &str) -> Vec<Vec<u32>> {
|
||||||
@@ -109,8 +105,77 @@ pub fn lcs_gen_ms(str1: &str, str2: &str) -> Result<Vec<MonotonicSequence>, belp
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn lcs_traceback_vec(str1: &str, str2: &str, dp: Vec<Vec<u32>>) {
|
pub fn lcs_traceback_vec(str1: &str, str2: &str, dp: &Vec<Vec<u32>>) -> Vec<String> {
|
||||||
todo!()
|
/* function backtrackAll(C[0..m,0..n], X[1..m], Y[1..n], i, j)
|
||||||
|
if i = 0 or j = 0
|
||||||
|
return {""}
|
||||||
|
if X[i] = Y[j]
|
||||||
|
return {Z + X[i] for all Z in backtrackAll(C, X, Y, i-1, j-1)}
|
||||||
|
R := {}
|
||||||
|
if C[i,j-1] ≥ C[i-1,j]
|
||||||
|
R := backtrackAll(C, X, Y, i, j-1)
|
||||||
|
if C[i-1,j] ≥ C[i,j-1]
|
||||||
|
R := R ∪ backtrackAll(C, X, Y, i-1, j)
|
||||||
|
return R
|
||||||
|
*/
|
||||||
|
let c1: Vec<char> = str1.chars().collect();
|
||||||
|
let c2: Vec<char> = str2.chars().collect();
|
||||||
|
use std::collections::HashSet;
|
||||||
|
fn backtrack_all(
|
||||||
|
dp: &Vec<Vec<u32>>,
|
||||||
|
c1: &Vec<char>,
|
||||||
|
c2: &Vec<char>,
|
||||||
|
i: usize,
|
||||||
|
j: usize,
|
||||||
|
) -> HashSet<String> {
|
||||||
|
if i == 0 || j == 0 {
|
||||||
|
return HashSet::from(["".into()]);
|
||||||
|
}
|
||||||
|
if c1[i - 1] == c2[j - 1] {
|
||||||
|
let mut s: Vec<String> = backtrack_all(dp, c1, c2, i - 1, j - 1)
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
s.iter_mut().for_each(|f| f.push(c1[i - 1]));
|
||||||
|
return (HashSet::from_iter(s));
|
||||||
|
};
|
||||||
|
let mut w = HashSet::new();
|
||||||
|
if dp[i][j - 1] >= dp[i - 1][j] {
|
||||||
|
w.extend(backtrack_all(dp, c1, c2, i, j - 1));
|
||||||
|
}
|
||||||
|
if dp[i][j - 1] < dp[i - 1][j] {
|
||||||
|
w.extend(backtrack_all(dp, c1, c2, i - 1, j));
|
||||||
|
}
|
||||||
|
(w)
|
||||||
|
}
|
||||||
|
backtrack_all(dp, &c1, &c2, dp.len() - 1, dp[0].len() - 1)
|
||||||
|
.into_iter()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lcs_traceback_funny(str1: &str, str2: &str, dp: &[Vec<u32>]) -> String {
|
||||||
|
let c1: Vec<char> = str1.chars().collect();
|
||||||
|
let _c2: Vec<char> = str2.chars().collect();
|
||||||
|
let (mut i, mut j) = (dp.len() - 1, dp[0].len() - 1);
|
||||||
|
let mut indices = vec![];
|
||||||
|
while dp[i][j] > 0 {
|
||||||
|
// up
|
||||||
|
while dp[i][j] == dp[i - 1][j] {
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
//over
|
||||||
|
while dp[i][j] == dp[i][j - 1] {
|
||||||
|
j -= 1;
|
||||||
|
}
|
||||||
|
// this
|
||||||
|
indices.push(i); // c1
|
||||||
|
|
||||||
|
// cross
|
||||||
|
i -= 1;
|
||||||
|
j -= 1;
|
||||||
|
|
||||||
|
// way easier when i understand it
|
||||||
|
}
|
||||||
|
indices.into_iter().rev().map(|c| c1[c]).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -118,17 +183,42 @@ mod test {
|
|||||||
|
|
||||||
// use crate::common_subsequence::{db2::DB as DB2, lcs_gen_dbai};
|
// use crate::common_subsequence::{db2::DB as DB2, lcs_gen_dbai};
|
||||||
|
|
||||||
|
use crate::common_subsequence::{lcs_traceback_funny, lcs_traceback_vec};
|
||||||
|
|
||||||
use super::{lcs_gen_ms, monotonic_sequence::MonotonicSequence};
|
use super::{lcs_gen_ms, monotonic_sequence::MonotonicSequence};
|
||||||
|
|
||||||
use super::{lcs_gen, lcs_gen_db, DB};
|
use super::{lcs_gen, lcs_gen_db, DB};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_normal_case() {
|
fn test_normal_case() {
|
||||||
lcs_gen("asjhdgasdhj", "gajhdgashjd");
|
// use crate::wrapper_::StrDisplay;
|
||||||
|
let str1 = "qesadfghsjwergwse";
|
||||||
|
let str2 = "kufygkjhsvgsbvjhsawsfwaf";
|
||||||
|
// let (str1, str2) = ("XMJYAUZ", "MZJAWXU");
|
||||||
|
let d = lcs_gen(str1, str2);
|
||||||
|
// println!(" {c}", c = StrDisplay(str2));
|
||||||
|
// (" ".chars().chain(str1.chars()))
|
||||||
|
// .zip(d.iter())
|
||||||
|
// .for_each(|(c, v)| println!("{v:?} {c}"));
|
||||||
|
let ww = lcs_traceback_vec(str1, str2, &d);
|
||||||
|
// _ww.iter().for_each(|c|println!("{c}"));
|
||||||
// lcs_gen("", "");
|
// lcs_gen("", "");
|
||||||
|
let one = lcs_traceback_funny(str1, str2, &d);
|
||||||
|
dbg!(dbg!(&ww).contains(dbg!(&one)));
|
||||||
|
use crate::wrapper_::{ColoredInsanelySpecific, InsanelySpecific};
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
ColoredInsanelySpecific(InsanelySpecific {
|
||||||
|
c1: &str1.chars().collect(),
|
||||||
|
c2: &str2.chars().collect(),
|
||||||
|
dp: &d,
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn time() {
|
fn time() {
|
||||||
|
println!("asdas");
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
{
|
{
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
@@ -161,6 +251,13 @@ mod test {
|
|||||||
|
|
||||||
// success to me
|
// success to me
|
||||||
// ABSOLUTE FAILURE
|
// ABSOLUTE FAILURE
|
||||||
|
{
|
||||||
|
let start = Instant::now();
|
||||||
|
test_normal_case();
|
||||||
|
let duration = start.elapsed();
|
||||||
|
|
||||||
|
println!("for test_normal_case is: {:?}", duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! claude cooked
|
//! claude cooked
|
||||||
//! most of code is me? no most of code is claude
|
//! most of code is me
|
||||||
|
|
||||||
use std::ops::Range;
|
use std::{collections::VecDeque, ops::Range};
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq)]
|
#[derive(Default, Debug, Clone, PartialEq)]
|
||||||
pub struct MonotonicSequence {
|
pub struct MonotonicSequence {
|
||||||
@@ -55,7 +55,16 @@ impl MonotonicSequence {
|
|||||||
}
|
}
|
||||||
// jumps function
|
// jumps function
|
||||||
/// `self.jumps[result of this function]` to get info
|
/// `self.jumps[result of this function]` to get info
|
||||||
fn get_jump_index(&self, pos: usize) -> usize {
|
///
|
||||||
|
/** ```
|
||||||
|
# use lda_strdist::common_subsequence::monotonic_sequence::MonotonicSequence;
|
||||||
|
# let ms = MonotonicSequence::try_from_vec(&[0,0,0,1,1,1,2,2,3,3,4,4,4]).unwrap();
|
||||||
|
# let (pos, val) = ms.jumps()[3];
|
||||||
|
let at = ms.find_jump_index(val).unwrap();
|
||||||
|
debug_assert_eq!(ms.jumps()[at].1, val);
|
||||||
|
``` */
|
||||||
|
// notice that this thing gives 0 shit about self.length
|
||||||
|
pub fn get_jump_index(&self, pos: usize) -> usize {
|
||||||
match self.jumps.binary_search_by(|(jump_point, _value)| {
|
match self.jumps.binary_search_by(|(jump_point, _value)| {
|
||||||
// if *jump_point <= pos {
|
// if *jump_point <= pos {
|
||||||
// Ordering::Less
|
// Ordering::Less
|
||||||
@@ -72,6 +81,7 @@ impl MonotonicSequence {
|
|||||||
Err(0) => 0,
|
Err(0) => 0,
|
||||||
// debug_assert_ne!(index, 0); // confident
|
// debug_assert_ne!(index, 0); // confident
|
||||||
Err(index) => index - 1,
|
Err(index) => index - 1,
|
||||||
|
// what about pos bigger than self.len()? idc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get value at position
|
/// Get value at position
|
||||||
@@ -160,12 +170,14 @@ impl MonotonicSequence {
|
|||||||
// if 2, 4 which NEVER happens btw then can you not be 4? well but it never happens
|
// if 2, 4 which NEVER happens btw then can you not be 4? well but it never happens
|
||||||
}
|
}
|
||||||
// if bigger to big if smaller too small
|
// if bigger to big if smaller too small
|
||||||
pub fn can_set_mini(
|
/// manual use only
|
||||||
|
fn can_set_mini(
|
||||||
pos: usize,
|
pos: usize,
|
||||||
new_value: u32,
|
new_value: u32,
|
||||||
(current_min, current_max): (u32, u32),
|
(current_min, current_max): (u32, u32),
|
||||||
) -> Result<(), SequenceError> {
|
) -> Result<(), SequenceError> {
|
||||||
debug_assert!(current_max >= current_min && current_max - current_min <= 1);
|
/*debug_*/
|
||||||
|
assert!(current_max >= current_min && current_max - current_min <= 1);
|
||||||
if new_value < current_min {
|
if new_value < current_min {
|
||||||
return Err(SequenceError::ValueTooLow {
|
return Err(SequenceError::ValueTooLow {
|
||||||
pos,
|
pos,
|
||||||
@@ -181,6 +193,12 @@ impl MonotonicSequence {
|
|||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn can_set_3(&self, pos: usize, new_value: u32) -> Result<(), SequenceError> {
|
||||||
|
let minmax = self.can_set(pos, new_value)?;
|
||||||
|
Self::can_set_mini(pos, new_value, minmax)
|
||||||
|
}
|
||||||
|
|
||||||
/// Change value at position
|
/// Change value at position
|
||||||
pub fn set(&mut self, pos: usize, value: u32) -> Result<(), SequenceError> {
|
pub fn set(&mut self, pos: usize, value: u32) -> Result<(), SequenceError> {
|
||||||
let (min, max) = /*dbg!*/self.can_set(pos, value)?; // already checked for bounds here
|
let (min, max) = /*dbg!*/self.can_set(pos, value)?; // already checked for bounds here
|
||||||
@@ -202,8 +220,14 @@ impl MonotonicSequence {
|
|||||||
// THE jump index from get_jump_index
|
// THE jump index from get_jump_index
|
||||||
if value == min {
|
if value == min {
|
||||||
assert_eq!(current_value, max); // solid logic
|
assert_eq!(current_value, max); // solid logic
|
||||||
let at = self.get_jump_index(pos);
|
let at = self.find_jump_index(current_value).unwrap(); // because current value is in it
|
||||||
debug_assert_eq!(self.jumps[at].0, pos);
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
let at1 = self.get_jump_index(pos);
|
||||||
|
assert_eq!(at1, at);
|
||||||
|
debug_assert_eq!(self.jumps[at1].0, pos);
|
||||||
|
debug_assert_eq!(self.jumps[at].1, current_value);
|
||||||
|
}
|
||||||
// TODO: pos misuse?
|
// TODO: pos misuse?
|
||||||
let (ind, _ /*val*/) = self.jumps.get_mut(at).unwrap(); // pos here is valid. already checked bounds
|
let (ind, _ /*val*/) = self.jumps.get_mut(at).unwrap(); // pos here is valid. already checked bounds
|
||||||
|
|
||||||
@@ -235,8 +259,14 @@ impl MonotonicSequence {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO: pos misuse?
|
// TODO: pos misuse?
|
||||||
let at = self.get_jump_index(pos + 1); // should land at
|
let at = self.find_jump_index(value).unwrap(); // because current value is in it
|
||||||
debug_assert_eq!(self.jumps[at].0, pos + 1);
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
let at1 = self.get_jump_index(pos + 1); // should land at
|
||||||
|
assert_eq!(at1, at);
|
||||||
|
debug_assert_eq!(self.jumps[at1].0, pos + 1);
|
||||||
|
debug_assert_eq!(self.jumps[at].1, value);
|
||||||
|
}
|
||||||
let (index, _val) = /*dbg!*/self.jumps.get_mut(at).unwrap();
|
let (index, _val) = /*dbg!*/self.jumps.get_mut(at).unwrap();
|
||||||
|
|
||||||
// how does this work?
|
// how does this work?
|
||||||
@@ -250,10 +280,14 @@ impl MonotonicSequence {
|
|||||||
*index -= 1;
|
*index -= 1;
|
||||||
|
|
||||||
if *index == 0 {
|
if *index == 0 {
|
||||||
let val = *_val; // wow rust is cool guys
|
#[cfg(debug_assertions)]
|
||||||
let removed = self.jumps.remove(0);
|
let _val = *_val; // wow rust is cool guys
|
||||||
debug_assert_eq!(val - 1, current_value);
|
let _removed = self.jumps.remove(0);
|
||||||
assert_eq!(removed, (0, val - 1));
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
debug_assert_eq!(_val - 1, current_value);
|
||||||
|
assert_eq!(_removed, (0, _val - 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,21 +391,8 @@ impl MonotonicSequence {
|
|||||||
}; // always 1 behind => lagging
|
}; // always 1 behind => lagging
|
||||||
let mut jumps = vec![(0, lagging_value)];
|
let mut jumps = vec![(0, lagging_value)];
|
||||||
vec.iter().enumerate().skip(1).try_for_each(|(ind, &val)| {
|
vec.iter().enumerate().skip(1).try_for_each(|(ind, &val)| {
|
||||||
// if val > lagging_value + 1 {
|
|
||||||
// return Err(SequenceError::ValueTooHigh {
|
|
||||||
// pos: ind,
|
|
||||||
// attempted: val,
|
|
||||||
// max_allowed: lagging_value + 1,
|
|
||||||
// });
|
|
||||||
// } else if val < lagging_value {
|
|
||||||
// return Err(SequenceError::ValueTooLow {
|
|
||||||
// pos: ind,
|
|
||||||
// attempted: val,
|
|
||||||
// min_allowed: lagging_value,
|
|
||||||
// });
|
|
||||||
// } else
|
|
||||||
|
|
||||||
Self::can_set_mini(ind, val, (lagging_value, lagging_value + 1))?;
|
Self::can_set_mini(ind, val, (lagging_value, lagging_value + 1))?;
|
||||||
|
|
||||||
if val == lagging_value + 1 {
|
if val == lagging_value + 1 {
|
||||||
jumps.push((ind, val));
|
jumps.push((ind, val));
|
||||||
}
|
}
|
||||||
@@ -390,15 +411,19 @@ impl MonotonicSequence {
|
|||||||
let len = self.get_jump_index(pos) + 1;
|
let len = self.get_jump_index(pos) + 1;
|
||||||
self.jumps.truncate(len);
|
self.jumps.truncate(len);
|
||||||
}
|
}
|
||||||
pub fn flatten_before(&mut self, pos: usize) {
|
/// push something at 0 or self.validate() will fail
|
||||||
|
fn cut_b4(&mut self, pos: usize) {
|
||||||
let len = self.get_jump_index(pos);
|
let len = self.get_jump_index(pos);
|
||||||
// let r = self.jumps[len..].to_vec();
|
// let r = self.jumps[len..].to_vec();
|
||||||
|
|
||||||
self.jumps.rotate_left(len); // damn they figured it
|
self.jumps.rotate_left(/*dbg!*/ len); // damn they figured it
|
||||||
// self.jumps.copy_within(len.., 0);
|
|
||||||
|
|
||||||
|
// self.jumps.copy_within(len.., 0);
|
||||||
self.jumps.truncate(self.jumps.len() - len);
|
self.jumps.truncate(self.jumps.len() - len);
|
||||||
// assert_eq!(r, self.jumps, "rotate tricks failed");
|
// assert_eq!(r, self.jumps, "rotate tricks failed");
|
||||||
|
}
|
||||||
|
pub fn flatten_before(&mut self, pos: usize) {
|
||||||
|
self.cut_b4(pos);
|
||||||
if let Some((ind, _)) = self.jumps.first_mut() {
|
if let Some((ind, _)) = self.jumps.first_mut() {
|
||||||
*ind = 0;
|
*ind = 0;
|
||||||
}
|
}
|
||||||
@@ -429,12 +454,44 @@ impl MonotonicSequence {
|
|||||||
self.truncate(new_size);
|
self.truncate(new_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get a copy
|
||||||
pub fn jumps(&self) -> Vec<(usize, u32)> {
|
pub fn jumps(&self) -> Vec<(usize, u32)> {
|
||||||
self.jumps.to_vec()
|
self.jumps.to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn destroy(self) -> (Vec<(usize, u32)>, usize) {
|
||||||
|
(self.jumps, self.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// rebuild
|
||||||
|
pub fn revive(jumps: Vec<(usize, u32)>, length: usize) -> Option<Self> {
|
||||||
|
let r = Self { jumps, length };
|
||||||
|
if r.validate() {
|
||||||
|
Some(r)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set after
|
||||||
|
/// if pos is too big do nothing
|
||||||
|
/// if pos == 0 you would rather self::with(val, self.len())
|
||||||
pub fn propagate_to_end(&mut self, pos: usize, val: u32) -> Result<(), SequenceError> {
|
pub fn propagate_to_end(&mut self, pos: usize, val: u32) -> Result<(), SequenceError> {
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
|
if len == 0 {
|
||||||
|
return Err(SequenceError::OutOfBounds { pos, length: len });
|
||||||
|
}
|
||||||
|
if pos == 0 {
|
||||||
|
self.jumps.truncate(1);
|
||||||
|
if let Some((_0, c)) = self.jumps.first_mut() {
|
||||||
|
debug_assert_eq!(*_0, 0);
|
||||||
|
*c = val;
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
let Some(cur) = self.get(pos - 1) else {
|
let Some(cur) = self.get(pos - 1) else {
|
||||||
|
// pos - 1 is too big for bro
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
Self::can_set_mini(pos, val, (cur, cur + 1))?;
|
Self::can_set_mini(pos, val, (cur, cur + 1))?;
|
||||||
@@ -442,10 +499,85 @@ impl MonotonicSequence {
|
|||||||
if val == cur + 1 {
|
if val == cur + 1 {
|
||||||
self.jumps.push((pos, val));
|
self.jumps.push((pos, val));
|
||||||
}
|
}
|
||||||
self.length = len;
|
// self.length = len;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// DESTRUCTIVE: if pos too big basically wipe
|
||||||
|
/// pos is kept, anything before pos is val if suitable
|
||||||
|
pub fn set_before(&mut self, pos: usize, val: u32) -> Result<(), SequenceError> {
|
||||||
|
let len = self.len();
|
||||||
|
if len == 0 {
|
||||||
|
return Err(SequenceError::OutOfBounds { pos, length: len });
|
||||||
|
}
|
||||||
|
if pos == 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(cur) = self.get(pos) else {
|
||||||
|
self.jumps.truncate(1);
|
||||||
|
if let Some((_0, c)) = self.jumps.first_mut() {
|
||||||
|
debug_assert_eq!(*_0, 0);
|
||||||
|
*c = val;
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
Self::can_set_mini(pos, val, (cur - 1, cur))?;
|
||||||
|
|
||||||
|
self.cut_b4(pos);
|
||||||
|
|
||||||
|
if let Some((curind, _curval)) = self.jumps.first_mut() {
|
||||||
|
debug_assert_eq!(*_curval, cur);
|
||||||
|
*curind = if val == cur {
|
||||||
|
0
|
||||||
|
} else if val + 1 == cur {
|
||||||
|
pos
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if val + 1 == cur {
|
||||||
|
self.jumps.insert(0, (0, val));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn first_occurence_of(&self, value: u32) -> Option<usize> {
|
||||||
|
Some(self.jumps.get(self.find_jump_index(value)?)?.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// inspired by range2
|
||||||
|
// find from value is inherently easier than find from pos
|
||||||
|
///if plug Some(at) in `self.jumps[at].1` you get value back,
|
||||||
|
/// else is because theres no such value
|
||||||
|
///
|
||||||
|
/// use this over [`get_jump_index`](MonotonicSequence::get_jump_index) if can
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use lda_strdist::common_subsequence::monotonic_sequence::MonotonicSequence;
|
||||||
|
/// # let ms = MonotonicSequence::try_from_vec(&[0,0,0,1,1,1,2,2,3,3,4,4,4]).unwrap();
|
||||||
|
/// # let (pos, val) = ms.jumps()[3];
|
||||||
|
/// let at = ms.find_jump_index(val).unwrap();
|
||||||
|
/// debug_assert_eq!(ms.jumps()[at].1, val);
|
||||||
|
/// ```
|
||||||
|
// where is the run doctest TF
|
||||||
|
pub fn find_jump_index(&self, value: u32) -> Option<usize> {
|
||||||
|
if self.is_empty() {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
assert!(self.validate());
|
||||||
|
let jump_index = (value - self.first().unwrap()) as usize;
|
||||||
|
// {
|
||||||
|
// let &(_p, _v) = self.jumps.get(jump_index)?;
|
||||||
|
// assert_eq!(_v, value);
|
||||||
|
// }
|
||||||
|
if jump_index < self.jumps.len() {
|
||||||
|
Some(jump_index)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn range2(&self, item: u32) -> Option<Range<usize>> {
|
pub fn range2(&self, item: u32) -> Option<Range<usize>> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
@@ -487,6 +619,68 @@ impl MonotonicSequence {
|
|||||||
// },
|
// },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// iter returns an iter idk
|
||||||
|
/// equal to self.[into_iter](#method.into_iter)
|
||||||
|
pub fn iter(&self) -> MonotonicIter {
|
||||||
|
self.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MonotonicIter {
|
||||||
|
/// hey dont be stupid
|
||||||
|
pub dis: VecDeque<(usize, u32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DoubleEndedIterator for MonotonicIter {
|
||||||
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
|
let (f_, v) = self.dis.back_mut()?;
|
||||||
|
let v = *v;
|
||||||
|
*f_ -= 1;
|
||||||
|
if *f_ == 0 {
|
||||||
|
self.dis.pop_back();
|
||||||
|
// return Some(self.dis.back()?.1);
|
||||||
|
}
|
||||||
|
Some(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Iterator for MonotonicIter {
|
||||||
|
type Item = u32;
|
||||||
|
// hit it from the front
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let (f_, v)= self.dis.front_mut()?;
|
||||||
|
let v = *v;
|
||||||
|
*f_ -= 1;
|
||||||
|
if *f_ == 0 {
|
||||||
|
self.dis.pop_front();
|
||||||
|
// return Some(self.dis.front()?.1);
|
||||||
|
}
|
||||||
|
Some(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for &MonotonicSequence {
|
||||||
|
type IntoIter = MonotonicIter;
|
||||||
|
type Item = u32;
|
||||||
|
|
||||||
|
// hehe
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
let dis: Vec<(usize, u32)> = self
|
||||||
|
.jumps()
|
||||||
|
.into_iter()
|
||||||
|
.chain([(self.length, 42)])
|
||||||
|
.collect();
|
||||||
|
let dis = dis
|
||||||
|
.windows(2)
|
||||||
|
.map(|w| {
|
||||||
|
let &[(f, v), (s, _)] = w else { unreachable!() };
|
||||||
|
debug_assert!(s > f);
|
||||||
|
(s - f, v)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Self::IntoIter { dis }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ai gen testcases: not quite sure because short + not updated with new methods
|
// ai gen testcases: not quite sure because short + not updated with new methods
|
||||||
@@ -513,6 +707,8 @@ mod tests {
|
|||||||
assert_eq!(seq.get(6), None);
|
assert_eq!(seq.get(6), None);
|
||||||
|
|
||||||
assert_eq!(seq.to_vec(), vec![0, 0, 1, 1, 2, 2]);
|
assert_eq!(seq.to_vec(), vec![0, 0, 1, 1, 2, 2]);
|
||||||
|
println!("{seq:?}");
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -533,6 +729,8 @@ mod tests {
|
|||||||
|
|
||||||
// Can't create invalid sequence
|
// Can't create invalid sequence
|
||||||
assert!(seq.set(3, 0).is_err());
|
assert!(seq.set(3, 0).is_err());
|
||||||
|
println!("{seq:?}");
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -549,6 +747,10 @@ mod tests {
|
|||||||
|
|
||||||
seq.set(1, 1).unwrap();
|
seq.set(1, 1).unwrap();
|
||||||
assert_eq!(seq.to_vec(), vec![0, 1, 1, 1, 2, 2]);
|
assert_eq!(seq.to_vec(), vec![0, 1, 1, 1, 2, 2]);
|
||||||
|
println!("{sec:?}");
|
||||||
|
assert!(sec.validate());
|
||||||
|
println!("{seq:?}");
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_sequence() {
|
fn test_basic_sequence() {
|
||||||
@@ -564,6 +766,11 @@ mod tests {
|
|||||||
seq.set(4, 2).unwrap();
|
seq.set(4, 2).unwrap();
|
||||||
seq.extend(6);
|
seq.extend(6);
|
||||||
assert_eq!(seq.to_vec(), vec![0, 0, 1, 1, 2, 2]);
|
assert_eq!(seq.to_vec(), vec![0, 0, 1, 1, 2, 2]);
|
||||||
|
|
||||||
|
seq.extend(10);
|
||||||
|
seq.propagate_to_end(8, 3).unwrap();
|
||||||
|
println!("{seq:?}, {tovec:?}", tovec = seq.to_vec());
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edge_cases() {
|
fn test_edge_cases() {
|
||||||
@@ -581,6 +788,8 @@ mod tests {
|
|||||||
seq.set(1, 5),
|
seq.set(1, 5),
|
||||||
Err(SequenceError::ValueTooHigh { .. })
|
Err(SequenceError::ValueTooHigh { .. })
|
||||||
));
|
));
|
||||||
|
println!("{seq:?}");
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push_pop() {
|
fn test_push_pop() {
|
||||||
@@ -592,6 +801,7 @@ mod tests {
|
|||||||
assert_eq!(seq.pop(), Some(1));
|
assert_eq!(seq.pop(), Some(1));
|
||||||
assert_eq!(seq.pop(), Some(1));
|
assert_eq!(seq.pop(), Some(1));
|
||||||
assert_eq!(seq.to_vec(), vec![0]);
|
assert_eq!(seq.to_vec(), vec![0]);
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flatten_after() {
|
fn test_flatten_after() {
|
||||||
@@ -600,8 +810,10 @@ mod tests {
|
|||||||
seq.propagate_to_end(4, 2).unwrap();
|
seq.propagate_to_end(4, 2).unwrap();
|
||||||
assert_eq!(seq.to_vec(), vec![0, 0, 1, 1, 2, 2]);
|
assert_eq!(seq.to_vec(), vec![0, 0, 1, 1, 2, 2]);
|
||||||
|
|
||||||
seq.flatten_after(3);
|
seq.flatten_after(2);
|
||||||
assert_eq!(seq.to_vec(), vec![0, 0, 1, 1, 1, 1]);
|
assert_eq!(seq.to_vec(), vec![0, 0, 1, 1, 1, 1]);
|
||||||
|
println!("{seq:?}");
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flatten_before() {
|
fn test_flatten_before() {
|
||||||
@@ -612,6 +824,9 @@ mod tests {
|
|||||||
|
|
||||||
seq.flatten_before(3);
|
seq.flatten_before(3);
|
||||||
assert_eq!(seq.to_vec(), vec![1, 1, 1, 1, 2, 2]);
|
assert_eq!(seq.to_vec(), vec![1, 1, 1, 1, 2, 2]);
|
||||||
|
println!("{seq:?}");
|
||||||
|
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -619,6 +834,7 @@ mod tests {
|
|||||||
// Valid sequence
|
// Valid sequence
|
||||||
let v = vec![0, 0, 1, 1, 2, 2];
|
let v = vec![0, 0, 1, 1, 2, 2];
|
||||||
let seq = MonotonicSequence::try_from_vec(&v).unwrap();
|
let seq = MonotonicSequence::try_from_vec(&v).unwrap();
|
||||||
|
println!("{seq:?}");
|
||||||
assert_eq!(seq.to_vec(), v);
|
assert_eq!(seq.to_vec(), v);
|
||||||
|
|
||||||
// Invalid jumps
|
// Invalid jumps
|
||||||
@@ -627,11 +843,34 @@ mod tests {
|
|||||||
MonotonicSequence::try_from_vec(&v),
|
MonotonicSequence::try_from_vec(&v),
|
||||||
Err(SequenceError::ValueTooHigh { .. })
|
Err(SequenceError::ValueTooHigh { .. })
|
||||||
));
|
));
|
||||||
|
|
||||||
|
assert!(seq.validate())
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn absolute_devastation() {
|
fn absolute_devastation() {
|
||||||
let c = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3];
|
let c = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3];
|
||||||
let mut db = MonotonicSequence::try_from_vec(&c).unwrap();
|
let mut db = MonotonicSequence::try_from_vec(&c).unwrap();
|
||||||
assert!(db.propagate_to_end(3, 2).is_err());
|
assert!(db.propagate_to_end(3, 2).is_err());
|
||||||
|
assert!(db.set_before(6, 2).is_ok());
|
||||||
|
println!("{db:?}");
|
||||||
|
assert!(db.validate())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn iter() {
|
||||||
|
let c = [
|
||||||
|
0, 0, 0, 0, 1, 1, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13,
|
||||||
|
14, 15, 16,
|
||||||
|
];
|
||||||
|
let m = MonotonicSequence::try_from_vec(&c).unwrap();
|
||||||
|
println!("{m:?}");
|
||||||
|
let mut c = c.into_iter();
|
||||||
|
let mut m = m.into_iter();
|
||||||
|
println!("{m:?}");
|
||||||
|
for f in 0..35 {
|
||||||
|
let a = c.next();
|
||||||
|
let b = m.next();
|
||||||
|
assert_eq!(a, b, "{f}: {a:?} != {b:?}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::levenshtein::EditOperation;
|
use crate::levenshtein::EditOperation;
|
||||||
|
|
||||||
pub struct EditOperationVec<'e>(pub &'e Vec<EditOperation>);
|
pub struct EditOperationVec<'e>(pub &'e Vec<EditOperation>);
|
||||||
@@ -53,3 +55,87 @@ impl std::fmt::Display for CostOperationVec<'_> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct StrDisplay<'e>(pub &'e str);
|
||||||
|
|
||||||
|
impl Display for StrDisplay<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "[")?;
|
||||||
|
for (c, i) in self.0.chars().enumerate() {
|
||||||
|
if c != 0 {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{i}")?;
|
||||||
|
}
|
||||||
|
write!(f, "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InsanelySpecific<'e> {
|
||||||
|
pub c1: &'e Vec<char>,
|
||||||
|
pub c2: &'e Vec<char>,
|
||||||
|
pub dp: &'e Vec<Vec<u32>>,
|
||||||
|
}
|
||||||
|
pub struct ColoredInsanelySpecific<'e>(pub InsanelySpecific<'e>);
|
||||||
|
|
||||||
|
impl Display for InsanelySpecific<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, " ")?;
|
||||||
|
self.c2.iter().try_for_each(|c| write!(f, " {c}"))?;
|
||||||
|
writeln!(f)?;
|
||||||
|
self.dp.iter().zip(self.c1.iter()).try_for_each(|(v, c)| {
|
||||||
|
v.iter().try_for_each(|g| write!(f, "{g} "))?;
|
||||||
|
writeln!(f, "{c}")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ColoredInsanelySpecific<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let s = &self.0;
|
||||||
|
|
||||||
|
write!(f, "-")?;
|
||||||
|
for i in s.c2 {
|
||||||
|
write!(f, " {i}")?;
|
||||||
|
}
|
||||||
|
writeln!(f)?;
|
||||||
|
use lda_ansi::ansi_backbone::Style as StyleConstruct;
|
||||||
|
use lda_ansi::ansi_colors_2::ansi_color_interface::ColorContext;
|
||||||
|
use lda_ansi::ansi_colors_2::Color;
|
||||||
|
use lda_ansi::ansi_colors_2::CustomColor;
|
||||||
|
use lda_ansi::ansi_styles::Style;
|
||||||
|
// use lda_ansi::AnsiStyles;
|
||||||
|
|
||||||
|
let hl = StyleConstruct::new().color(Color::Green.fg()).to_owned();
|
||||||
|
// let hl = AnsiStyles::new().style(hl);
|
||||||
|
let dim = StyleConstruct::new()
|
||||||
|
.color(CustomColor::Color256(236).fg())
|
||||||
|
.to_owned();
|
||||||
|
let reset = StyleConstruct::new().style(Style::Reset).to_owned();
|
||||||
|
// let reset = AnsiStyles::new().style(reset);
|
||||||
|
let b = s.dp[0][0] as usize;
|
||||||
|
let mut idfk = vec![b];
|
||||||
|
|
||||||
|
for (v, c) in s.dp.iter().zip(['-'].iter().chain(s.c1)) {
|
||||||
|
write!(f, "{dim}")?;
|
||||||
|
for (ind, v) in v.iter().enumerate() {
|
||||||
|
if let Some(old) = idfk.get_mut(*v as usize - b) {
|
||||||
|
if *old > ind {
|
||||||
|
write!(f, "{hl}{v}{dim} ")?;
|
||||||
|
*old = ind;
|
||||||
|
// continue;
|
||||||
|
} else {
|
||||||
|
write!(f, "{v} ")?;
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
write!(f, "{hl}{v}{dim} ")?;
|
||||||
|
idfk.push(ind);
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeln!(f, "{reset}{c}")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user