Wrote program for Day 47
This commit is contained in:
parent
ee7740c90d
commit
cd79043caa
@ -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 #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 #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 #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: |
|
||||
|
6
Week-07/Day-47_Zip-It/day47/Cargo.toml
Normal file
6
Week-07/Day-47_Zip-It/day47/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day47"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
109
Week-07/Day-47_Zip-It/day47/src/lib.rs
Normal file
109
Week-07/Day-47_Zip-It/day47/src/lib.rs
Normal 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(())
|
||||
}
|
28
Week-07/Day-47_Zip-It/day47/src/main.rs
Normal file
28
Week-07/Day-47_Zip-It/day47/src/main.rs
Normal 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);
|
||||
}
|
||||
};
|
||||
}
|
50
Week-07/Day-47_Zip-It/day47/tests/compress_uncompress.rs
Normal file
50
Week-07/Day-47_Zip-It/day47/tests/compress_uncompress.rs
Normal 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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user