Part 2 :)
This commit is contained in:
parent
eeca1d3a49
commit
292bd581a5
88
src/main.rs
88
src/main.rs
|
@ -3,12 +3,14 @@ use std::collections::HashMap;
|
||||||
use bitintr::{Lzcnt, Tzcnt};
|
use bitintr::{Lzcnt, Tzcnt};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
//use itertools::Itertools;
|
||||||
|
|
||||||
type Charmask = i32;
|
type Charmask = i32;
|
||||||
type Achar = i8; // ASCII char
|
type Achar = i8; // ASCII char
|
||||||
|
|
||||||
const WORD_LENGTH: usize = 5;
|
const WORD_LENGTH: usize = 5;
|
||||||
const WORD_LENGTH_P: usize = 5; // Padded for SIMD shenanigans
|
const WORD_LENGTH_P: usize = 5; // Padded for SIMD shenanigans
|
||||||
|
const GUESS_DEPTH: usize = 2;
|
||||||
const A: Achar = 'A' as Achar;
|
const A: Achar = 'A' as Achar;
|
||||||
const Z: Achar = 'Z' as Achar;
|
const Z: Achar = 'Z' as Achar;
|
||||||
|
|
||||||
|
@ -56,6 +58,10 @@ fn load_dictionary(filename: &str) -> Vec<Word> {
|
||||||
words.iter().map(|w| str2word(w)).collect()
|
words.iter().map(|w| str2word(w)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn letters2str(letters: [Achar; WORD_LENGTH]) -> String {
|
||||||
|
letters.iter().map(|x| (*x as u8) as char).collect()
|
||||||
|
}
|
||||||
|
|
||||||
/* fn inc_char(c: char) -> char {
|
/* fn inc_char(c: char) -> char {
|
||||||
(c as u8 + 1) as char
|
(c as u8 + 1) as char
|
||||||
} */
|
} */
|
||||||
|
@ -70,6 +76,16 @@ fn load_dictionary(filename: &str) -> Vec<Word> {
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
/* fn charmask2str(cm: Charmask) -> String {
|
||||||
|
let mut s = String::default();
|
||||||
|
for i in cm.tzcnt() ..= 32-cm.lzcnt() {
|
||||||
|
if (cm & (1<<i)) != 0 {
|
||||||
|
s += &((A + i as Achar) as u8 as char).to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
fn char2bit(c: Achar) -> Charmask {
|
fn char2bit(c: Achar) -> Charmask {
|
||||||
debug_assert!((A..=Z).contains(&c));
|
debug_assert!((A..=Z).contains(&c));
|
||||||
|
@ -103,25 +119,32 @@ fn generate_wordcache(words: Vec<Word>) -> WordCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_word(w: &[Charmask; WORD_LENGTH_P], banned_chars: &[Charmask; WORD_LENGTH_P]) -> bool {
|
fn filter_word(w: &[Charmask; WORD_LENGTH_P], banned_chars: &[Charmask; WORD_LENGTH_P]) -> bool {
|
||||||
for i in 0..WORD_LENGTH {
|
w.iter().zip(banned_chars.iter()).all(|(x,y)| x & y == 0)
|
||||||
if w[i] & banned_chars[i] != 0 {return false;}
|
// for i in 0..WORD_LENGTH {
|
||||||
}
|
// if w[i] & banned_chars[i] != 0 {return false;}
|
||||||
true
|
// }
|
||||||
|
// true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simulate(guess: &Word, solution: &Word, mut s: SimState, wordcache: &WordCache) -> usize {
|
fn simulate(guess_ids: [usize; GUESS_DEPTH], solution_id: usize, mut s: SimState, wordcache: &WordCache) -> usize {
|
||||||
s.required_chars |= guess.charmask & solution.charmask;
|
let allwords = &wordcache[&0];
|
||||||
let bans = guess.charmask & !solution.charmask;
|
let solution = allwords[solution_id];
|
||||||
|
let mut bans = 0;
|
||||||
|
for guess_id in guess_ids {
|
||||||
|
let guess = allwords[guess_id];
|
||||||
|
s.required_chars |= guess.charmask & solution.charmask;
|
||||||
|
bans |= guess.charmask & !solution.charmask;
|
||||||
|
for i in 0..WORD_LENGTH {
|
||||||
|
if guess.letters[i] == solution.letters[i] { // Right letter right position
|
||||||
|
s.banned_chars[i] = !guess.charbits[i];
|
||||||
|
} else if guess.charbits[i] & solution.charmask != 0 { // Right letter wrong position
|
||||||
|
s.banned_chars[i] |= guess.charbits[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for j in 0..s.banned_chars.len() {
|
for j in 0..s.banned_chars.len() {
|
||||||
s.banned_chars[j] |= bans;
|
s.banned_chars[j] |= bans;
|
||||||
}
|
}
|
||||||
for i in 0..WORD_LENGTH {
|
|
||||||
if guess.letters[i] == solution.letters[i] { // Right letter right position
|
|
||||||
s.banned_chars[i] = !guess.charbits[i];
|
|
||||||
} else if guess.charbits[i] & solution.charmask != 0 { // Right letter wrong position
|
|
||||||
s.banned_chars[i] |= guess.charbits[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let cachekey = s.required_chars;
|
let cachekey = s.required_chars;
|
||||||
match wordcache.contains_key(&cachekey) {
|
match wordcache.contains_key(&cachekey) {
|
||||||
true => wordcache[&cachekey].iter().filter(|w| filter_word(&w.charbits, &s.banned_chars)).count(),
|
true => wordcache[&cachekey].iter().filter(|w| filter_word(&w.charbits, &s.banned_chars)).count(),
|
||||||
|
@ -129,44 +152,43 @@ fn simulate(guess: &Word, solution: &Word, mut s: SimState, wordcache: &WordCach
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_worstcase(word: &Word, wordcache: &WordCache) -> (String, usize) {
|
fn find_worstcase(word_ids: [usize; GUESS_DEPTH], wordcache: &WordCache) -> (String, usize) {
|
||||||
|
let allwords = &wordcache[&0];
|
||||||
|
|
||||||
let mut worst = 0;
|
let mut worst = 0;
|
||||||
let mut worst_w = wordcache[&0][0].letters;
|
let mut worst_w = 0;
|
||||||
let ss = SimState::default();
|
let ss = SimState::default();
|
||||||
for target in &wordcache[&0] {
|
for target_id in 0..allwords.len() {
|
||||||
let remaining = simulate(word, target, ss, wordcache);
|
let remaining = simulate(word_ids, target_id, ss, wordcache);
|
||||||
if remaining > worst {
|
if remaining > worst {
|
||||||
worst = remaining;
|
worst = remaining;
|
||||||
worst_w = target.letters;
|
worst_w = target_id;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let wordstr: String = word.letters.iter().map(|x| (*x as u8) as char).collect();
|
let wordstr: String = word_ids.map(|i| letters2str(allwords[i].letters)).join(", ");
|
||||||
let worststr: String = worst_w.iter().map(|x| (*x as u8) as char).collect();
|
let worststr: String = letters2str(allwords[worst_w].letters);
|
||||||
let output = format!("{} - {} ({})", wordstr, worst, worststr);
|
let output = format!("{} - {} ({})", wordstr, worst, worststr);
|
||||||
println!("{}", output);
|
println!("{}", output);
|
||||||
(output, worst)
|
(output, worst)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn charmask2str(cm: Charmask) -> String {
|
|
||||||
let mut s = String::default();
|
|
||||||
for i in cm.tzcnt() ..= 32-cm.lzcnt() {
|
|
||||||
if (cm & (1<<i)) != 0 {
|
|
||||||
s += &((A + i as Achar) as u8 as char).to_string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
fs::write("test.txt", ["test1", "test2", "test3"].join("\n")).expect("Failed to write output");
|
fs::write("test.txt", ["test1", "test2", "test3"].join("\n")).expect("Failed to write output");
|
||||||
let words = load_dictionary("words");
|
let words = load_dictionary("words");
|
||||||
println!("Hello, world! {} words in dict", words.len());
|
let totalwords = words.len();
|
||||||
|
println!("Hello, world! {} words in dict", totalwords);
|
||||||
let wordcache = generate_wordcache(words);
|
let wordcache = generate_wordcache(words);
|
||||||
|
|
||||||
//let sr = simulate(&wordcache[""][0], &wordcache[""][5000], &wordcache);
|
//let sr = simulate(&wordcache[""][0], &wordcache[""][5000], &wordcache);
|
||||||
//println!("{:?}", sr);
|
//println!("{:?}", sr);
|
||||||
|
|
||||||
let mut results: Vec<(String, usize)> = wordcache[&0].par_iter().map(|w| find_worstcase(w, &wordcache)).collect();
|
//(0..=5).flat_map(|i| (i..=5).map(move |j| (i,j))).map(|(i,j)| print!("{},{}\t", i, j));
|
||||||
|
let mut results: Vec<(String, usize)> =
|
||||||
|
(0..totalwords).into_par_iter().flat_map_iter(|i| (i..totalwords).map(move |j| (i,j)))
|
||||||
|
.map(|(i, j)| find_worstcase([i, j], &wordcache)).collect();
|
||||||
|
// let mut results: Vec<(String, usize)> =
|
||||||
|
// (0..totalwords).into_par_iter()
|
||||||
|
// .map(|i| find_worstcase([i], &wordcache)).collect();
|
||||||
results.sort_by_key(|r| r.1);
|
results.sort_by_key(|r| r.1);
|
||||||
let results_strs: Vec<String> = results.iter().map(|r| r.0.clone()).collect();
|
let results_strs: Vec<String> = results.iter().map(|r| r.0.clone()).collect();
|
||||||
fs::write("results.txt", results_strs.join("\n")).expect("Failed to write output");
|
fs::write("results.txt", results_strs.join("\n")).expect("Failed to write output");
|
||||||
|
|
Loading…
Reference in New Issue