am i happy
This commit is contained in:
1 parent
bfc7eab495
commit
39f466c59a
3 files changed
+606
-253
No files matched your search
+197
-252
@@ -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)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}),
|
if self.inner.last().map_or(false, |&x| x >= self.len) {
|
||||||
Some(_)
|
return Err("Inner values must be less than len".to_string());
|
||||||
), // what the fuck is this
|
}
|
||||||
"the inner vec should be ever increasing, which it is not"
|
Ok(())
|
||||||
);
|
|
||||||
}
|
}
|
||||||
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 {
|
||||||
|
v if v == last + 1 => {
|
||||||
self.inner.push(self.len());
|
self.inner.push(self.len());
|
||||||
self.len += 1;
|
self.len += 1;
|
||||||
} else if val == last {
|
Ok(())
|
||||||
|
}
|
||||||
|
v if v == last => {
|
||||||
self.len += 1;
|
self.len += 1;
|
||||||
} else {
|
Ok(())
|
||||||
panic!("trying value {val} is not equal or one bigger than current last {last}");
|
}
|
||||||
|
_ => 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)
|
|
||||||
.iter()
|
|
||||||
.rposition(|f| ind >= *f) // imagine got 7 > 4, and 4 is at index 2, so the value of 7 is 2
|
|
||||||
.map(|c| c as u32 + 1) // hack
|
|
||||||
.or(Some(0))
|
|
||||||
}
|
|
||||||
pub fn range_of(&self, ele: u32) -> Option<Range<u32>> {
|
|
||||||
if ele == 0 {
|
|
||||||
Some(0..*self.inner.get(0).unwrap_or(&self.len()))
|
|
||||||
} else if ele > self.last().unwrap_or_default() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(
|
Some(
|
||||||
*self.inner.get(ele as usize - 1).unwrap_or(&self.len())
|
self.inner
|
||||||
..*self.inner.get(ele as usize).unwrap_or(&self.len()),
|
.iter()
|
||||||
|
.rposition(|&f| ind >= f)
|
||||||
|
.map_or(0, |c| c 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),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
|
||||||
// }
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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("", "");
|
||||||
|
|||||||
Reference in new issue
Block a user