From a94398d31f39adde628fd77d3105c28927d061ce Mon Sep 17 00:00:00 2001 From: John Date: Thu, 7 Aug 2025 05:55:08 -0400 Subject: [PATCH] detritus: Initial commit --- .gitignore | 2 + .rustfmt.toml | 16 +++++ Cargo.toml | 7 ++ LICENSE | 21 ++++++ README.md | 9 +++ res/passthe.jpg | Bin 0 -> 40936 bytes src/lib.rs | 180 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 70 +++++++++++++++++++ 8 files changed, 305 insertions(+) create mode 100644 .gitignore create mode 100644 .rustfmt.toml create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 res/passthe.jpg create mode 100644 src/lib.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..c460cf0 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,16 @@ +unstable_features = true +max_width = 100 +wrap_comments = true +comment_width = 100 +struct_lit_width = 100 + +imports_granularity = "Crate" +# Allow structs to fill an entire line +# use_small_heuristics = "Max" +# Allow small functions on single line +# fn_single_line = true + +# Alignment +enum_discrim_align_threshold = 12 +#struct_field_align_threshold = 12 +where_single_line = true diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7973b5e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "detritus" +version = "0.1.0" +edition = "2024" + +[dependencies] +repline = { version = "0.0.8", registry = "soft-fish" } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..193efc9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 soft.fish + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..319b5a0 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# detritus + +A prefix tree on T9 dial codes. Perfect for indulging in the benthic zone. + + + +## Why is it named detritus? + +I put in a word, and detritus popped out. diff --git a/res/passthe.jpg b/res/passthe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2138d1769cb6e980c61585cadbbd659fb5137091 GIT binary patch literal 40936 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 *cR?j#z;qRPv%^{2`cMeMa10S6L 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

2bI>Pcpqi5vh#NPyYhO^D=2{;a9$Y0SkjyRrbSX zgXQm#KaLW%t!QX$k&tuv_99|NLlonOLbEck_qWbD$i2uy1$sr=B z5Y$x-F;NA-;POEr4$=cB%&)2(hSet9N_|y4g~-F*+;xEty(07kkd0K@X`j>j>IJGtH<-w8Y$ zt5Rg^WDT8Gt3%63V@czWqW=OW5LZ=CF1V)6+4qRVuz|3%v9JGY6z2!S#)lH(iSQzZ zhBmYVTcxoUB!nO-OJW}fEqK{G3!;)xC@%^54>b+uHwFTXqXRc9^IN7L&V{J$-UKAq zwm=Ap)%8-3&Urm(Yz0=SWa)<&LB*J28fmLc*XT3qD#-3tlC=7W6ID8LEpp;B=0ESW z3T%a94}Nq?A^Vq3iQ_`CR_qJQR5bH}heei=&=}d4E$-QFHgidWw`OeACD(a#Tw#YsLb%O2u*Upn8n{0T~{_x%Hg!a1?R#ZgJLU|NK(ep22h;t(% zhKL2p_kOgCQ&xA&ny6q6vgB8x+B7##{8i%wTFibqAtqKz(2)THtf3jE{cld-qUiwH zA;1BK9Z#fJyg7hYO*~34$g?K8qy8LS(?5F1L;)Kmb4y#!sBF}W-;cjs%)E>g9 zs|MnXjoq|1vx(4YNF}tT8F8f4EwOkvviR(&Ua{ke_A%snqmCzy&8PpW2($hdgq>{6 z_-mWjoa+W;TB5IX*{RpaIWDt8C;Q?rie5#U{SQ8pxzWf$#)CMTH6q~a4RBqTm;cDr OL3jC&;xkcyr~VIX9nn|- literal 0 HcmV?d00001 diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..c7c048a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,180 @@ +//! Implements a trie on T9 numpads +//! +//! # T9: +//! 1: 2:abc 3:def +//! 4:ghi 5:jkl 6:mno +//! 7:pqrs 8:tuv 9:wxyz + +use std::{ + collections::VecDeque, + ops::{Index, IndexMut}, +}; + +#[derive(Debug, Default)] +pub struct Trie9 { + pub link: Option>, + pub leaf: Vec, +} + +impl Trie9 { + pub fn new() -> Self { + Self::default() + } + + pub fn insert(&mut self, string: &str) -> bool { + let Some(trie) = self.at_mut(string.chars()) else { + return false; + }; + + trie.leaf.push(string.into()); + true + } + + pub fn get(&self, index: T9) -> Option<&Trie9> { + self.link.as_ref()?.get(index as usize) + } + + pub fn get_mut(&mut self, index: T9) -> Option<&mut Trie9> { + self.link.as_mut()?.get_mut(index as usize) + } + + pub fn get_or_insert(&mut self, index: T9) -> &mut Trie9 { + self.link + .get_or_insert_default() + .get_mut(index as usize) + .expect("link exists at all T9 indices") + } + + pub fn at(&self, code: Iter) -> Option<&Self> + where + Iter: IntoIterator, + T: TryInto, + { + let mut code = code.into_iter(); + match code.next() { + None => Some(self), + Some(link) => self.get(link.try_into().ok()?)?.at(code), + } + } + + pub fn at_mut(&mut self, code: Iter) -> Option<&mut Self> + where + Iter: IntoIterator, + T: TryInto, + { + let mut code = code.into_iter(); + match code.next() { + None => Some(self), + Some(link) => self.get_or_insert(link.try_into().ok()?).at_mut(code), + } + } + + pub fn iter<'t>(&'t self) -> Trie9Iter<'t> { + Trie9Iter::new(self) + } +} + +#[derive(Clone, Debug)] +pub struct Trie9Iter<'t9> { + queue: VecDeque<&'t9 Trie9>, + items: std::slice::Iter<'t9, String>, +} + +impl<'t> Trie9Iter<'t> { + pub fn new(trie: &'t Trie9) -> Self { + Self { queue: VecDeque::from([trie]), items: Default::default() } + } +} + +impl<'t> Iterator for Trie9Iter<'t> { + type Item = &'t str; + + fn next(&mut self) -> Option { + let Self { queue, items } = self; + + if let Some(item) = items.next() { + return Some(item.as_str()); + } + + let Trie9 { link, leaf } = queue.pop_front()?; + *items = leaf.iter(); + queue.extend(link.iter().flat_map(|v| v.iter())); + + self.next() + } +} + +impl<'t> IntoIterator for &'t Trie9 { + type IntoIter = Trie9Iter<'t>; + type Item = &'t str; + + fn into_iter(self) -> Self::IntoIter { + Self::IntoIter::new(self) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum T9 { + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, +} + +impl From for u8 { + fn from(value: T9) -> Self { + value as u8 + 2 + } +} + +impl From for char { + fn from(value: T9) -> Self { + match value { + T9::T2 => '2', + T9::T3 => '3', + T9::T4 => '4', + T9::T5 => '5', + T9::T6 => '6', + T9::T7 => '7', + T9::T8 => '8', + T9::T9 => '9', + } + } +} + +impl TryFrom for T9 { + type Error = char; + fn try_from(value: char) -> Result { + Ok(match value { + '2' | 'A'..='C' | 'a'..='c' | 'À'..='Æ' | 'à'..='æ' | 'Ç' | 'ç' => Self::T2, + '3' | 'D'..='F' | 'd'..='f' | 'È'..='Ë' | 'è'..='ë' => Self::T3, + '4' | 'G'..='I' | 'g'..='i' | 'Ì'..='Ï' | 'ì'..='ï' => Self::T4, + '5' | 'J'..='L' | 'j'..='l' | '1' => Self::T5, + '6' | 'M'..='O' | 'm'..='o' | 'Ò'..='Ø' | 'ò'..='ø' | '0' => Self::T6, + '7' | 'P'..='S' | 'p'..='s' => Self::T7, + '8' | 'T'..='V' | 't'..='v' | 'Ù'..='Ü' | 'ù'..='ü' => Self::T8, + '9' | 'W'..='Z' | 'w'..='z' => Self::T9, + _ => Err(value)?, + }) + } +} + +impl Index for Trie9 { + type Output = Trie9; + fn index(&self, index: T9) -> &Self::Output { + let Some(link) = self.get(index) else { + panic!("No Trie9 at index {index:?}"); + }; + link + } +} + +impl IndexMut for Trie9 { + fn index_mut(&mut self, index: T9) -> &mut Self::Output { + self.get_or_insert(index) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1d41308 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,70 @@ +//! Solves a fun little puzzle invented by a coworker + +use detritus::{T9, Trie9}; +use repline::prebaked::*; +use std::{ + error::Error, + fs::File, + io::{BufRead, BufReader, IsTerminal, Write}, +}; + +fn main() -> Result<(), Box> { + let mut trie = Trie9::new(); + + // "Parse" CLI arg + let args: Vec<_> = std::env::args().skip(1).collect(); + let path = match args.as_slice() { + [] => "/usr/share/dict/words", + [path] => path, + _ => Err("Usage: detritus [dict]")?, + }; + + // Read in the database and construct the Trie9 + for line in BufReader::new(File::open(path)?).lines() { + trie.insert(&line?); + } + + if std::io::stdin().is_terminal() { + yestty(trie) + } else { + notty(trie) + } +} + +fn yestty(trie: Trie9) -> Result<(), Box> { + repline::read_and("\x1b[36m", " t>", " ?>", |line| { + let key: Vec<_> = match line.trim().chars().map(T9::try_from).collect() { + Ok(t9) => t9, + Err(e) => { + println!("Unexpected character: {e}"); + return Ok(Response::Deny); + } + }; + + key.iter().for_each(|&c| print!("{}", char::from(c))); + println!(); + + let Some(trie) = trie.at(key.iter().copied()) else { + return Ok(Response::Accept); + }; + for item in trie { + println!("{item}") + } + + Ok(Response::Accept) + })?; + Ok(()) +} + +fn notty(trie: Trie9) -> Result<(), Box> { + let stdin = std::io::stdin().lock(); + let key = std::io::read_to_string(stdin)?; + if let Some(trie) = trie.at(key.trim().chars()) { + for word in trie.iter() { + if writeln!(std::io::stdout(), "{word}").is_err() { + break; + } + } + } + Ok(()) +}