generated from PlexSheep/rs-base
feat(solver): interactive input of responses #3
This commit is contained in:
parent
36347d1661
commit
0b83b26b20
|
@ -8,7 +8,7 @@ use libpt::cli::{repl::Repl, strum};
|
||||||
use libpt::log::*;
|
use libpt::log::*;
|
||||||
use strum::{EnumIter, IntoEnumIterator};
|
use strum::{EnumIter, IntoEnumIterator};
|
||||||
|
|
||||||
use wordle_analyzer::game::response::Evaluation;
|
use wordle_analyzer::game::evaluation::Evaluation;
|
||||||
use wordle_analyzer::game::response::GuessResponse;
|
use wordle_analyzer::game::response::GuessResponse;
|
||||||
|
|
||||||
use wordle_analyzer::solve::{BuiltinSolverNames, Solver};
|
use wordle_analyzer::solve::{BuiltinSolverNames, Solver};
|
||||||
|
@ -80,7 +80,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
fn help_guess_interactive(cli: Cli) -> anyhow::Result<()> {
|
fn help_guess_interactive(cli: Cli) -> anyhow::Result<()> {
|
||||||
let wl = BuiltinWList::default();
|
let wl = BuiltinWList::default();
|
||||||
let builder = game::Game::builder(&wl)
|
let builder = game::GameBuilder::new(&wl, false)
|
||||||
.length(cli.length)
|
.length(cli.length)
|
||||||
.max_steps(cli.max_steps)
|
.max_steps(cli.max_steps)
|
||||||
.precompute(cli.precompute);
|
.precompute(cli.precompute);
|
||||||
|
|
|
@ -3,11 +3,12 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use super::response::Status;
|
use super::response::Status;
|
||||||
|
|
||||||
|
pub type EvaluationUnit = (char, Status);
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
pub struct Evaluation {
|
pub struct Evaluation {
|
||||||
inner: Vec<EvaluationUnit>,
|
inner: Vec<EvaluationUnit>,
|
||||||
}
|
}
|
||||||
pub type EvaluationUnit = (char, Status);
|
|
||||||
|
|
||||||
impl IntoIterator for Evaluation {
|
impl IntoIterator for Evaluation {
|
||||||
type Item = EvaluationUnit;
|
type Item = EvaluationUnit;
|
||||||
|
@ -27,7 +28,10 @@ impl From<Vec<EvaluationUnit>> for Evaluation {
|
||||||
impl FromStr for Evaluation {
|
impl FromStr for Evaluation {
|
||||||
type Err = Infallible;
|
type Err = Infallible;
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
// TODO: make this proper
|
let mut v: Vec<EvaluationUnit> = Vec::new();
|
||||||
Ok(vec![('x', Status::None)].into())
|
for c in s.chars() {
|
||||||
|
v.push((c, Status::from(c)))
|
||||||
|
}
|
||||||
|
Ok(v.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use evaluation::*;
|
||||||
|
|
||||||
pub mod summary;
|
pub mod summary;
|
||||||
|
|
||||||
use self::response::{Evaluation, Status};
|
use self::response::Status;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Game<'wl, WL>
|
pub struct Game<'wl, WL>
|
||||||
|
@ -35,7 +35,7 @@ where
|
||||||
impl<'wl, WL: WordList> Game<'wl, WL> {
|
impl<'wl, WL: WordList> Game<'wl, WL> {
|
||||||
/// get a new [`GameBuilder`]
|
/// get a new [`GameBuilder`]
|
||||||
pub fn builder(wl: &'wl WL) -> GameBuilder<'wl, WL> {
|
pub fn builder(wl: &'wl WL) -> GameBuilder<'wl, WL> {
|
||||||
GameBuilder::new(wl)
|
GameBuilder::new(wl, true)
|
||||||
}
|
}
|
||||||
/// Create a [Game] of wordle
|
/// Create a [Game] of wordle
|
||||||
///
|
///
|
||||||
|
@ -54,15 +54,19 @@ impl<'wl, WL: WordList> Game<'wl, WL> {
|
||||||
precompute: bool,
|
precompute: bool,
|
||||||
max_steps: usize,
|
max_steps: usize,
|
||||||
wlist: &'wl WL,
|
wlist: &'wl WL,
|
||||||
|
generate_solution: bool,
|
||||||
) -> GameResult<Self> {
|
) -> GameResult<Self> {
|
||||||
// TODO: check if the length is in the range bounds of the wordlist
|
// TODO: check if the length is in the range bounds of the wordlist
|
||||||
let solution = wlist.rand_solution();
|
|
||||||
let game: Game<'wl, WL> = Game {
|
let game: Game<'wl, WL> = Game {
|
||||||
length,
|
length,
|
||||||
precompute,
|
precompute,
|
||||||
max_steps,
|
max_steps,
|
||||||
step: 0,
|
step: 0,
|
||||||
solution: Some(solution),
|
solution: if generate_solution {
|
||||||
|
Some(wlist.rand_solution())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
wordlist: wlist,
|
wordlist: wlist,
|
||||||
finished: false,
|
finished: false,
|
||||||
responses: Vec::new(),
|
responses: Vec::new(),
|
||||||
|
@ -203,26 +207,33 @@ pub struct GameBuilder<'wl, WL: WordList> {
|
||||||
precompute: bool,
|
precompute: bool,
|
||||||
max_steps: usize,
|
max_steps: usize,
|
||||||
wordlist: &'wl WL,
|
wordlist: &'wl WL,
|
||||||
|
generate_solution: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'wl, WL: WordList> GameBuilder<'wl, WL> {
|
impl<'wl, WL: WordList> GameBuilder<'wl, WL> {
|
||||||
/// make a new [GameBuilder]
|
/// make a new [GameBuilder]
|
||||||
///
|
///
|
||||||
/// We need a [WordList], so provide one here.
|
/// We need a [WordList], so provide one here.
|
||||||
pub fn new(wl: &'wl WL) -> Self {
|
pub fn new(wl: &'wl WL, generate_solution: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
length: super::DEFAULT_WORD_LENGTH,
|
length: super::DEFAULT_WORD_LENGTH,
|
||||||
precompute: false,
|
precompute: false,
|
||||||
max_steps: super::DEFAULT_MAX_STEPS,
|
max_steps: super::DEFAULT_MAX_STEPS,
|
||||||
wordlist: wl,
|
wordlist: wl,
|
||||||
|
generate_solution,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// build a [`Game`] with the stored configuration
|
/// build a [`Game`] with the stored configuration
|
||||||
pub fn build(&'wl self) -> GameResult<Game<'wl, WL>> {
|
pub fn build(&'wl self) -> GameResult<Game<'wl, WL>> {
|
||||||
trace!("{:#?}", self);
|
trace!("{:#?}", self);
|
||||||
let game: Game<WL> =
|
let game: Game<WL> = Game::build(
|
||||||
Game::build(self.length, self.precompute, self.max_steps, self.wordlist)?;
|
self.length,
|
||||||
|
self.precompute,
|
||||||
|
self.max_steps,
|
||||||
|
self.wordlist,
|
||||||
|
self.generate_solution,
|
||||||
|
)?;
|
||||||
Ok(game)
|
Ok(game)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::convert::Infallible;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use super::Game;
|
use super::{Evaluation, Game};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Copy, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, PartialEq, Copy, Eq, PartialOrd, Ord)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
@ -15,34 +15,6 @@ pub struct AtomicEvaluation {
|
||||||
char: char,
|
char: char,
|
||||||
status: Status,
|
status: Status,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
|
||||||
pub struct Evaluation {
|
|
||||||
inner: Vec<EvaluationUnit>,
|
|
||||||
}
|
|
||||||
pub type EvaluationUnit = (char, Status);
|
|
||||||
|
|
||||||
impl IntoIterator for Evaluation {
|
|
||||||
type Item = EvaluationUnit;
|
|
||||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.inner.into_iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Vec<EvaluationUnit>> for Evaluation {
|
|
||||||
fn from(value: Vec<EvaluationUnit>) -> Self {
|
|
||||||
Self { inner: value }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Evaluation {
|
|
||||||
type Err = Infallible;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
// TODO: make this proper
|
|
||||||
Ok(vec![('x', Status::None)].into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
@ -63,6 +35,19 @@ pub enum Status {
|
||||||
Matched = 2,
|
Matched = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<char> for Status {
|
||||||
|
fn from(value: char) -> Self {
|
||||||
|
let value = value.to_ascii_lowercase(); // let's not deal with unicode here, wordle is
|
||||||
|
// ASCII centric anyway
|
||||||
|
match value {
|
||||||
|
'x' => Self::None,
|
||||||
|
'f' | 'e' => Self::Exists,
|
||||||
|
'c' | 'm' => Self::Matched,
|
||||||
|
_ => Self::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GuessResponse {
|
impl GuessResponse {
|
||||||
pub(crate) fn new<WL: WordList>(guess: &Word, status: Evaluation, game: &Game<WL>) -> Self {
|
pub(crate) fn new<WL: WordList>(guess: &Word, status: Evaluation, game: &Game<WL>) -> Self {
|
||||||
let new = Self {
|
let new = Self {
|
||||||
|
|
Loading…
Reference in New Issue