Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use radix_fmt::radix_3;
- use std::{
- error::Error,
- fs::File,
- io::{BufRead, BufReader},
- iter::Iterator,
- result::Result, cmp::Ordering,
- };
- pub struct WordleBase {
- pub words: Vec<String>,
- pub guesses: Vec<String>,
- }
- impl WordleBase {
- pub fn new(
- words: Vec<String>,
- guesses: Vec<String>,
- ) -> WordleBase {
- WordleBase {
- words,
- guesses,
- }
- }
- pub fn load(
- words_path: &str,
- guesses_path: &str,
- ) -> Result<WordleBase, Box<dyn Error>> {
- let words = WordleBase::read_lines(words_path)?;
- let guesses = WordleBase::read_lines(guesses_path)?;
- Ok(WordleBase::new(words, guesses))
- }
- pub fn read_lines(path: &str) -> std::io::Result<Vec<String>> {
- let f = File::open(path)?;
- let reader = BufReader::new(f);
- let r = reader
- .lines()
- .take_while(Result::is_ok)
- .map(|s| s.unwrap())
- .collect();
- Ok(r)
- }
- }
- pub struct Char {
- character: char,
- char_type: CharType,
- }
- impl Char {
- pub fn new(character: char, char_type: CharType) -> Char {
- Char {
- character,
- char_type,
- }
- }
- }
- pub enum CharType {
- Gray,
- Yellow,
- Green,
- }
- pub struct Guess {
- pub chars: Vec<Char>,
- }
- impl Guess {
- pub fn matches(&self, word: &String) -> bool {
- let chars: Vec<char> = word.chars().collect();
- if chars.len() != self.len() {
- return false;
- }
- for (i, s) in self.chars.iter().enumerate() {
- match &s.char_type {
- CharType::Gray => {
- if word.contains(s.character) {
- return false;
- }
- }
- CharType::Yellow => {
- if !word.contains(s.character) {
- return false;
- }
- }
- CharType::Green => {
- if chars.get(i) != Some(&s.character) {
- return false;
- }
- }
- }
- }
- true
- }
- pub fn compare(&self, word_list : &Vec<String>) -> u16 {
- let mut r = 0;
- for word in word_list {
- if self.matches(word) {
- r += 1;
- }
- }
- r
- }
- pub fn new(words: Vec<Char>) -> Guess {
- Guess { chars: words }
- }
- #[allow(dead_code)]
- pub fn len(&self) -> usize {
- self.chars.len()
- }
- }
- pub struct WordleEngine<'a> {
- base: &'a WordleBase,
- // There are 6 columns, therefore the max value would be 5
- current_column: u8,
- current_words: Vec<String>,
- probablistic_distribution: Vec<(&'a str, f64)>,
- }
- impl<'a> WordleEngine<'a> {
- pub fn base(&self) -> &'a WordleBase {
- &self.base
- }
- #[allow(dead_code)]
- pub fn current_column(&self) -> u8 {
- self.current_column
- }
- pub fn current_words(&self) -> &Vec<String> {
- &self.current_words
- }
- pub fn distribution(&self) -> &Vec<(&'a str, f64)> {
- &self.probablistic_distribution
- }
- pub fn new(base: &'a WordleBase) -> WordleEngine {
- let current_words = base.words.clone();
- let probablistic_distribution = Vec::<(&str, f64)>::new();
- WordleEngine {
- base,
- current_column: 0,
- current_words,
- probablistic_distribution
- }
- }
- pub fn input_guess(&mut self, guess : &Guess) -> &Vec<String> {
- self.current_column += 1;
- let vec = self.current_words();
- let mut new_vec : Vec<String> = Vec::with_capacity(vec.len());
- for word in vec {
- if guess.matches(&word) {
- new_vec.push(word.to_string());
- }
- }
- self.current_words = new_vec;
- &self.current_words
- }
- pub fn change_distribution(&mut self) {
- self.probablistic_distribution = WordleEngine::calculate_distribution(self.current_words(), &self.base().guesses)
- }
- pub fn calculate_score(guess : &String, words : &Vec<String>) -> u16 {
- let guesses = WordleEngine::create_guess_list(guess);
- let mut score = 0u16;
- for guess in guesses {
- score += guess.compare(words);
- }
- score
- }
- pub fn calculate_distribution<'b>(
- words: &Vec<String>,
- guesses: &'b Vec<String>,
- ) -> Vec<(&'b str, f64)> {
- let mut orders : Vec<(&str, f64)> = Vec::new();
- for guess in guesses {
- let score = WordleEngine::calculate_score(guess, words);
- orders.push((guess, score as f64));
- }
- orders.sort_by(|a, b| {
- if a.1 == b.1 {
- return Ordering::Greater;
- }
- if a.1 < b.1 {
- return Ordering::Greater;
- }
- return Ordering::Less;
- });
- orders
- }
- pub fn create_guess_list(word: &String) -> Vec<Guess> {
- let num = 3u32.pow(word.len() as u32); // For a 5 letter word this would be equal to 243
- let mut guesses: Vec<Guess> = Vec::with_capacity(num as usize);
- for n in 0..num {
- guesses.push(WordleEngine::create_guess(n, word));
- }
- guesses
- }
- pub fn create_guess(num: u32, value: &String) -> Guess {
- let r = radix_3(num).to_string();
- let chars: Vec<char> = value.chars().collect();
- let count = chars.len();
- let diff = count - r.chars().count();
- let zeroes_string: String = std::iter::repeat("0").take(diff).collect();
- let string = zeroes_string + &r;
- let mut r: Vec<Char> = Vec::with_capacity(value.len());
- for (i, s) in string.chars().enumerate() {
- match s {
- '0' => r.push(Char::new(chars[i], CharType::Gray)),
- '1' => r.push(Char::new(chars[i], CharType::Yellow)),
- '2' => r.push(Char::new(chars[i], CharType::Green)),
- _ => {
- // It shouldn't be possible to end up here
- panic!()
- }
- }
- }
- return Guess::new(r);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement