pub fn lzw_encode<T: Clone + PartialEq>(
input: &[T],
initial: &[T],
max_lookahead: usize,
) -> Vec<usize> {
let mut dictionary: Vec<Vec<T>> = Vec::with_capacity(initial.len());
for i in initial {
dictionary.push(vec![i.clone()]);
}
let mut output: Vec<usize> = Vec::new();
let mut i = 0;
while i < input.len() {
let mut longest_prefix: Option<usize> = None;
for (idx, entry) in dictionary.iter().enumerate() {
let entry_len = entry.len();
if entry_len > max_lookahead
|| i + entry_len > input.len()
|| input[i..i + entry_len] != *entry
{
continue;
}
if let Some(longest) = &mut longest_prefix {
if entry_len > dictionary[*longest].len() {
*longest = idx;
}
} else {
longest_prefix = Some(idx);
}
}
if let Some(idx) = longest_prefix {
i += dictionary[idx].len();
output.push(idx);
if i < input.len() {
let next_char = input[i].clone();
let mut new_entry = dictionary[idx].clone();
new_entry.push(next_char);
if !dictionary.contains(&new_entry) {
dictionary.push(new_entry);
}
}
} else {
panic!("No match found in dictionary");
}
}
return output;
}
pub fn lzw_decode<T: Clone + PartialEq>(input: &[usize], initial: &[T]) -> Vec<T> {
let mut dictionary: Vec<Vec<T>> = Vec::with_capacity(initial.len());
for i in initial {
dictionary.push(vec![i.clone()]);
}
let mut output: Vec<T> = Vec::new();
let mut i = 0;
while i < input.len() {
let idx = input[i];
let entry = dictionary[idx].clone();
output.extend(entry.clone()); if i + 1 < input.len() {
let next_idx = input[i + 1];
if next_idx < dictionary.len() {
let next_entry = dictionary[next_idx].clone();
let mut new_entry = entry.clone();
new_entry.push(next_entry[0].clone());
if !dictionary.contains(&new_entry) {
dictionary.push(new_entry);
}
} else {
let mut new_entry = entry.clone();
new_entry.push(entry[0].clone()); if !dictionary.contains(&new_entry) {
dictionary.push(new_entry);
}
}
}
i += 1;
}
return output;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lzw() {
let input = b"ABABABABA";
let initial = b"AB";
let encoded = lzw_encode(input, initial, 4);
assert_eq!(encoded, vec![0, 1, 2, 4, 3]);
}
#[test]
fn test_lzw_decode() {
let input = b"ABABABABA";
let initial = b"AB";
let encoded = lzw_encode(input, initial, 4);
let decoded = lzw_decode(&encoded, initial);
assert_eq!(input.to_vec(), decoded);
}
#[test]
fn test_rabarbar() {
let input = b"rabarbarbar";
let initial = b"rab";
let encoded = lzw_encode(input, initial, 4);
assert!(encoded.len() < input.len());
let decoded = lzw_decode(&encoded, initial);
assert_eq!(input, decoded.as_slice());
}
}