Wrote program for Day 47

This commit is contained in:
Mariano Riefolo 2024-09-10 18:08:25 +02:00
parent ee7740c90d
commit cd79043caa
5 changed files with 194 additions and 1 deletions

View File

@ -93,7 +93,7 @@ We encourage you to share your progress and ask questions in the Discussions sec
| Day #44 | [Maximum Edge Of A Triangle](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-44_Maximum-Edge-Of-A-Triangle) | :white_check_mark: | | Day #44 | [Maximum Edge Of A Triangle](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-44_Maximum-Edge-Of-A-Triangle) | :white_check_mark: |
| Day #45 | [Subtract The Swapped Bits...](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-45_Subtract-The-Swapped-Bits-Without-Temp-Storage) | :white_check_mark: | | Day #45 | [Subtract The Swapped Bits...](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-45_Subtract-The-Swapped-Bits-Without-Temp-Storage) | :white_check_mark: |
| Day #46 | [Hot Pics Of Danny Devito](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-46_Hot-Pics-Of-Danny-Devito) | :white_check_mark: | | Day #46 | [Hot Pics Of Danny Devito](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-46_Hot-Pics-Of-Danny-Devito) | :white_check_mark: |
| Day #47 | [Zip It](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-47_Zip-It) | :white_large_square: | | Day #47 | [Zip It](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-47_Zip-It) | :white_check_mark: |
| Day #48 | [Christmas Tree](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-48_Christmas-Tree) | :white_large_square: | | Day #48 | [Christmas Tree](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-48_Christmas-Tree) | :white_large_square: |
| Day #49 | [Swimming Pool](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-49_Swimming-Pool) | :white_large_square: | | Day #49 | [Swimming Pool](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-07/Day-49_Swimming-Pool) | :white_large_square: |
| Day #50 | [Tic Tac Toe](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-08/Day-50_Tic-Tac-Toe) | :white_large_square: | | Day #50 | [Tic Tac Toe](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-08/Day-50_Tic-Tac-Toe) | :white_large_square: |

View File

@ -0,0 +1,6 @@
[package]
name = "day47"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -0,0 +1,109 @@
use std::collections::HashMap;
use std::fs;
use std::io::{BufWriter, Write};
fn get_bit(byte: u8, position: u8) -> u8 {
(byte >> position) & 1
}
pub fn compress(source: &str, destination: &str) -> Result<(), std::io::Error> {
let file_content = fs::read(source)?;
let mut association = HashMap::new();
for char in file_content.iter() {
if !association.contains_key(char) {
association.insert(char, association.len() as u8);
}
}
let file = fs::File::create(destination)?;
let mut dest_file = BufWriter::new(file);
let mut occurrence: Vec<_> = association.iter().collect();
occurrence.sort_by_key(|&(_, v)| v);
for (key, _) in occurrence.iter() {
dest_file.write_all(&[***key])?;
}
dest_file.write_all(&[**occurrence.last().unwrap().0])?;
let nbits = (association.len() as f32).log2().ceil() as u8;
let mut bytes = Vec::new();
let mut byte = 0;
let mut pos = 0;
for char in file_content.iter() {
let tmp = association[char];
for i in 0..nbits {
byte |= get_bit(tmp, i) << (7 - pos);
pos += 1;
if pos == 8 {
pos = 0;
bytes.push(byte);
byte = 0;
}
}
}
if pos != 0 {
bytes.push(byte);
}
dest_file.write_all(&bytes)?;
Ok(())
}
fn reverse_bits(mut n: u8) -> u8 {
let mut result = 0;
for _ in 0..8 {
result = (result << 1) | (n & 1);
n >>= 1;
}
result
}
pub fn uncompress(source: &str, destination: &str) -> Result<(), std::io::Error> {
let file_content = fs::read(source)?;
let mut association = Vec::new();
let mut i = 1;
for char in file_content.iter() {
if !association.is_empty() && &char == association.last().unwrap() {
break;
}
association.push(char);
i += 1;
}
let nbits = (association.len() as f32).log2().ceil() as u8;
let bytes = &file_content[i..];
let mut nbit = 0;
let mut current_bits = 0;
let mut uncompressed = Vec::new();
for byte in bytes {
let byte = reverse_bits(*byte);
for i in 0..8 {
let bit = get_bit(byte, i);
current_bits = (current_bits << 1) | bit;
nbit += 1;
if nbit == nbits {
current_bits = reverse_bits(current_bits);
current_bits >>= 8 - nbits;
uncompressed.push(*association[current_bits as usize]);
nbit = 0;
current_bits = 0;
}
}
}
let file = fs::File::create(destination)?;
let mut dest_file = BufWriter::new(file);
dest_file.write_all(&uncompressed)?;
Ok(())
}

View File

@ -0,0 +1,28 @@
use std::{env, process::exit};
use day47::{compress, uncompress};
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() != 4 {
eprintln!("Usage: day47 (c|u) <source file> <destination file>");
exit(1);
}
let f = match args[1].as_str() {
"c" => compress,
"u" => uncompress,
_ => {
eprintln!("The first argument should be c (compress) or u (uncompress)");
exit(1);
}
};
match f(&args[2], &args[3]) {
Ok(_) => println!("Done!"),
Err(e) => {
eprintln!("{}", e);
exit(1);
}
};
}

View File

@ -0,0 +1,50 @@
#[cfg(test)]
mod tests {
use std::fs;
use day47::{compress, uncompress};
#[test]
fn librs() {
assert!(compress("src/lib.rs", "compressed1").is_ok());
assert!(uncompress("compressed1", "uncompressed1").is_ok());
let original = fs::read("src/lib.rs").unwrap();
let uncompressed = fs::read("uncompressed1").unwrap();
assert_eq!(original, uncompressed);
fs::remove_file("compressed1").unwrap();
fs::remove_file("uncompressed1").unwrap();
}
#[test]
fn mainrs() {
assert!(compress("src/main.rs", "compressed2").is_ok());
assert!(uncompress("compressed2", "uncompressed2").is_ok());
let original = fs::read("src/main.rs").unwrap();
let uncompressed = fs::read("uncompressed2").unwrap();
assert_eq!(original, uncompressed);
fs::remove_file("compressed2").unwrap();
fs::remove_file("uncompressed2").unwrap();
}
#[test]
fn cargotoml() {
assert!(compress("Cargo.toml", "compressed3").is_ok());
assert!(uncompress("compressed3", "uncompressed3").is_ok());
let original = fs::read("Cargo.toml").unwrap();
let uncompressed = fs::read("uncompressed3").unwrap();
assert_eq!(original, uncompressed);
fs::remove_file("compressed3").unwrap();
fs::remove_file("uncompressed3").unwrap();
}
#[test]
fn cargolock() {
assert!(compress("Cargo.lock", "compressed4").is_ok());
assert!(uncompress("compressed4", "uncompressed4").is_ok());
let original = fs::read("Cargo.lock").unwrap();
let uncompressed = fs::read("uncompressed4").unwrap();
assert_eq!(original, uncompressed);
fs::remove_file("compressed4").unwrap();
fs::remove_file("uncompressed4").unwrap();
}
}