Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
* [Xor](https://github.com/TheAlgorithms/Rust/blob/master/src/ciphers/xor.rs)
* Compression
* [Run Length Encoding](https://github.com/TheAlgorithms/Rust/blob/master/src/compression/run_length_encoding.rs)
* [Move-To-Front Encoding](https://github.com/TheAlgorithms/Rust/blob/master/src/compression/move_to_front.rs)
* Conversions
* [Binary To Decimal](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/binary_to_decimal.rs)
* [Binary To Hexadecimal](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/binary_to_hexadecimal.rs)
Expand Down
2 changes: 2 additions & 0 deletions src/compression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod move_to_front;
mod run_length_encoding;

pub use self::move_to_front::{move_to_front_decode, move_to_front_encode};
pub use self::run_length_encoding::{run_length_decode, run_length_encode};
60 changes: 60 additions & 0 deletions src/compression/move_to_front.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// https://en.wikipedia.org/wiki/Move-to-front_transform

fn blank_char_table() -> Vec<char> {
(0..=255).map(|ch| ch as u8 as char).collect()
}

pub fn move_to_front_encode(text: &str) -> Vec<u8> {
let mut char_table = blank_char_table();
let mut result = Vec::new();

for ch in text.chars() {
if let Some(position) = char_table.iter().position(|&x| x == ch) {
result.push(position as u8);
char_table.remove(position);
char_table.insert(0, ch);
}
}

result
}

pub fn move_to_front_decode(encoded: &[u8]) -> String {
let mut char_table = blank_char_table();
let mut result = String::new();

for &pos in encoded {
let ch = char_table[pos as usize];
result.push(ch);
char_table.remove(pos as usize);
char_table.insert(0, ch);
}

result
}

#[cfg(test)]
mod test {
use super::*;

macro_rules! test_mtf {
($($name:ident: ($text:expr, $encoded:expr),)*) => {
$(
#[test]
fn $name() {
assert_eq!(move_to_front_encode($text), $encoded);
assert_eq!(move_to_front_decode($encoded), $text);
}
)*
}
}

test_mtf! {
empty: ("", &[]),
single_char: ("@", &[64]),
repeated_chars: ("aaba", &[97, 0, 98, 1]),
mixed_chars: ("aZ!", &[97, 91, 35]),
word: ("banana", &[98, 98, 110, 1, 1, 1]),
special_chars: ("\0\n\t", &[0, 10, 10]),
}
}