slow, doesn't keep track of what words

This commit is contained in:
mehbark 2026-07-07 15:09:35 -04:00
parent 81a9ac109e
commit 9eac56f50c
2 changed files with 69 additions and 2 deletions

View file

@ -1,6 +1,6 @@
use std::{fmt, ops::Deref}; use std::{fmt, ops::Deref};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Debug)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Debug, Hash)]
pub struct LetterSet(u32); pub struct LetterSet(u32);
/// Immutable set of English letters /// Immutable set of English letters
@ -60,6 +60,10 @@ impl LetterSet {
self.0.count_ones() as u8 self.0.count_ones() as u8
} }
pub const fn is_empty(self) -> bool {
self.0 == 0
}
const fn letter_index(letter: u8) -> Option<u8> { const fn letter_index(letter: u8) -> Option<u8> {
if letter.is_ascii_alphabetic() { if letter.is_ascii_alphabetic() {
let lower = letter.to_ascii_lowercase(); let lower = letter.to_ascii_lowercase();
@ -98,6 +102,15 @@ where
} }
} }
impl<T> From<T> for LetterSet
where
T: AsRef<[u8]>,
{
fn from(value: T) -> Self {
Self::from_slice(value.as_ref())
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@ -181,4 +194,13 @@ mod test {
assert_eq!(A.add(b'b'), AB); assert_eq!(A.add(b'b'), AB);
assert_eq!(AB.add(b'c'), ABC); assert_eq!(AB.add(b'c'), ABC);
} }
#[test]
fn is_empty() {
assert!(LetterSet::EMPTY.is_empty());
assert!(!LetterSet::FULL.is_empty());
assert!(!A.is_empty());
assert!(!AB.is_empty());
assert!(!BC.is_empty());
}
} }

View file

@ -1,5 +1,50 @@
use std::{
collections::{HashMap, hash_map::Entry},
io::{self, BufRead, BufReader},
};
use crate::letterset::LetterSet;
mod letterset; mod letterset;
fn main() { fn main() {
println!("Hello, world!"); let dictionary: Vec<String> = BufReader::new(io::stdin().lock())
.lines()
.collect::<Result<_, _>>()
.unwrap();
let mut min_lengths: HashMap<LetterSet, u16> = HashMap::new();
let min_length = solve(dictionary.as_slice(), &mut min_lengths, LetterSet::FULL);
println!("{min_length}");
}
// length doesn't include spaces. i think that's okay
fn solve(
dictionary: &[String],
min_lengths: &mut HashMap<LetterSet, u16>,
remaining: LetterSet,
) -> u16 {
if remaining.is_empty() {
return 0;
}
if let Some(min) = min_lengths.get(&remaining) {
return *min;
}
let min_length = dictionary
.iter()
.filter(|word| remaining != remaining.difference(LetterSet::from(word.as_bytes())))
.map(|word| {
(u16::try_from(word.len()).unwrap()).saturating_add(solve(
dictionary,
min_lengths,
remaining.difference(LetterSet::from(word)),
))
})
.min()
.unwrap_or(u16::MAX);
min_lengths.insert(remaining, min_length);
min_length
} }