This commit is contained in:
lda committed 2025-01-23 01:12:41 +07:00
1 parent 9843797733
commit 055d3331ce
6 files changed
+469 -1385

No files matched your search

+1 -411
View File
@@ -256,414 +256,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());
}
}
}
+407
View File
@@ -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());
}
}
-761
View File
@@ -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());
// // }
// // }
// }
-206
View File
@@ -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]);
}
}
-4
View File
@@ -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>> {
+61 -3
View File
@@ -1,5 +1,5 @@
//! 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::ops::Range;
@@ -55,7 +55,18 @@ 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.get_jump_index(pos);
debug_assert_eq!(ms.jumps()[at].0, pos);
let at = ms.find_jump_index(val).unwrap();
debug_assert_eq!(ms.jumps()[at].1, val);
``` */
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,11 +83,13 @@ 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
/// ///
/// this would return none if pos >= self.len() /// this would return none if pos >= self.len()
///
pub fn get(&self, pos: usize) -> Option<u32> { pub fn get(&self, pos: usize) -> Option<u32> {
// check for bounds // check for bounds
if pos >= self.length { if pos >= self.length {
@@ -160,12 +173,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
/// manual use only
pub fn can_set_mini( pub 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,
@@ -204,6 +219,12 @@ impl MonotonicSequence {
assert_eq!(current_value, max); // solid logic assert_eq!(current_value, max); // solid logic
let at = self.get_jump_index(pos); let at = self.get_jump_index(pos);
debug_assert_eq!(self.jumps[at].0, pos); debug_assert_eq!(self.jumps[at].0, pos);
#[cfg(debug_assertions)]
{
let at2 = self.find_jump_index(current_value).unwrap(); // because current value is in it
assert_eq!(at2, at);
debug_assert_eq!(self.jumps[at2].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
@@ -237,6 +258,12 @@ impl MonotonicSequence {
// TODO: pos misuse? // TODO: pos misuse?
let at = self.get_jump_index(pos + 1); // should land at let at = self.get_jump_index(pos + 1); // should land at
debug_assert_eq!(self.jumps[at].0, pos + 1); debug_assert_eq!(self.jumps[at].0, pos + 1);
#[cfg(debug_assertions)]
{
let at2 = self.find_jump_index(value).unwrap(); // because current value is in it
assert_eq!(at2, at);
debug_assert_eq!(self.jumps[at2].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?
@@ -446,6 +473,37 @@ impl MonotonicSequence {
Ok(()) Ok(())
} }
// inspired by range2
// find from value is inherently easier than find from pos
/// 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.get_jump_index(pos);
debug_assert_eq!(ms.jumps()[at].0, pos);
let at = ms.find_jump_index(val).unwrap();
debug_assert_eq!(ms.jumps()[at].1, val);
``` */
pub fn find_jump_index(&self, value: u32) -> Option<usize> {
if self.is_empty() {
return None;
};
debug_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;