am i happy

This commit is contained in:
lda committed 2025-01-21 01:38:29 +07:00
1 parent bfc7eab495
commit 39f466c59a
3 files changed
+612 -259

No files matched your search

+203 -258
View File
@@ -2,9 +2,17 @@
use std::ops::Range; use std::ops::Range;
/// a vec like struct, where everything is ever increasing and not by anything more than one. /// Represents a compressed sequence of monotonically increasing numbers where
/// adjacent values can only differ by 0 or 1.
/// ///
/// so you can have 1, 2, 3, 4, 5 but not 0, 1, 1, 1, 3 /// # Examples
/// ```
/// # use lda_strdist::common_subsequence::db::DB;
/// let mut db = DB::new();
/// db.push(0); // [0]
/// db.push(0); // [0, 0]
/// db.push(1); // [0, 0, 1]
/// ```
#[derive(Debug, Default, PartialEq, Clone)] #[derive(Debug, Default, PartialEq, Clone)]
pub struct DB { pub struct DB {
/// inner starts from index 0 but inner\[0\] is the point where DB::vec is 1 /// inner starts from index 0 but inner\[0\] is the point where DB::vec is 1
@@ -13,80 +21,78 @@ pub struct DB {
} }
impl DB { impl DB {
fn verify_increasing(&self) { /// Validates the `DB` instance.
assert!( pub fn validate(&self) -> Result<(), String> {
matches!( if !self.inner.windows(2).all(|w| w[0] < w[1]) {
self.inner.iter().try_fold(&u32::MIN, |lastele, current| { return Err("Inner vector must be strictly increasing".to_string());
if current > lastele { }
Some(current) if self.inner.last().map_or(false, |&x| x >= self.len) {
} else { return Err("Inner values must be less than len".to_string());
None }
} Ok(())
}),
Some(_)
), // what the fuck is this
"the inner vec should be ever increasing, which it is not"
);
} }
fn verify_len(&self) {
let selflen = self.len();
assert!(self.inner.last().unwrap_or(&0) < &selflen
&& !self.inner.iter().any(|f| f >= &selflen),
"the inner vector elements denote at what indexes the DB::vec(&self) vec value jumps up by one, and so any inner elements should not exceed self.len(), which some of them do"); /// Creates a new `DB` instance.
}
pub fn verify(&self) {
self.verify_len();
self.verify_increasing();
}
pub fn new() -> Self { pub fn new() -> Self {
Default::default() Default::default()
} }
/// Creates a new `DB` instance with a specified length.
pub fn with_len(len: u32) -> Self { pub fn with_len(len: u32) -> Self {
Self { Self {
len, len,
..Default::default() ..Default::default()
} }
} }
pub fn push(&mut self, val: u32) { /// Adds a value to the sequence.
pub fn push(&mut self, val: u32) -> Result<(), String> {
let last = self.last().unwrap_or_default(); let last = self.last().unwrap_or_default();
if val == last + 1 { match val {
self.inner.push(self.len()); v if v == last + 1 => {
self.len += 1; self.inner.push(self.len());
} else if val == last { self.len += 1;
self.len += 1; Ok(())
} else { }
panic!("trying value {val} is not equal or one bigger than current last {last}"); v if v == last => {
self.len += 1;
Ok(())
}
_ => Err(format!(
"Value {val} is not equal or one bigger than current last {last}"
)),
} }
} }
/// Returns the last value in the sequence.
fn last(&self) -> Option<u32> { fn last(&self) -> Option<u32> {
if self.len() > 0 { if self.len > 0 {
Some(self.inner.len() as _) Some(self.inner.len() as u32)
} else { } else {
None None
} }
} }
pub fn pop(&mut self) -> Option<u32> {
let returnvalue = self.last(); /// Returns the length of the sequence.
if let Some(_) = returnvalue {
if let Some(bro) = self.inner.last() {
if self.len() - bro == 1 {
self.inner.pop();
} else if self.len() < *bro {
panic!("run DB::verify_len(&self) ")
}
// self.len -= 1;
// }
// else {
}
// self.len.checked_sub(1);
self.len -= 1
}
return returnvalue;
}
fn len(&self) -> u32 { fn len(&self) -> u32 {
self.len self.len
} }
/// Removes the last value from the sequence.
pub fn pop(&mut self) -> Option<u32> {
let return_value = self.last();
if let Some(_) = return_value {
if let Some(&last_inner) = self.inner.last() {
if self.len - last_inner == 1 {
self.inner.pop();
} else if self.len < last_inner {
panic!("run DB::validate(&self)");
}
}
self.len -= 1;
}
return_value
}
/// 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
@@ -106,71 +112,58 @@ impl DB {
``` ```
*/ */
pub fn get(&self, ind: u32) -> Option<u32> { pub fn get(&self, ind: u32) -> Option<u32> {
if self.len() <= ind { if self.len <= ind {
// panic!("index {ind} >= len {selflen} which is ugly")
return None; return None;
} }
(&self.inner) Some(
.iter() self.inner
.rposition(|f| ind >= *f) // imagine got 7 > 4, and 4 is at index 2, so the value of 7 is 2 .iter()
.map(|c| c as u32 + 1) // hack .rposition(|&f| ind >= f)
.or(Some(0)) .map_or(0, |c| c as u32 + 1),
)
} }
pub fn range_of(&self, ele: u32) -> Option<Range<u32>> {
if ele == 0 { /// Returns the range of indices where a value appears.
Some(0..*self.inner.get(0).unwrap_or(&self.len())) pub fn range_of(&self, value: u32) -> Option<Range<u32>> {
} else if ele > self.last().unwrap_or_default() { if value == 0 {
None return Some(0..self.inner.first().copied().unwrap_or(self.len));
} else {
Some(
*self.inner.get(ele as usize - 1).unwrap_or(&self.len())
..*self.inner.get(ele as usize).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),
)
} }
// the same with range of we have // the same with range of we have
/// Determines the available values for a given index.
///index can be numbers in output.0, and output.1 tell you to select the bigger number at .0.1 ///index can be numbers in output.0, and output.1 tell you to select the bigger number at .0.1
/// ///
/// output: (two numbers that can be, can be the same), (should be the other number; should be appending) /// output: (two numbers that can be, can be the same), (should be the other number; should be appending; is the current number)
/// ///
/// must check for in len() range by yourself /// must check for in len() range by yourself
pub fn available_values(&self, ind: u32) -> (Option<[u32; 2]>, Option<bool>) { pub fn available_values(&self, ind: u32) -> (Option<[u32; 2]>, Option<bool>) {
// let mut last_ind: u32 = 0; for (&cur_ind, cur_val) in self.inner.iter().chain([self.len].iter()).zip(1u32..) {
for (&cur_ind, cur_val) in // ([0].iter()).chain
(self.inner.iter()).chain([self.len()].iter()).zip(1u32..)
{
// exactly at 3 == 3
if ind == cur_ind { if ind == cur_ind {
// bug if vec[0] = 0 // no more let choose = if cur_val >= self.inner.len() as u32
// if cur_val == 0 {
// // at 0 where there is nothing before it
// return (Some([0, 0]), None);
// } else {
// at exactly eg 3, 8, 49, or the end where you can have another
// end
let choose = if cur_val >= self.inner.len() as _
|| cur_ind + 1 < self.inner[cur_val as usize] || cur_ind + 1 < self.inner[cur_val as usize]
// not immediate
{ {
Some(true) Some(true)
} else { } else {
None None
}; };
return (Some([cur_val - 1, cur_val]), choose); return (Some([cur_val - 1, cur_val]), choose);
// }
} else if ind + 1 == cur_ind { } else if ind + 1 == cur_ind {
// right before a number you can change the value and it is still ever increasing
// not immediate (not sandwiched)
// if cur_val - 2 passes then cur_val is not self.inner.len() (??)
let choose = if (cur_val - 1) let choose = if (cur_val - 1)
.checked_sub(1) .checked_sub(1)
.and_then(|c| self.inner.get(c as usize)) .and_then(|c| self.inner.get(c as usize))
.map(|c| *c < ind) .map(|&c| c < ind)
.unwrap_or(0 < ind) .unwrap_or(0 < ind)
|| cur_ind == self.len() || cur_ind == self.len
// end
{ {
Some(false) Some(false)
} else { } else {
@@ -178,30 +171,23 @@ impl DB {
}; };
return (Some([cur_val - 1, cur_val]), choose); return (Some([cur_val - 1, cur_val]), choose);
} else if ind < cur_ind { } else if ind < cur_ind {
// at the first instance where cur_ind > ind is where you know we have crossed it
// also it passed the == and -1 check.
// also it cant be bigger than cur_ind making it the last ind actually
// so we use the last val that corresponds
return (Some([cur_val - 1, cur_val - 1]), None); return (Some([cur_val - 1, cur_val - 1]), None);
} }
// last_ind = cur_ind;
} }
(None, None) (None, None)
} }
// result? change depend on up is not none // result? change depend on up is not none
/// Changes the value at a given index.
pub fn change(&mut self, ind: u32, val: u32) { pub fn change(&mut self, ind: u32, val: u32) {
let (avail, up) = self.available_values(ind); let (avail, up) = self.available_values(ind);
if let (Some(avail), Some(up)) = (avail, up) { if let (Some(avail), Some(up)) = (avail, up) {
if val == avail[0] && up { if val == avail[0] && up {
if self.inner.len() == val as _ { if self.inner.len() == val as usize {
self.inner.push(ind); self.inner.push(ind);
} else { } else {
self.inner.get_mut(val as usize).map(|e| *e += 1); self.inner.get_mut(val as usize).map(|e| *e += 1);
}; }
// } else if val == avail[0] && !up {
// self.inner.get_mut(val as usize).map(|e| *e -= 1);
} else if val == avail[1] && !up { } else if val == avail[1] && !up {
self.inner self.inner
.get_mut(avail[0] as usize) .get_mut(avail[0] as usize)
@@ -211,16 +197,15 @@ impl DB {
} }
} }
/// Propagates a value to the end of the sequence.
/// override everything from ind on, that is if ind / val is good /// override everything from ind on, that is if ind / val is good
pub fn propagate_to_end(&mut self, ind: u32, val: u32) { pub fn propagate_to_end(&mut self, ind: u32, val: u32) {
// println!("idn = {ind}, vala{val}"); if ind >= self.len {
if ind >= self.len() { panic!("uh oh out of bounds: {ind} >= {}", self.len);
panic!("uh oh out of bounds: {ind} >={}", self.len())
} }
if self.len() > 0 { if self.len > 0 {
if matches!(self.last(), Some(x) if (x) > 0) { if matches!(self.last(), Some(x) if x > 0) {
match self.get(ind) { match self.get(ind) {
// what is this fucking logic idk man what the fuck is this code
Some(vecv) if vecv == val => { Some(vecv) if vecv == val => {
self.inner.truncate(val as usize); self.inner.truncate(val as usize);
} }
@@ -231,49 +216,48 @@ impl DB {
Some(x) if val == x - 1 && self.inner[val as usize] == ind => { Some(x) if val == x - 1 && self.inner[val as usize] == ind => {
self.inner.truncate(val as usize); self.inner.truncate(val as usize);
} }
None => { None => unreachable!("len is > 0"),
unreachable!("len is > 0")
}
_ => {} _ => {}
} }
} else { } else if val == 1 {
if val == 1 { self.inner.push(ind);
self.inner.push(ind);
}
} }
// println!("{:?}", self.inner)
} }
} }
/// Converts the compressed sequence back to a full vector.
pub fn vec(&self) -> Vec<u32> { pub fn vec(&self) -> Vec<u32> {
let mut count = (0..).into_iter(); let mut count = (0..).into_iter();
self.inner self.inner
.iter() .iter()
.chain([self.len()].iter()) .chain([self.len].iter())
.scan(0u32, |c, f| { .scan(0u32, |c, &f| {
let r = Some(vec![count.next().unwrap(); (*f - *c) as usize]); let r = Some(vec![count.next().unwrap(); (f - *c) as usize]);
*c = *f; *c = f;
return r; r
}) })
.flatten() .flatten()
.collect() .collect()
} }
/// Creates a `DB` instance from a full vector.
pub fn try_from_vec(v: Vec<u32>) -> Option<Self> { pub fn try_from_vec(v: Vec<u32>) -> Option<Self> {
// let mut count = (0..).into_iter(); let len = v.len() as u32;
let len = v.len() as _; let mut inner = Vec::new();
let mut inner: Vec<u32> = vec![];
let mut c = 0u32; let mut c = 0u32;
for (i, f) in v.iter().enumerate() { for (i, &f) in v.iter().enumerate() {
if c + 1 == *f { if c + 1 == f {
inner.push(i as _); inner.push(i as u32);
} else if c + 1 < *f || c > *f { } else if c + 1 < f || c > f {
return None; return None;
}; }
c = *f; c = f;
} }
Some(Self { inner, len }) Some(Self { inner, len })
} }
} }
/// working as intended: i am happy
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::DB; use super::DB;
@@ -287,7 +271,7 @@ mod test {
inner: ctodb, inner: ctodb,
len: clen, len: clen,
}; };
ctodb.verify(); assert!(ctodb.validate().is_ok());
assert_eq!(ctodb.vec(), c); assert_eq!(ctodb.vec(), c);
} }
#[test] #[test]
@@ -352,7 +336,7 @@ mod test {
let mut db = DB::new(); let mut db = DB::new();
let mut c = vec![]; let mut c = vec![];
let mut push = |i| { let mut push = |i| {
db.push(i); db.push(i).unwrap();
c.push(i); c.push(i);
}; };
for _ in 0..6 { for _ in 0..6 {
@@ -377,17 +361,17 @@ mod test {
fn invalid_push() { fn invalid_push() {
let mut db = DB::new(); let mut db = DB::new();
// dbg!(&db.inner); // dbg!(&db.inner);
db.push(1); db.push(1).unwrap();
// dbg!(&db.inner); // dbg!(&db.inner);
for _ in 3..=11 { for _ in 3..=11 {
db.push(1) db.push(1).unwrap();
} }
// dbg!(&db.inner); // dbg!(&db.inner);
// dbg!(db.vec()); // dbg!(db.vec());
db.push(2); db.push(2).unwrap();
dbg!(db.len() != 0); dbg!(db.len() != 0);
db.push(4); db.push(4).expect("this is the one");
} }
#[test] #[test]
#[should_panic] #[should_panic]
@@ -395,13 +379,13 @@ mod test {
let mut db = DB::new(); let mut db = DB::new();
// dbg!(&db.inner); // dbg!(&db.inner);
db.push(0); db.push(0).unwrap();
db.push(1); db.push(1).unwrap();
// dbg!(&db.inner); // dbg!(&db.inner);
// dbg!(db.vec()); // dbg!(db.vec());
db.push(2); db.push(2).unwrap();
dbg!(db.len() != 0); dbg!(db.len() != 0);
db.push(1); db.push(1).expect("this is the one yall");
} }
#[test] #[test]
@@ -541,6 +525,84 @@ mod test {
assert_eq!(db, db2); 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] #[test]
fn prop_idk() { fn prop_idk() {
let c = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13]; let c = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13];
@@ -606,120 +668,3 @@ mod test {
} }
} }
} }
// // [0,0,0,1,1,1,2,2,3] 9
// // 0,1,2,3,4,5,6,7,8
// // [ 3, 6, 8]
// fn change(&mut self, ind: u32, to: u32) {
// // change means that the index is valid: 0..self.len(), if anything other than that crash
// let Some(vec_ind_plus_one) = self.get(ind) else {
// panic!("index not cool")
// };
// // vec_ind_plus_one is from 1 to self.inner.len(),
// // // index is valid
// let last_ = self.inner.len() as u32; // last element == last index + 1
// assert!(if last_ == 0 {
// vec_ind_plus_one == 0
// } else {
// vec_ind_plus_one <= last_
// });
// // // panic if to is too big
// if to > last_ + 1 {
// panic!("pushing something too big: {to} is way big compared to biggest number {last_}")
// }
// // // to is now ok
// assert!(to <= last_ + 1);
// // // if vec has 0 size, all cases
// if last_ == 0 {
// if to == 0 {
// return;
// } else if to != 1 {
// panic!("{to} way bigger than {vec_ind_plus_one} which is not cool")
// }
// // everything is 0, index is valid
// self.inner.push(ind);
// return;
// }
// assert_ne!(vec_ind_plus_one, 0);
// assert_ne!(last_, 0);
// // vec[vec_ind] is going to be the first number that we care about
// let vec_ind = vec_ind_plus_one - 1;
// let ind_this = self.inner[vec_ind as usize];
// assert!(ind_this <= ind);
// let Some(&ind_next) = self.inner.get(vec_ind_plus_one as usize) else {
// // ind is in range of ind_this..self.len()
// assert_eq!(ind_this, last_);
// // if to == vec_ind + 1 {
// // // this is the case here
// // }
// if ind == self.len() - 1 && to == last_ + 1 {
// self.inner.push(ind);
// return;
// }
// // if to > last_ + 1 {
// // panic!("uh we done this before")
// // }
// else if to == last_ - 1 && ind_this == ind {
// // if let Some(c) = self.inner.last_mut() {
// // *c += 1;
// // }
// // else {
// // unreachable!()
// // }
// // or
// self.inner[to as usize] += 1;
// return;
// } else if !(to == last_ && ind_this < ind) {
// panic!("ever increasing vec")
// }
// return;
// };
// assert!(ind < ind_next);
// let ideal_to = vec_ind_plus_one;
// if to == ideal_to && (ind_this..ind_next).contains(&ind) {
// return;
// } else if to == ideal_to + 1 && ind == ind_next - 1 {
// self.inner[to as usize] -= 1;
// return;
// } else if ind_this > 0 {
// }
// // // vec is NOT 0 size now
// // // let &last_changing_index = self
// // // .inner
// // // .last()
// // // .expect("somehow this panics; self.inner.len() != 0");
// // // for the range of the last element (DB::vec from first element == last_ to end)
// // // if ind is strictly bigger than inner.last() and to is equal to last_
// // // if ind > last_changing_index && to == last_ {
// // // self.inner.push(ind);
// // // return;
// // // }
// // //literally the last element
// // // if to is 0
// // // and vec is not 0, so vec[0] has to exist
// // if to == 0 {
// // // if nothing
// // if ind < self.inner[0] {
// // return;
// // }
// // if ind == self.inner[0] {
// // self.inner[0] += 1;
// // return;
// // }
// // }
// // // if to is not 0,
// // else if true {
// // }
// // return;
// }
+348
View File
@@ -0,0 +1,348 @@
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.len() == 0 {
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);
}
}
+61 -1
View File
@@ -1,6 +1,8 @@
use db::DB; use db::DB;
// use db2::{DBError, DB as DB2};
pub mod db; pub mod db;
pub mod db2;
pub fn lcs_gen(str1: &str, str2: &str) -> Vec<Vec<u32>> { pub fn lcs_gen(str1: &str, str2: &str) -> Vec<Vec<u32>> {
let c1: Vec<char> = str1.chars().collect(); let c1: Vec<char> = str1.chars().collect();
@@ -62,12 +64,50 @@ pub fn lcs_gen_db(str1: &str, str2: &str) -> Vec<DB> {
db db
} }
// #[allow(non_camel_case_types)]
// #[derive(Debug)]
// pub enum belper {
// DBE(DBError),
// None,
// }
// pub fn lcs_gen_dbai(str1: &str, str2: &str) -> Result<Vec<DB2>, belper> {
// let c1: Vec<char> = str1.chars().collect();
// let c1len = c1.len();
// let c2: Vec<char> = str2.chars().collect();
// let c2len = c2.len();
// let mut db: Vec<DB2> = vec![DB2::with_len(c2len as u32 + 1); c1len + 1];
// if c1len * c2len == 0 {
// // for i in &db {
// // println!("{i:?}")
// // }
// return Ok(db);
// }
// for i in 1..=c1len {
// for j in 1..=c2len {
// if c1[i - 1] == c2[j - 1] {
// let val = db[i - 1].get(j as u32 - 1).ok_or(belper::None)? + 1;
// db[i].push(val).map_err(|c| belper::DBE(c))?;
// } else {
// let val = db[i]
// .get(j as u32 - 1)
// .ok_or(belper::None)?
// .max(db[i - 1].get(j as _).ok_or(belper::None)?);
// db[i].push(val).map_err(|c| belper::DBE(c))?;
// }
// }
// }
// // for i in &db {
// // println!("{i:?}")
// // }
// Ok(db)
// }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
// use crate::common_subsequence::{db2::DB as DB2, lcs_gen_dbai};
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() {
@@ -142,6 +182,26 @@ mod test {
.collect(); .collect();
assert_eq!(c, s) assert_eq!(c, s)
} }
// #[test]
// fn test_dbai() {
// // CURRENTLY BREAKING IDFK idk IDKF
// let s: Vec<Vec<u32>> = vec![
// vec![0, 0, 0, 0, 0, 0, 0, 0],
// vec![0, 0, 0, 0, 0, 0, 1, 1],
// vec![0, 1, 1, 1, 1, 1, 1, 1],
// vec![0, 1, 1, 2, 2, 2, 2, 2],
// vec![0, 1, 1, 2, 2, 2, 2, 2],
// vec![0, 1, 1, 2, 3, 3, 3, 3],
// vec![0, 1, 1, 2, 3, 3, 3, 4],
// vec![0, 1, 2, 2, 3, 3, 3, 4],
// ];
// let c: Vec<Vec<u32>> = lcs_gen_dbai("XMJYAUZ", "MZJAWXU")
// .expect("oops")
// .iter()
// .map(DB2::to_vec)
// .collect();
// assert_eq!(c, s)
// }
#[test] #[test]
fn test_empty() { fn test_empty() {
lcs_gen("", ""); lcs_gen("", "");