dramatically less cloning
This commit is contained in:
parent
8cba1ef0ce
commit
1222162bd6
3 changed files with 50 additions and 23 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1 +1,4 @@
|
||||||
/target
|
/target
|
||||||
|
perf.data
|
||||||
|
perf.data.old
|
||||||
|
flamegraph.svg
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,6 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
|
|
|
||||||
63
src/main.rs
63
src/main.rs
|
|
@ -1,5 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
env,
|
||||||
io::{self, BufRead, BufReader},
|
io::{self, BufRead, BufReader},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -13,43 +14,63 @@ fn main() {
|
||||||
.collect::<Result<_, _>>()
|
.collect::<Result<_, _>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"{:#?}",
|
||||||
|
solve(
|
||||||
|
&dictionary,
|
||||||
|
LetterSet::from(
|
||||||
|
env::args()
|
||||||
|
.nth(1)
|
||||||
|
.expect("give me the letters you want NOW")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve(dictionary: &[String], target: LetterSet) -> Option<(u16, Vec<String>)> {
|
||||||
let mut bests = HashMap::new();
|
let mut bests = HashMap::new();
|
||||||
let best = solve(dictionary.as_slice(), &mut bests, LetterSet::FULL);
|
bests.insert(LetterSet::EMPTY, (0, Vec::new()));
|
||||||
println!("{best:?}");
|
|
||||||
|
score(dictionary, &mut bests, target);
|
||||||
|
|
||||||
|
bests.get(&target).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
// length doesn't include spaces. i think that's okay
|
// length doesn't include spaces. i think that's okay
|
||||||
fn solve(
|
// assumes that `bests[LetterSet::EMPTY] == (0, Vec::new())`
|
||||||
|
fn score(
|
||||||
dictionary: &[String],
|
dictionary: &[String],
|
||||||
bests: &mut HashMap<LetterSet, (u16, Vec<String>)>,
|
bests: &mut HashMap<LetterSet, (u16, Vec<String>)>,
|
||||||
remaining: LetterSet,
|
remaining: LetterSet,
|
||||||
) -> (u16, Vec<String>) {
|
) -> u16 {
|
||||||
if remaining.is_empty() {
|
|
||||||
return (0, Vec::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(min) = bests.get(&remaining) {
|
if let Some(min) = bests.get(&remaining) {
|
||||||
return min.clone();
|
return min.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let best = dictionary
|
let Some((word, score)) = dictionary
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|word| remaining != remaining.difference(LetterSet::from(word.as_bytes())))
|
.filter(|word| remaining != remaining.difference(LetterSet::from(word)))
|
||||||
.map(|word| {
|
.map(|word| {
|
||||||
let (score, mut path) = solve(
|
(
|
||||||
|
word,
|
||||||
|
(u16::try_from(word.len()).unwrap()).saturating_add(score(
|
||||||
dictionary,
|
dictionary,
|
||||||
bests,
|
bests,
|
||||||
remaining.difference(LetterSet::from(word)),
|
remaining.difference(LetterSet::from(word)),
|
||||||
);
|
)),
|
||||||
path.push(word.clone());
|
|
||||||
(
|
|
||||||
(u16::try_from(word.len()).unwrap()).saturating_add(score),
|
|
||||||
path,
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.min()
|
.min_by_key(|(_, score)| *score)
|
||||||
.unwrap_or((u16::MAX, Vec::new()));
|
else {
|
||||||
|
return u16::MAX;
|
||||||
|
};
|
||||||
|
|
||||||
bests.insert(remaining, best.clone());
|
let remaining_after_word = remaining.difference(LetterSet::from(word));
|
||||||
best
|
let (_score, path) = bests
|
||||||
|
.get(&remaining_after_word)
|
||||||
|
.expect("we already inserted this");
|
||||||
|
let mut path = path.clone();
|
||||||
|
path.push(word.clone());
|
||||||
|
bests.insert(remaining, (score, path));
|
||||||
|
score
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue