fix(naive): make the naive solver work with a winrate of seemingly over 98%
cargo devel CI / cargo CI (push) Has been cancelled Details

This commit is contained in:
Christoph J. Scherr 2024-08-02 16:31:09 +02:00
parent d5cf04d89b
commit a59b847675
2 changed files with 30 additions and 4 deletions

View File

@ -1,6 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use libpt::log::{debug, info, trace}; use libpt::log::{debug, error, info, trace};
use crate::error::{SolverError, WResult}; use crate::error::{SolverError, WResult};
use crate::game::evaluation::{Evaluation, EvaluationUnit}; use crate::game::evaluation::{Evaluation, EvaluationUnit};
@ -75,20 +75,29 @@ impl<'wl, WL: WordList> Solver<'wl, WL> for NaiveSolver<'wl, WL> {
// get all words that have the correct chars on the same positions // get all words that have the correct chars on the same positions
let mut matches: Vec<WordData> = game.wordlist().get_words_matching(&pattern)?; let mut matches: Vec<WordData> = game.wordlist().get_words_matching(&pattern)?;
if matches.is_empty() { if matches.is_empty() {
error!("no matches even when just considering the known good chars");
return Err(SolverError::NoMatches(game.solution().cloned()).into()); return Err(SolverError::NoMatches(game.solution().cloned()).into());
} else {
trace!("found {} basic matches", matches.len())
} }
matches = matches matches = matches
.iter() .iter()
// only words that have not been guessed yet // only words that have not been guessed yet
.filter(|p| !game.made_guesses().contains(&&p.0)) .filter(|p| !game.made_guesses().contains(&&p.0))
.filter(|solution_candidate| { .filter(|solution_candidate| {
if !game.responses().is_empty()
&& !state.has_all_known_contained(&solution_candidate.0)
{
debug!("known cont:{:#?}", state.get_all_known_contained());
return false;
}
for (idx, c) in solution_candidate.0.char_indices() { for (idx, c) in solution_candidate.0.char_indices() {
let cinfo = state let cinfo = state
.char_map_mut() .char_map_mut()
.entry(c) .entry(c)
.or_insert(CharInfo::new(game.length())); .or_insert(CharInfo::new(game.length()));
if !cinfo.part_of_solution() || cinfo.has_been_tried(idx) if !cinfo.occurences_of_char_possible(&solution_candidate.0, c)
// || !cinfo.occurences_of_char_possible(&solution_candidate.0, c) || cinfo.has_been_tried(idx)
{ {
return false; return false;
} }

View File

@ -3,6 +3,7 @@ use std::fmt::Debug;
use std::ops::{Range, RangeBounds}; use std::ops::{Range, RangeBounds};
use crate::error::WResult; use crate::error::WResult;
use crate::wlist::word::Word;
pub(crate) type CharMap = HashMap<char, CharInfo>; pub(crate) type CharMap = HashMap<char, CharInfo>;
@ -32,6 +33,22 @@ impl SolverState {
pub fn char_map_mut(&mut self) -> &mut CharMap { pub fn char_map_mut(&mut self) -> &mut CharMap {
&mut self.char_map &mut self.char_map
} }
pub(crate) fn get_all_known_contained(&self) -> Vec<(&char, &CharInfo)> {
self.char_map
.iter()
.filter(|(key, value)| value.part_of_solution())
.collect()
}
pub(crate) fn has_all_known_contained(&self, guess: &Word) -> bool {
for needed_char in self.get_all_known_contained() {
if !guess.contains(*needed_char.0) {
return false;
}
}
true
}
} }
impl CharInfo { impl CharInfo {
@ -62,7 +79,7 @@ impl CharInfo {
#[must_use] #[must_use]
pub fn part_of_solution(&self) -> bool { pub fn part_of_solution(&self) -> bool {
self.occurences_amount.end > 0 self.occurences_amount.start > 0 && self.occurences_amount.end > 0
} }
pub fn min_occurences(&mut self, min: usize) { pub fn min_occurences(&mut self, min: usize) {