Misc improvements

This commit is contained in:
Matthieu Jolimaitre 2025-06-12 16:46:11 +02:00
parent 5c56fc7540
commit 6e9f041f15
17 changed files with 977752 additions and 468873 deletions

2
.gitignore vendored
View file

@ -1 +1,3 @@
/target
/flamegraph.svg
/perf.data*

6
data/chars_of.sh Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/bash
set -e
allowed="azertyuiopqsdfghjklmwxcvbn"
cat "$1" | tr '[:upper:]' '[:lower:]' | sed 's/\(.\)/\1\n/g' | sort | uniq | grep -v -E "[$allowed]"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

78855
data/dict/pli07.txt Normal file

File diff suppressed because it is too large Load diff

386264
data/dict/scrable_2012.txt Normal file

File diff suppressed because it is too large Load diff

3
data/dict_specs.txt Normal file
View file

@ -0,0 +1,3 @@
- abriates
+ revisite
+ captes

View file

@ -21,7 +21,7 @@ struct Args {
fn main() {
let args = Args::parse();
dbg!(&args);
let mut dict = dictionnary::scrable(7);
let mut dict = dictionnary::scrable_2012(7);
// let dict = dictionnary::francais(7);
let count = if args.target.is_some() { 1 } else { args.count };
(0..count).for_each(|_| {
@ -35,12 +35,14 @@ fn main() {
.collect();
}
dbg!(&target);
let solver = Grouping::new(dict.clone());
let first_char = target.chars().next().expect("Target has a first letter.");
let dict = dict.iter().filter(|w| w.starts_with(first_char)).cloned();
let solver = Grouping::new(dict);
let mut game = Simulation::new(target.clone());
let result = game.play_all(solver, Some(20));
let result = game.play_all(solver, Some(10));
match result {
Ok((_, tries)) => println!("succ,{target},{tries}"),
Err(reason) => println!("fail,{target},{reason}"),
Ok((_, tries)) => println!("succ,{tries},{target}"),
Err(reason) => println!("fail,{reason},{target}"),
};
});
}

View file

@ -1,26 +1,63 @@
use std::{fs, path::Path};
use std::{fs, ops::Not, path::Path};
use rand::{seq::SliceRandom, thread_rng};
const ALLOWED: &str = "azertyuiopqsdfghjklmwxcvbn";
const REPLACES: &[(char, &str)] = &[
('à', "a"),
('â', "a"),
('ä', "a"),
('ç', "c"),
('é', "e"),
('è', "e"),
('ê', "e"),
('ë', "e"),
('î', "i"),
('ï', "i"),
('ô', "o"),
('ö', "o"),
('ù', "u"),
('û', "u"),
('ü', "u"),
];
pub fn load(path: impl AsRef<Path>, width: usize) -> Vec<String> {
let content = fs::read_to_string(path).expect("Can read file.");
lines_of(width, &content)
}
pub fn francais(width: usize) -> Vec<String> {
lines_of(width, include_str!("../data/francais.txt"))
}
pub fn gutenberg(width: usize) -> Vec<String> {
lines_of(width, include_str!("../data/gutenberg.txt"))
macro_rules! decl_dict {
($name:ident) => {
pub fn $name(width: usize) -> Vec<String> {
lines_of(
width,
include_str!(concat!("../data/dict/", stringify!($name), ".txt")),
)
}
};
}
pub fn scrable(width: usize) -> Vec<String> {
lines_of(width, include_str!("../data/scrable.txt"))
decl_dict!(gutenberg);
decl_dict!(liste_francais);
decl_dict!(ods4);
decl_dict!(ods5);
decl_dict!(ods6);
decl_dict!(pli07);
decl_dict!(scrable_2012);
fn translate_line(line: &str) -> Option<String> {
let mut content = line.to_lowercase();
for (f, t) in REPLACES {
content = content.replace(*f, t);
}
(content.chars())
.all(|c| ALLOWED.chars().any(|a| a == c))
.then_some(content)
}
fn lines_of(width: usize, content: &str) -> Vec<String> {
let mut res = content
.lines()
.filter_map(translate_line)
.filter(|w| w.len() == width)
.map(|l| l.to_string())
.collect::<Vec<_>>();

View file

@ -89,10 +89,10 @@ pub trait Game {
Some(guess) => match self.guess(dbg!(&guess)) {
Ok(()) => return Ok((guess, try_)),
Err(infos) => {
let printable = Info::as_printable(infos.iter().cloned())
let printed = Info::as_printable(infos.iter().cloned())
.into_iter()
.collect::<String>();
dbg!(printable);
dbg!(printed);
solver.learn(infos);
}
},

View file

@ -1,5 +1,3 @@
use rayon::prelude::*;
use crate::game::Info;
use super::{Game, InfoKind};

View file

@ -12,7 +12,7 @@ mod solve;
pub fn main() {
let (mut game, infos) = Proxy::init();
let dict = dictionnary::scrable(infos.len());
let dict = dictionnary::scrable_2012(infos.len());
let mut solver = Grouping::new(dict.into_iter().filter(|w| matches(w, &infos)));
solver.learn(infos);
let result = game.play_all(solver, Some(6));

View file

@ -12,12 +12,14 @@ mod solve;
fn main() {
let first_arg = args().nth(1);
let dict = dictionnary::scrable(first_arg.clone().map(|w| w.len()).unwrap_or(7));
let dict = dictionnary::scrable_2012(first_arg.clone().map(|w| w.len()).unwrap_or(7));
let random_word = || dict.choose(&mut rand::thread_rng()).unwrap().to_string();
let target = first_arg.unwrap_or_else(random_word);
dbg!(&target);
let solver = Grouping::new(dict);
let first_char = target.chars().next().expect("Target has a first letter.");
let dict = dict.into_iter().filter(|w| w.starts_with(first_char));
let mut game = Simulation::new(target);
let solver = Grouping::new(dict);
let result = game.play_all(solver, Some(20));
println!("{result:?}");
}

View file

@ -7,7 +7,7 @@ use rand::{
use rayon::iter::{ParallelBridge, ParallelIterator};
use crate::{
dictionnary::{self, gutenberg},
dictionnary,
game::{
simulation::{wordle, wordle_buffs_for, wordle_inner},
Info, InfoKind,
@ -77,11 +77,13 @@ impl Solver for Grouping {
return self.candidates.first().cloned();
}
self.dict.shuffle(&mut thread_rng());
let scored = self
.dict
.iter()
.take(100_000)
.par_bridge()
// .par_bridge()
.map(|word| (word, self.rank_word_avg_groups(word)))
.collect::<Vec<_>>();
@ -150,7 +152,7 @@ fn test_misc() {
dbg!(grouping.rank_word_avg_groups("volitif"));
dbg!(grouping.rank_word_avg_groups("amorcee"));
let mut gut = gutenberg(7);
let mut gut = dictionnary::gutenberg(7);
dbg!(gut.len());
let mut grouping = Grouping::new(gut.into_iter().filter(|w| w.starts_with('j')));