From b862767944334a85ba2d48ff9bbfd0bcac23c508 Mon Sep 17 00:00:00 2001 From: mehbark Date: Wed, 22 Apr 2026 18:11:30 -0400 Subject: [PATCH] use comfy_table for output --- Cargo.lock | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 69 +++++++++++------- 3 files changed, 244 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1131c83..75ce100 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,207 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "comfy-table" +version = "7.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958c5d6ecf1f214b4c2bbbbf6ab9523a864bd136dcf71a7e8904799acfe1ad47" +dependencies = [ + "crossterm", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags", + "crossterm_winapi", + "document-features", + "parking_lot", + "rustix", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "libc" +version = "0.2.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "substitution-helper" version = "0.1.0" +dependencies = [ + "comfy-table", +] + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/Cargo.toml b/Cargo.toml index 406fe44..8b6c4e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] +comfy-table = "7.2.2" diff --git a/src/main.rs b/src/main.rs index 541b5f1..d65224d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,8 @@ use std::{ process, }; +use comfy_table::{CellAlignment, ContentArrangement, Table, presets::UTF8_FULL}; + fn main() { let mut subst = HashMap::new(); for pair in env::args().skip(1) { @@ -26,9 +28,7 @@ fn main() { .or_default() += 1; } - println!("Letters:"); - print_freqs(byte_frequencies, &subst); - println!(); + print_freqs(byte_frequencies, &subst, "L"); let mut digram_freqs: HashMap<[char; 2], usize> = HashMap::new(); for slice in inp.as_bytes().windows(2) { @@ -41,9 +41,7 @@ fn main() { *digram_freqs.entry([*a as char, *b as char]).or_default() += 1; } - println!("Digrams:"); - print_freqs(digram_freqs, &subst); - println!(); + print_freqs(digram_freqs, &subst, "Di"); let mut trigram_freqs: HashMap<[char; 3], usize> = HashMap::new(); for slice in inp.as_bytes().windows(3) { @@ -58,9 +56,7 @@ fn main() { .or_default() += 1; } - println!("Trigrams:"); - print_freqs(trigram_freqs, &subst); - println!(); + print_freqs(trigram_freqs, &subst, "Tri"); for byte in inp.bytes() { let new_byte = subst @@ -72,7 +68,11 @@ fn main() { } } -fn print_freqs(freqs: HashMap<[char; N], usize>, subst: &HashMap) { +fn print_freqs( + freqs: HashMap<[char; N], usize>, + subst: &HashMap, + gram_name: &'static str, +) { let total_freqs: usize = freqs.values().sum(); let mut freqs: Vec<_> = freqs @@ -81,23 +81,38 @@ fn print_freqs(freqs: HashMap<[char; N], usize>, subst: &HashMap .collect(); freqs.sort_by_key(|(f, count)| (*count, *f)); - for (c, count) in freqs.iter().rev() { - println!( - "{:>3}: {:4.1}% ({count:4})", - c.iter() - .map(|c| { - let Ok(b): Result = (*c).try_into() else { - panic!() - }; + let mut table = Table::new(); - if let Some(new) = subst.get(&b) { - (*new as char).to_ascii_uppercase() - } else { - (b as char).to_ascii_lowercase() - } - }) - .collect::(), - (*count as f32 / total_freqs as f32) * 100. - ); + table + .load_preset(UTF8_FULL) + .apply_modifier(comfy_table::modifiers::UTF8_SOLID_INNER_BORDERS) + .set_content_arrangement(ContentArrangement::Dynamic) + .set_header([gram_name, "Freq", "N"]); + + for column in table.column_iter_mut() { + column.set_cell_alignment(CellAlignment::Right); } + + for (c, count) in freqs.iter().rev() { + let char = c + .iter() + .map(|c| { + let Ok(b): Result = (*c).try_into() else { + panic!() + }; + + if let Some(new) = subst.get(&b) { + (*new as char).to_ascii_uppercase() + } else { + (b as char).to_ascii_lowercase() + } + }) + .collect::(); + + let proportion = (*count as f32 / total_freqs as f32) * 100.; + + table.add_row([char, format!("{proportion:.1}%"), format!("{count}")]); + } + + println!("{table}"); }