slow, doesn't keep track of what words
This commit is contained in:
parent
81a9ac109e
commit
9eac56f50c
2 changed files with 69 additions and 2 deletions
|
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
47
src/main.rs
47
src/main.rs
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue