From 715bce656d6910d183d2365830db66cc0433b7f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20R=C3=B6ger?= Date: Tue, 18 Aug 2026 21:18:28 +0200 Subject: [PATCH] fix pattern bug where yellow takes precedence --- src/app/wordle_simulation.rs | 47 +++++++++++++++++++++++------------- src/app/wordle_solver.rs | 6 ++--- src/lib/game.rs | 6 ++--- src/lib/pattern.rs | 33 ++++++++++++++++++++++--- src/lib/solver.rs | 10 +++----- 5 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/app/wordle_simulation.rs b/src/app/wordle_simulation.rs index 0dfcab0..de110c2 100644 --- a/src/app/wordle_simulation.rs +++ b/src/app/wordle_simulation.rs @@ -2,34 +2,47 @@ use std::{env::args, path::Path}; use wordle_solver::{game::Game, solver::Solver, word_list::WordList}; -pub fn main() { - let valid_words = WordList::from_file(Path::new("valid-words.txt")).unwrap(); - let target_words = WordList::from_file(Path::new("answers.txt")).unwrap(); +pub fn do_simulation(valid_words: WordList, target_words: WordList, opener: Option<&str>) -> u64 { let target_word = target_words.random_word(); + println!("Target: {}", target_word); let mut game = Game::new(target_word); let mut solver = Solver::new(valid_words, target_words); - if let Some(first_guess) = args().skip(1).next() { - if let Some(pat) = game.guess(&first_guess) { - solver.apply_guess(pat); - println!("{}", solver.tabular_format()); - } else { - println!("Found solution: {}", first_guess); + if let Some(first_guess) = opener { + match game.guess(&first_guess) { + Ok(pat) => { + solver.apply_guess(pat); + println!("{}", solver.tabular_format()); + } + Err(n) => { + println!("Found solution at guess {}: {}", n, first_guess); + return n; + } } } loop { - let best_word = &solver.evaluate_all_words().first().unwrap().clone().word; - println!("{}", solver.best_word_format()); + let best_word = solver.evaluate_all_words().first().unwrap().word.clone(); + println!("{}", solver.best_word_format(5)); - if let Some(pat) = game.guess(best_word) { - solver.apply_guess(pat); - println!("{}", solver.tabular_format()); - } else { - println!("Found solution: {}", best_word); - break; + match game.guess(&best_word) { + Ok(pat) => { + solver.apply_guess(pat); + println!("{}", solver.tabular_format()); + } + Err(n) => { + println!("Found solution at guess {}: {}", n, best_word); + return n; + } } } } + +pub fn main() { + let valid_words = WordList::from_file(Path::new("valid-words.txt")).unwrap(); + let target_words = WordList::from_file(Path::new("answers.txt")).unwrap(); + + do_simulation(valid_words, target_words, args().skip(1).next().as_deref()); +} diff --git a/src/app/wordle_solver.rs b/src/app/wordle_solver.rs index 19c426d..51c9c77 100644 --- a/src/app/wordle_solver.rs +++ b/src/app/wordle_solver.rs @@ -9,13 +9,13 @@ pub fn main() { solver.apply_guess(Pattern::from_guess("CRANE", "CASTS").unwrap()); println!("{}", solver.tabular_format()); - println!("{}", solver.best_word_format()); + println!("{}", solver.best_word_format(5)); solver.apply_guess(Pattern::from_guess("CRANE", "WORKS").unwrap()); println!("{}", solver.tabular_format()); - println!("{}", solver.best_word_format()); + println!("{}", solver.best_word_format(5)); solver.apply_guess(Pattern::from_guess("CRANE", "PAPER").unwrap()); println!("{}", solver.tabular_format()); - println!("{}", solver.best_word_format()); + println!("{}", solver.best_word_format(5)); } diff --git a/src/lib/game.rs b/src/lib/game.rs index 1432d8e..6367dbf 100644 --- a/src/lib/game.rs +++ b/src/lib/game.rs @@ -13,13 +13,13 @@ impl Game { } } - pub fn guess(&mut self, word: &str) -> Option { + pub fn guess(&mut self, word: &str) -> Result { self.score += 1; if word == self.word { - None + Err(self.score) } else { - Some(Pattern::from_guess(&self.word, word).unwrap()) + Ok(Pattern::from_guess(&self.word, word).unwrap()) } } } diff --git a/src/lib/pattern.rs b/src/lib/pattern.rs index 5f9d325..8b279f0 100644 --- a/src/lib/pattern.rs +++ b/src/lib/pattern.rs @@ -64,8 +64,10 @@ impl Pattern { } } - // Yellows for i in 0..chars.len() { + if stats[i] == CharStatus::GREEN { + continue; + } if let Some((j, _)) = rest.iter().enumerate().find(|(_, x)| **x == guess[i]) { stats[i] = CharStatus::YELLOW; rest[j] = ' '; @@ -151,7 +153,7 @@ mod tests { assert_eq!( Pattern::from_guess("abcde", "eabcd"), Pattern::try_new( - "abcde", + "eabcd", vec![ CharStatus::YELLOW, CharStatus::YELLOW, @@ -164,7 +166,7 @@ mod tests { assert_eq!( Pattern::from_guess("abcde", "fghij"), Pattern::try_new( - "abcde", + "fghij", vec![ CharStatus::GREY, CharStatus::GREY, @@ -177,7 +179,7 @@ mod tests { assert_eq!( Pattern::from_guess("aabbc", "bbaab"), Pattern::try_new( - "aabbc", + "bbaab", vec![ CharStatus::YELLOW, CharStatus::YELLOW, @@ -189,6 +191,29 @@ mod tests { ); } + #[test] + fn bug_1() { + let target = "RARER"; + let g1 = "RAISE"; + + let pat = Pattern::from_guess(target, g1).unwrap(); + + assert_eq!( + pat, + Pattern::try_new( + "RAISE", + vec![ + CharStatus::GREEN, + CharStatus::GREEN, + CharStatus::GREY, + CharStatus::GREY, + CharStatus::YELLOW, + ], + ) + .unwrap() + ) + } + #[test] fn pattern_match_1() { let p1 = Pattern::try_new( diff --git a/src/lib/solver.rs b/src/lib/solver.rs index 3c372b0..539c65c 100644 --- a/src/lib/solver.rs +++ b/src/lib/solver.rs @@ -80,10 +80,8 @@ impl Solver { let expected_score_after_guess = score * solution_probability + (1.0 - solution_probability) * (score - + ((self.valid_words.equal_likelieness_entropy() - - expected_information_gained) - .log2() - + 1.0)); + + (self.valid_words.equal_likelieness_entropy() - expected_information_gained) + .log2()); WordStats { word: word.to_string(), @@ -110,7 +108,7 @@ impl Solver { self.best_words.clone() } - pub fn best_word_format(&self) -> String { + pub fn best_word_format(&self, n: usize) -> String { let mut table = Table::new("#{:<} {:>} | {:<} {:<} {:<}"); table.add_row( @@ -121,7 +119,7 @@ impl Solver { .with_cell("E[I]") .with_cell("E[score]"), ); - for (i, ws) in self.best_words.iter().take(10).enumerate() { + for (i, ws) in self.best_words.iter().take(n).enumerate() { table.add_row( Row::new() .with_cell(i + 1)