71 lines
1.8 KiB
Rust
71 lines
1.8 KiB
Rust
//! 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<dyn Error>> {
|
|
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<dyn Error>> {
|
|
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<dyn Error>> {
|
|
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(())
|
|
}
|