diff --git a/compressed.bin b/compressed.bin new file mode 100644 index 0000000..1daf88c Binary files /dev/null and b/compressed.bin differ diff --git a/src/main.rs b/src/main.rs index 6e75c83..1b99bb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,99 @@ -use std::{collections::HashMap, env}; +use std::{ + collections::HashMap, + env, + fs::File, + io::{Read, Write}, + path::Path, +}; fn main() { - println!("Hello, world!"); let args: Vec = env::args().collect(); + let file_name = Path::new(&args[1]); + + let content = read_file(file_name); + let stats = get_stats(&content); + let tree = create_tree(stats); + + let result = compress(content, tree); + + std::io::stdout() + .write_all(&result) + .expect("Couldn't write the result"); } -fn get_stats(text: String) -> HashMap { - todo!() +fn read_file(path: &Path) -> String { + let mut file = File::open(path).expect("Can't open file"); + + let mut contents = String::new(); + file.read_to_string(&mut contents) + .expect("Couldn't read the file"); + + contents +} + +fn get_stats(text: &String) -> HashMap { + let mut letters = HashMap::new(); + + for letter in text.chars() { + *letters.entry(letter.to_string()).or_insert(0) += 1; + } + + letters +} + +fn create_tree(letters: HashMap) -> HashMap { + let mut tree = HashMap::new(); + let mut sorted: Vec = letters.keys().cloned().collect(); + + sorted.sort_by_key(|key| std::cmp::Reverse(letters[key])); + + let mut a: u32 = 0; + + for letter in sorted { + let mut zeroes = "".to_string(); + + for _ in 0..a { + zeroes.push('0'); + } + + tree.insert(letter, format!("{zeroes}1")); + a += 1; + } + + tree +} + +fn compress(text: String, tree: HashMap) -> Vec { + let mut compressed = Vec::new(); + + let mut current_byte: u8 = 0; + let mut bit_count: u8 = 0; + + for letter in text.chars() { + let code = tree.get(&letter.to_string()).unwrap(); + + for bit in code.chars() { + current_byte <<= 1; + + if bit == '1' { + current_byte |= 1; + } + + bit_count += 1; + + if bit_count == 8 { + compressed.push(current_byte); + + current_byte = 0; + bit_count = 0; + } + } + } + + if bit_count > 0 { + current_byte <<= 8 - bit_count; + compressed.push(current_byte); + } + + compressed } diff --git a/src/test.rs b/src/test.rs index f0877ba..f010bcb 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,11 +1,33 @@ #[cfg(test)] mod tests { + + use std::collections::HashMap; + + use crate::{create_tree, get_stats}; + use super::*; - use main; #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); + fn check_basic_functions() { + let test = get_stats("ZEHTZJATJAEJEF".to_string()); + let case = HashMap::from([ + ("Z".to_string(), 2), + ("E".to_string(), 3), + ("H".to_string(), 1), + ("T".to_string(), 2), + ("J".to_string(), 3), + ("A".to_string(), 2), + ("F".to_string(), 1), + ]); + + println!("{:?} \n {:?}", test, case); + assert!(test == case); + } + #[test] + fn test2() { + let small_string : String = "aaaaaaaaaaaaaaaaaaa a a a a a a a bazbazoreb kjzbej kjqbzetjbqzefe jabzezf jbzaefe jbzae ljzbef ljsndsf lj".to_string(); + + let stats = get_stats(small_string); + create_tree(stats); } }