From 7a9e62546be9da56c033c57c8eb5e03e51e8a17c Mon Sep 17 00:00:00 2001 From: Mark Lodato Date: Mon, 31 Jan 2022 19:37:45 -0500 Subject: [PATCH 1/4] Add `compress` member to workspace **Why?** So we can compress inputs because :shrug:. --- Cargo.toml | 1 + compress/Cargo.toml | 10 ++++++++++ compress/src/lib.rs | 34 ++++++++++++++++++++++++++++++++++ compress/src/main.rs | 26 ++++++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 compress/Cargo.toml create mode 100644 compress/src/lib.rs create mode 100644 compress/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index b37ec41..6f94b3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ + "compress", "day1", ] diff --git a/compress/Cargo.toml b/compress/Cargo.toml new file mode 100644 index 0000000..2ee6874 --- /dev/null +++ b/compress/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "compress" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +brotli = "3" +clap = { version = "3", features = ["derive"] } diff --git a/compress/src/lib.rs b/compress/src/lib.rs new file mode 100644 index 0000000..43efc1e --- /dev/null +++ b/compress/src/lib.rs @@ -0,0 +1,34 @@ +/// Compresses the passed string into the output byte vector. +pub fn compress(input: String) -> Vec { + let input = input.into_bytes(); + let mut output = Vec::with_capacity(input.len()); + brotli::BrotliCompress(&mut input.as_slice(), &mut output, &Default::default()).unwrap(); + output +} + +#[macro_export] +macro_rules! aoc_input { + ($path:literal) => {{ + let file = include_bytes!("../input.compressed").to_vec(); + compress::decompress(file) + }}; +} + +/// Decompresses the passed byte vector into a string. +pub fn decompress(input: Vec) -> String { + let mut output = Vec::with_capacity(input.len()); + brotli::BrotliDecompress(&mut input.as_slice(), &mut output).unwrap(); + String::from_utf8(output).unwrap() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn decompress_inverts_compress() { + let s = "some string"; + + assert_eq!(decompress(compress(s.to_string())), s); + } +} diff --git a/compress/src/main.rs b/compress/src/main.rs new file mode 100644 index 0000000..0b2b839 --- /dev/null +++ b/compress/src/main.rs @@ -0,0 +1,26 @@ +//! Takes an input file path and writes the compressed contents +//! to `{file_name}.compressed`. +//! +//! Used for compressing Advent of Code inputs because why not. + +use clap::Parser; + +#[derive(Parser)] +#[clap(about = "Compresses input file to .compressed file")] +struct Args { + /// Path of file to compress. + #[clap(long, short)] + input: std::path::PathBuf, +} +fn main() { + let args = Args::parse(); + + let input_file = std::fs::read_to_string(&args.input).unwrap(); + let compressed = compress::compress(input_file); + + let mut output_path = args.input; + output_path.set_extension("compressed"); + std::fs::write(&output_path, compressed).unwrap(); + + println!("Wrote to {:?}", output_path); +} From af3901354731487fb5f0d53570d72b9ce29b7a86 Mon Sep 17 00:00:00 2001 From: Mark Lodato Date: Mon, 31 Jan 2022 19:40:42 -0500 Subject: [PATCH 2/4] Compress `day1` Using the new `compress` member. Also ignore any future `input.txt`s. --- .gitignore | 1 + day1/Cargo.toml | 1 + day1/benches/bench.rs | 6 +++--- day1/input.compressed | Bin 0 -> 887 bytes day1/input.txt | 1 - day1/src/lib.rs | 8 ++++---- day1/src/main.rs | 4 +--- 7 files changed, 10 insertions(+), 11 deletions(-) create mode 100644 day1/input.compressed delete mode 100644 day1/input.txt diff --git a/.gitignore b/.gitignore index 96ef6c0..d61a5fd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +**/input.txt diff --git a/day1/Cargo.toml b/day1/Cargo.toml index ecff584..262e969 100644 --- a/day1/Cargo.toml +++ b/day1/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +compress = { path = "../compress" } [dev-dependencies] criterion = { version = "0.3", features = ["html_reports"] } diff --git a/day1/benches/bench.rs b/day1/benches/bench.rs index d1e9bd0..34c73ca 100644 --- a/day1/benches/bench.rs +++ b/day1/benches/bench.rs @@ -1,9 +1,9 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; fn criterion_benchmark(c: &mut Criterion) { - let input = include_str!("../input.txt"); - c.bench_function("part1", |b| b.iter(|| day1::part1(black_box(input)))); - c.bench_function("part2", |b| b.iter(|| day1::part2(black_box(input)))); + let input = compress::aoc_input!("../input.compressed"); + c.bench_function("part1", |b| b.iter(|| day1::part1(black_box(&input)))); + c.bench_function("part2", |b| b.iter(|| day1::part2(black_box(&input)))); } criterion_group!(benches, criterion_benchmark); diff --git a/day1/input.compressed b/day1/input.compressed new file mode 100644 index 0000000000000000000000000000000000000000..28329cedce72228be8d8af71e5eb0e3e7a2fed2b GIT binary patch literal 887 zcmV--1Bm<^R~z`HP*Nh!*hXQXREju)f(r%+K$sFG6GR0A5}M#<(tiNZ+B{Scl9Cc& zW{(yWhw6DSG;@O9$Ph&KxRMW`K|vZwyWx@qnFFN~Hk1y9O}4U%kWuXDs6k4&e1tk- zi6*64NDJcIQDv=yPbk1Hh^5&{13cXC#uRH`)Qmw}g?rsp0=iuYgUYRMH`c($9)^Ly zq)p}ox9^eff!)3j_i;qBp2{xxXQFdX{1tTVuTIQSEd+Z({$A~T+8_URu_x~QTroI{rx^u#cqz>X8O*GdEWgmuxFpg1^7C@e7gIm{rB9? zVr!G{k7lLUnYnkagYT&C?zzvq<$C|#>(A|7?f>^q-&@}Q|7yRATv@xX{`fBmDEfc* zV{`Afn)llLEAQU6|4y|%`&awkvVZNAy+l!9+Sz&j-EsHdf7Be#JBHW$@v{M2F41Gj zXKLOEduVUjpl@820V-~KHYi^_cH!QUGr^#Am=AJ(oFn8UGD(UXCZFp(3v)r=d@KmJ z;Tp49mIC?;eJ$jq$p^xIAc_sh6jhZj+yRDY!H^fJ813#2IH?oKMW`59ZX-{cu?>~q z{QZqO0uDiiTMALNu9ES&e<`p8A~gX7EU1Wp4N{j-4rVaw;rsx7h0palg3NX+x z76eEL2mzodM1sk2r*O;lmsw=X@Hg>rUr#zrT}zd z5->Ga2r&VY2qY2^6oi;WL0N_gpaIB&cLfTVLINbf3?dI|js}5bQUigY06GDKB~(ae zAREktz+fXlm>htJ5)3hz5E6t5DT&f-B!o}^0#FDI5-JA3grGqjDiB~a!2l)#pok8w zg;o+^XSZSzL<|Jvx#1|`VBt#^m}C|eWHdQRS&7AWq>AR20Bl6Sf?=d$VhD-^b^*uG NVRnGoGH`Jzss+B1sbv5F literal 0 HcmV?d00001 diff --git a/day1/input.txt b/day1/input.txt deleted file mode 100644 index 1855a96..0000000 --- a/day1/input.txt +++ /dev/null @@ -1 +0,0 @@ -()()(()()()(()()((()((()))((()((((()()((((()))()((((())(((((((()(((((((((()(((())(()()(()((()()(()(())(()((((()((()()()((((())((((((()(()(((()())(()((((()))())(())(()(()()))))))))((((((((((((()())()())())(())))(((()()()((((()(((()(()(()()(()(()()(()(((((((())(())(())())))((()())()((((()()((()))(((()()()())))(())))((((())(((()())(())(()))(()((((()())))())((()(())(((()((((()((()(())())))((()))()()(()(()))))((((((((()())((((()()((((()(()())(((((()(()())()))())(((()))()(()(()(()((((()(())(()))(((((()()(()()()(()(((())())(((()()(()()))(((()()(((())())(()(())())()()(())()()()((()(((()(())((()()((())()))((()()))((()()())((((()(()()(()(((()))()(()))))((()(((()()()))(()(((())()(()((()())(()(()()(()())(())()(((()(()())()((((()((()))))())()))((()()()()(())()())()()()((((()))))(()(((()()(((((((())()))()((((()((())()(()())(())()))(()(()())(((((((())))(((()))())))))()))())((())(()()((())()())()))))()((()()())(())((())((((()())())()()()(((()))())))()()))())(()()()(()((((((()()))())()))()(((()(((())((((()()()(()))())()()))))())()))())((())()())(((((())())((())())))(((())(((())(((((()(((((())(()(()())())(()(())(()))(()((((()))())()))))())))((()(()))))())))(((((())()))())()))))()))))(((()))()))))((()))((()((()(()(())()())))(()()()(())()))()((((())))))))(())(()((()()))(()))(()))(()((()))))))()()((((()()))()())()))))))()()()))(()((())(()))((()()()())()(((()((((())())))()((((()(()))))))())))()()())()))(()))))(()())()))))))((())))))))())()))()((())())))(()((()))()))(())))))(()))()())()()))((()(()))()()()()))))())()()))())(())()()))()))((()))))()()(()())))))()()()))((((()))()))))(()(())))(()())))((())())(()))()))))()())))()())()())))))))))()()))))())))((())((()))))())))(((()())))))))(()))()()))(()))()))))()())))))())((((()())))))))())))()()))))))))()))()))))()))))))(())))))))))())))))))))))))))())())((())))))))))()))((())))()))))))))())()(()))))))())))))()()()())()(()()()(()())(()))()()()(()())))())())))()))))())))))))()()()()())(())())()())()))))(()()()()()))))()))())())))((()())()())))()))()))))(()())))()))))))))(((()))()()))))))))))))))))))))(()))(()((()))())))())(()))(()(()(())))))()(()))()))()()))))))))))))()((()())(())())()(())))))())()())((()()))))(()()))))())()(())()))))))))))))))))))))()))(()(()())))))))()()((()))()))))))((())))()))))))))((()))())()()))())()()))((()))())))))))))))(()())()))(())((()(()()))(()())(())))()())(()(())()()))))()))()(()))))))(()))))))))))(()))())))))))))())))))())))(())))))()))))(())())))))))))()(()))))()())))())(()))()())))))))))))))())()()))))()))))))())))))()))))(())(()()()()((())()))())(()))((())()))())())(())(()()))))()))(())()()((())(())))(())))()))())))))))))()(((((())())))(())()))))(())))((()))()(((((((()))))()()))(())))))()(()))))(()()))()))())))))))(()())()))))))))())))(()))())()))(())()((())())()())())(()(()))))()))))))((()())(())()()(()())))()()))(())(())(()))())))()))(()))()()))((((()))))()))((()()()))))()))()))())))(()))()))))(())))()))())()(()))()())))())))))))())))())))()()))))))(()))())())))()))()()())())))))))))))))())))()))(()()))))())))())()(())))())))))))))))))))))()()())())))))()()()((()(()))()()(())()())()))()))))()()()))))))((()))))))))()(()(()((((((()()((()())))))))))))()))())))))((())())(()))())))())))))())()()())(())))())))()())())(())))))))()()(())))()))())))())())())()))))))))()))(()()()())())())))(())())))))))()()())()))))())))())()(())())))))))()())()))(()()(())())))()(()((()()((()()(((((())(()())()))(())()))(())))(())))))))()))()))((()))()))()))))))))()))))))))((()()())(()))(((()))(())))()))((())(((())))()())))())))))((())))))(())())((((((())())()(()))()(()((()())))((())()(()(()))))(())(()()())(())))())((()(((())())))(((()())())))())()(())())((((()()))))())((()))()()()()(())(((((((()()()((()))())(()())))(())())((((()()(()))))()((())))((())()))()(((()))())))()))((()(()))(())(()((((())((((()()(()()))(((())(()))))((((()(()))(())))))((()))(()))((()(((()(()))(()(()((()(())(()(()(()(()()((()))())(((())(()(()))))(()))()()))(())))(())()(((())(()))()((((()()))))())(()))))((())()((((()(((()))())())(((()))()())((())(())())(())()(())()(()()((((((()()))))()()(((()()))))()())()(((()(()))(()(()())(()(()))))(((((()(((())())))))(((((()((()()((())())((((((()(())(()()((()()()()()()()(()()))()(((()))()))(((((((())(((()((()())()((((())(((()(())))()((()(()()()((())((()())()))()))())))())((((((()))(()(()()()))(()((()(()(()))()((()(((()()()((())(((((())()(()))())())((()(())))(()(()())(())((())())())(((()()()(())))))())(()))))))()))))))())((()()()))((()((((((()))(((()((((()()()(((()))())()(()()(((()((()()()()())()()))()()()(()(())((()))))(()))())))))))()(()()(((((())()(()(((((()((()(()()())(()((((((((()((((((())()((((()()()((()((()((((((()))((())))))))())()))((()(()))()(()()(()((())((()()((((((((((((()())(()()()))((((()((((((())(()))())(()()((()()))()(((((((()((()()((((((()(((())))((())))((((((((()()(((((((())(((((()())(((())((())()((((()(((((((()(()(((()((((((()(((()(((((((((((()()((()()(()))((()()(((()(((())))((((())()(()(((())()(()(((())(((((((((((()))())))((((((())((()()((((()())())((((()()))((())(((((()(()()(()()()((())(()((()()((((()(((((()((()(()((((()())((((((()(((((()()(()(()((((())))(())(())(())((((()(()()((((()((((()()((()((((((())))(((((()))))()))(()((((((((()(((())())(((())))(()(()((())(((()((()()(((((()((()()(((())()(()))(((((((())(()(((((()))((()((()((()))(())())((((()((((())()(()))(((()(((((((((((((((())(((((((((()))(((()(()()()()((((((()((())()((((((((()(())(((((((((((()(()((())()((()()(()(()()((((()()((())(()((()()(()()((((()(((((((())))((((())(())()(((()()((()()((((()((()(((()((())(((()()()((((()((((()()(()(()((((((((())(()(((((())(()())(((((((()())()(()((((()((())(()()())((((()()(((()((((())(())(()()(((((((((()()))()(((())(()(()((((((())(()()())(()))()()(((()(((()((())(()(((((((()(()(()((()(((((()(()((()(()((((((()((((()()((((()(((()((())(()(()((()()((((()()(())()(())(((())(()((((((((()())(((((((((()(())()((((())))()))()()(((((()()((((((())(()()(((()(()(((((((()(()(((((((())(())((((()((()(())))((((()()())(()))((()())((((()(((((()(()(())(()(()()())(((((()(((((()((((()()((((((((()()))(()((((((())((((())()(()(((()()()(((()(()(())(())(((((()(())())((((())(())(()(((()(((((())((((())())((()(((((((()(((())(()(()))(((((((((()((()((()()(()((((())(((()((())((((())(()(((()(((()(()((((()(((())(()(((()(()()(()(()((()()(()())(())())((()(()(((()(((()(((()()(((((((((()(((((((((()()(((()(((()())((((()(()(((()()()((())((((((((((())(()(((()((((()())((((()((()))(((()()()(((((()(((((((())((()())(()((((())((((((((())(()((()((((((((((()()((()((()()))(((()())()())()(((()())()()(()(()(((((((())()))(())()))())()()((())()((()((((()((()((())(((((()((((((()(())))(()))())(((()))((()()(()(((()))((((())()(((()))))()(()(())()(((((())(()(()(())(())()((()()()((((()(())((()())(()(()))(()(()(()()(())()()(()((())()((()))))()))((()(()()()()((()())(()))())()(()(((((((((())())((()((()((((((())()((((())(((())((()(()()()((())(()((())(((()((((()()((()(()(((((())()))()((((((()))((())(((()()))(((())(())()))(((((((())(())())()(())(((((()))()((()))()(()()((()()()()()())((((((( \ No newline at end of file diff --git a/day1/src/lib.rs b/day1/src/lib.rs index 880426a..88950bf 100644 --- a/day1/src/lib.rs +++ b/day1/src/lib.rs @@ -57,13 +57,13 @@ mod tests { #[test] fn test_part_1_chris_input() { - let input = include_str!("../input.txt"); - assert_eq!(part1(input), 280); + let input = compress::aoc_input!("../input.compressed"); + assert_eq!(part1(&input), 280); } #[test] fn test_part_2_chris_input() { - let input = include_str!("../input.txt"); - assert_eq!(part2(input), 1797); + let input = compress::aoc_input!("../input.compressed"); + assert_eq!(part2(&input), 1797); } } diff --git a/day1/src/main.rs b/day1/src/main.rs index bc5b7cf..dd72796 100644 --- a/day1/src/main.rs +++ b/day1/src/main.rs @@ -1,7 +1,5 @@ -use std::fs::read_to_string; - fn main() { - let input = read_to_string("input.txt").unwrap(); + let input = compress::aoc_input!("../input.compressed"); println!("part1: {}", day1::part1(&input)); println!("part2: {}", day1::part2(&input)); } From d102205d956af4aa1cf625f63d15478a9c8dbb10 Mon Sep 17 00:00:00 2001 From: Mark Lodato Date: Mon, 21 Feb 2022 10:56:31 -0500 Subject: [PATCH 3/4] Actually use `$path` in `aoc_input!` **This Commit** Updates the `aoc_input` macro to use the passed `$path` when determining which file to read. **Why?** Because the original was definitely a typo. However, we could decide that all inputs are in a consistent place and not have the macro take an argument but this seems less weird for now. See https://github.com/mlodato517/aoc_2015/pull/6#discussion_r810288814 for more details. --- compress/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compress/src/lib.rs b/compress/src/lib.rs index 43efc1e..6889ee6 100644 --- a/compress/src/lib.rs +++ b/compress/src/lib.rs @@ -9,7 +9,7 @@ pub fn compress(input: String) -> Vec { #[macro_export] macro_rules! aoc_input { ($path:literal) => {{ - let file = include_bytes!("../input.compressed").to_vec(); + let file = include_bytes!($path).to_vec(); compress::decompress(file) }}; } From 5599a7f109d1fa98207111e2a21cc5c4988be109 Mon Sep 17 00:00:00 2001 From: Mark Lodato Date: Mon, 21 Feb 2022 11:13:33 -0500 Subject: [PATCH 4/4] Rewrite compress functions with generics **Why?** For fun. --- compress/src/lib.rs | 32 +++++++++++++++++++++----------- compress/src/main.rs | 10 ++++++---- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/compress/src/lib.rs b/compress/src/lib.rs index 6889ee6..a318226 100644 --- a/compress/src/lib.rs +++ b/compress/src/lib.rs @@ -1,23 +1,31 @@ +use std::io::{Read, Write}; + /// Compresses the passed string into the output byte vector. -pub fn compress(input: String) -> Vec { - let input = input.into_bytes(); - let mut output = Vec::with_capacity(input.len()); - brotli::BrotliCompress(&mut input.as_slice(), &mut output, &Default::default()).unwrap(); - output +pub fn compress_to(mut input: R, mut output: W) +where + R: Read, + W: Write, +{ + brotli::BrotliCompress(&mut input, &mut output, &Default::default()).unwrap(); } #[macro_export] macro_rules! aoc_input { ($path:literal) => {{ let file = include_bytes!($path).to_vec(); - compress::decompress(file) + compress::decompress(file.as_slice()) }}; } -/// Decompresses the passed byte vector into a string. -pub fn decompress(input: Vec) -> String { - let mut output = Vec::with_capacity(input.len()); - brotli::BrotliDecompress(&mut input.as_slice(), &mut output).unwrap(); +/// Decompresses the passed reader into a string. +/// +/// Panics if the result of decompression is invalid UTF-8. +pub fn decompress(mut input: R) -> String +where + R: Read, +{ + let mut output = Vec::new(); + brotli::BrotliDecompress(&mut input, &mut output).unwrap(); String::from_utf8(output).unwrap() } @@ -28,7 +36,9 @@ mod tests { #[test] fn decompress_inverts_compress() { let s = "some string"; + let mut output = Vec::new(); + compress_to(s.as_bytes(), &mut output); - assert_eq!(decompress(compress(s.to_string())), s); + assert_eq!(decompress(output.as_slice()), s); } } diff --git a/compress/src/main.rs b/compress/src/main.rs index 0b2b839..bc3c036 100644 --- a/compress/src/main.rs +++ b/compress/src/main.rs @@ -4,6 +4,7 @@ //! Used for compressing Advent of Code inputs because why not. use clap::Parser; +use std::fs::File; #[derive(Parser)] #[clap(about = "Compresses input file to .compressed file")] @@ -15,12 +16,13 @@ struct Args { fn main() { let args = Args::parse(); - let input_file = std::fs::read_to_string(&args.input).unwrap(); - let compressed = compress::compress(input_file); + let input_file = File::open(&args.input).unwrap(); let mut output_path = args.input; output_path.set_extension("compressed"); - std::fs::write(&output_path, compressed).unwrap(); + let output_file = File::create(&output_path).unwrap(); - println!("Wrote to {:?}", output_path); + compress::compress_to(input_file, output_file); + + println!("Wrote to {output_path:?}"); }