generated from PlexSheep/rs-base
improve naive solver #13
|
@ -1,3 +1,7 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use colored::Colorize;
|
||||||
use libpt::cli::console::{style, StyledObject};
|
use libpt::cli::console::{style, StyledObject};
|
||||||
|
|
||||||
use crate::wlist::word::Word;
|
use crate::wlist::word::Word;
|
||||||
|
@ -15,21 +19,6 @@ pub struct Evaluation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evaluation {
|
impl Evaluation {
|
||||||
/// Display the evaluation color coded
|
|
||||||
pub fn colorized_display(&self) -> Vec<StyledObject<String>> {
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
for e in self.inner.iter() {
|
|
||||||
let mut c = style(e.0.to_string());
|
|
||||||
if e.1 == Status::Matched {
|
|
||||||
c = c.green();
|
|
||||||
} else if e.1 == Status::Exists {
|
|
||||||
c = c.yellow();
|
|
||||||
}
|
|
||||||
buf.push(c);
|
|
||||||
}
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The first string is the word the evaluation is for, The second string defines how the
|
/// The first string is the word the evaluation is for, The second string defines how the
|
||||||
/// characters of the first string match the solution.
|
/// characters of the first string match the solution.
|
||||||
///
|
///
|
||||||
|
@ -108,3 +97,20 @@ impl From<&Evaluation> for Word {
|
||||||
Word::from(value.inner.iter().map(|v| v.0).collect::<String>())
|
Word::from(value.inner.iter().map(|v| v.0).collect::<String>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Evaluation {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
for s in &self.inner {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match s.1 {
|
||||||
|
Status::None => s.0.to_string().into(),
|
||||||
|
Status::Exists => s.0.to_string().yellow(),
|
||||||
|
Status::Matched => s.0.to_string().green(),
|
||||||
|
}
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
std::fmt::Result::Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ where
|
||||||
solution: Option<WordData>,
|
solution: Option<WordData>,
|
||||||
wordlist: &'wl WL,
|
wordlist: &'wl WL,
|
||||||
responses: Vec<GuessResponse>,
|
responses: Vec<GuessResponse>,
|
||||||
// TODO: keep track of the letters the user has tried
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'wl, WL: WordList> Game<'wl, WL> {
|
impl<'wl, WL: WordList> Game<'wl, WL> {
|
||||||
|
@ -126,15 +125,29 @@ impl<'wl, WL: WordList> Game<'wl, WL> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an [Evaluation] for a given solution and guess.
|
/// Generates an [Evaluation] for a given solution and guess.
|
||||||
pub(crate) fn evaluate(mut solution: WordData, guess: &Word) -> Evaluation {
|
pub(crate) fn evaluate(solution: WordData, guess: &Word) -> Evaluation {
|
||||||
let mut evaluation = Vec::new();
|
let mut evaluation = Vec::new();
|
||||||
let mut status: Status;
|
let mut status: Status;
|
||||||
let mut buf = solution.0.clone();
|
let mut buf = solution.0.clone();
|
||||||
|
|
||||||
for ((idx, c_guess), c_sol) in guess.chars().enumerate().zip(solution.0.chars()) {
|
for ((idx, c_guess), c_sol) in guess.chars().enumerate().zip(solution.0.chars()) {
|
||||||
if c_guess == c_sol {
|
if c_guess == c_sol {
|
||||||
status = Status::Matched;
|
status = Status::Matched;
|
||||||
buf.replace_range(idx..idx + 1, "_");
|
buf.replace_range(idx..idx + 1, "_");
|
||||||
} else if buf.contains(c_guess) {
|
} else if buf.contains(c_guess)
|
||||||
|
&& buf
|
||||||
|
.char_indices()
|
||||||
|
.filter(|c| c.1 == c_guess)
|
||||||
|
.filter(|c| {
|
||||||
|
guess
|
||||||
|
.chars()
|
||||||
|
.nth(c.0)
|
||||||
|
.expect("the evaluations are somehow different lengths")
|
||||||
|
== c.1
|
||||||
|
})
|
||||||
|
.count()
|
||||||
|
== 0
|
||||||
|
{
|
||||||
status = Status::Exists;
|
status = Status::Exists;
|
||||||
buf = buf.replacen(c_guess, "_", 1);
|
buf = buf.replacen(c_guess, "_", 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -359,16 +372,8 @@ impl<'wl, WL: WordList> Display for Game<'wl, WL> {
|
||||||
self.step(),
|
self.step(),
|
||||||
self.solution(),
|
self.solution(),
|
||||||
)?;
|
)?;
|
||||||
for s in self
|
for s in self.responses() {
|
||||||
.responses()
|
write!(f, "\"{s}\",")?;
|
||||||
.iter()
|
|
||||||
.map(|v| v.evaluation().to_owned().colorized_display())
|
|
||||||
{
|
|
||||||
write!(f, "\"")?;
|
|
||||||
for si in s {
|
|
||||||
write!(f, "{si}")?;
|
|
||||||
}
|
|
||||||
write!(f, "\", ")?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,17 +92,6 @@ impl GuessResponse {
|
||||||
|
|
||||||
impl Display for GuessResponse {
|
impl Display for GuessResponse {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
for s in self.evaluation.clone().into_iter() {
|
write!(f, "{}", self.evaluation())
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
match s.1 {
|
|
||||||
Status::None => s.0.to_string().into(),
|
|
||||||
Status::Exists => s.0.to_string().yellow(),
|
|
||||||
Status::Matched => s.0.to_string().green(),
|
|
||||||
}
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
std::fmt::Result::Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use wordle_analyzer::error::GameError;
|
use test_log::test; // set the log level with an envvar: `RUST_LOG=trace cargo test`
|
||||||
|
|
||||||
|
use libpt::log::info;
|
||||||
use wordle_analyzer::game::evaluation::Evaluation;
|
use wordle_analyzer::game::evaluation::Evaluation;
|
||||||
use wordle_analyzer::game::response::GuessResponse;
|
|
||||||
use wordle_analyzer::wlist::builtin::BuiltinWList;
|
use wordle_analyzer::wlist::builtin::BuiltinWList;
|
||||||
use wordle_analyzer::wlist::WordList;
|
use wordle_analyzer::wlist::WordList;
|
||||||
|
|
||||||
|
@ -23,10 +24,25 @@ fn test_eval_simple() -> anyhow::Result<()> {
|
||||||
let mut game = builder.build()?;
|
let mut game = builder.build()?;
|
||||||
let guess = Word::from("slate");
|
let guess = Word::from("slate");
|
||||||
game.guess(&guess, None)?;
|
game.guess(&guess, None)?;
|
||||||
assert_eq!(
|
let correct = Evaluation::build(&guess, "xxccc")?;
|
||||||
|
info!(
|
||||||
|
"{} =? {}",
|
||||||
*game.last_response().unwrap().evaluation(),
|
*game.last_response().unwrap().evaluation(),
|
||||||
Evaluation::build(&guess, "xxccc")?
|
correct
|
||||||
);
|
);
|
||||||
|
assert_eq!(*game.last_response().unwrap().evaluation(), correct);
|
||||||
|
|
||||||
|
let mut game = builder.build()?;
|
||||||
|
let guess = Word::from("about");
|
||||||
|
game.guess(&guess, None)?;
|
||||||
|
let correct = Evaluation::build(&guess, "fxxxf")?;
|
||||||
|
info!(
|
||||||
|
"{} =? {}",
|
||||||
|
*game.last_response().unwrap().evaluation(),
|
||||||
|
correct
|
||||||
|
);
|
||||||
|
assert_eq!(*game.last_response().unwrap().evaluation(), correct);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,18 +56,57 @@ fn test_eval_reoccuring_char() -> anyhow::Result<()> {
|
||||||
let mut game = builder.build()?;
|
let mut game = builder.build()?;
|
||||||
let guess = Word::from("pines");
|
let guess = Word::from("pines");
|
||||||
game.guess(&guess, None)?;
|
game.guess(&guess, None)?;
|
||||||
assert_eq!(
|
let correct = Evaluation::build(&guess, "xcccc")?;
|
||||||
|
info!(
|
||||||
|
"{} =? {}",
|
||||||
*game.last_response().unwrap().evaluation(),
|
*game.last_response().unwrap().evaluation(),
|
||||||
Evaluation::build(&guess, "xcccc")?
|
correct
|
||||||
);
|
);
|
||||||
|
assert_eq!(*game.last_response().unwrap().evaluation(), correct);
|
||||||
|
|
||||||
let mut game = builder.build()?;
|
let mut game = builder.build()?;
|
||||||
let guess = Word::from("sides");
|
let guess = Word::from("sides");
|
||||||
game.guess(&guess, None)?;
|
game.guess(&guess, None)?;
|
||||||
assert_eq!(
|
let correct = Evaluation::build(&guess, "xcxcc")?;
|
||||||
|
info!(
|
||||||
|
"{} =? {}",
|
||||||
*game.last_response().unwrap().evaluation(),
|
*game.last_response().unwrap().evaluation(),
|
||||||
Evaluation::build(&guess, "xcxcc")?
|
correct
|
||||||
);
|
);
|
||||||
|
assert_eq!(*game.last_response().unwrap().evaluation(), correct);
|
||||||
|
|
||||||
|
let mut game = builder.build()?;
|
||||||
|
let guess = Word::from("ninja");
|
||||||
|
game.guess(&guess, None)?;
|
||||||
|
let correct = Evaluation::build(&guess, "cccxx")?;
|
||||||
|
info!(
|
||||||
|
"{} =? {}",
|
||||||
|
*game.last_response().unwrap().evaluation(),
|
||||||
|
correct
|
||||||
|
);
|
||||||
|
assert_eq!(*game.last_response().unwrap().evaluation(), correct);
|
||||||
|
|
||||||
|
let mut game = builder.build()?;
|
||||||
|
let guess = Word::from("which");
|
||||||
|
game.guess(&guess, None)?;
|
||||||
|
let correct = Evaluation::build(&guess, "xxfxx")?;
|
||||||
|
info!(
|
||||||
|
"{} =? {}",
|
||||||
|
*game.last_response().unwrap().evaluation(),
|
||||||
|
correct
|
||||||
|
);
|
||||||
|
assert_eq!(*game.last_response().unwrap().evaluation(), correct);
|
||||||
|
|
||||||
|
let mut game = builder.build()?;
|
||||||
|
let guess = Word::from("indie");
|
||||||
|
game.guess(&guess, None)?;
|
||||||
|
let correct = Evaluation::build(&guess, "ffxxf")?;
|
||||||
|
info!(
|
||||||
|
"{} =? {}",
|
||||||
|
*game.last_response().unwrap().evaluation(),
|
||||||
|
correct
|
||||||
|
);
|
||||||
|
assert_eq!(*game.last_response().unwrap().evaluation(), correct);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue