637 lines
26 KiB
C#
637 lines
26 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using CsvHelper;
|
|
using CsvHelper.Configuration;
|
|
using MathNet.Numerics.Statistics;
|
|
using NUnit.Framework;
|
|
|
|
namespace Core.Tests
|
|
{
|
|
[TestFixture]
|
|
public class WordleUtilTests
|
|
{
|
|
private static readonly char[] Alphabet = Enumerable.Range(0, 26).Select(r => Convert.ToChar('A' + r)).ToArray();
|
|
|
|
|
|
[Test]
|
|
public void GameTest()
|
|
{
|
|
var actual = "NAIVE";
|
|
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var frequency = new LetterPositionFrequency(dictionarySearcher, 5);
|
|
dictionarySearcher.SortDictionary(frequency);
|
|
|
|
var wordleState = new WordleUtil.WordleState();
|
|
|
|
do
|
|
{
|
|
var results =
|
|
dictionarySearcher
|
|
.FindWords(wordleState.InWord, wordleState.NotInWord, 5)
|
|
.Where(r => Regex.IsMatch(r, WordleUtil.GetRegexRestrictions(wordleState.Criteria)));
|
|
|
|
//var guess = frequency.ScoreWords(results).OrderBy(f => f.Item2).Last().Item1;
|
|
var guess = results.First();
|
|
var response = WordleUtil.GetGuessResult(actual, guess);
|
|
wordleState.Update(guess, response);
|
|
|
|
Console.WriteLine(guess);
|
|
|
|
} while (!wordleState.IsSolved());
|
|
}
|
|
|
|
|
|
[Test, Explicit]
|
|
public void GameTest_NaiveBayes_WriteOutput()
|
|
{
|
|
var wordleUtil = new WordleUtil();
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var wordFrequency = new WordFrequency();
|
|
var actual = "NAIVE";
|
|
|
|
|
|
var steps = 0;
|
|
var wordleState = new WordleUtil.WordleState();
|
|
do
|
|
{
|
|
var constrainedWords =
|
|
dictionarySearcher
|
|
.FindWords(wordleState.InWord, wordleState.NotInWord, 5)
|
|
.Where(r => Regex.IsMatch(r, WordleUtil.GetRegexRestrictions(wordleState.Criteria)))
|
|
.OrderByDescending(w => wordFrequency.GetWordFreq(w))
|
|
.ToList();
|
|
|
|
if (constrainedWords.First() == "NAIVE")
|
|
{
|
|
constrainedWords.RemoveAt(0);
|
|
constrainedWords.Add("NAIVE");
|
|
}
|
|
if (constrainedWords.Contains("WAIVE"))
|
|
{
|
|
constrainedWords.Remove("WAIVE");
|
|
constrainedWords.Add("WAIVE");
|
|
}
|
|
var letterCountPercents = GetLetterCountPercents(constrainedWords);
|
|
SetWordleConstraints(letterCountPercents, wordleState);
|
|
|
|
var frequency = new LetterPositionFrequency(constrainedWords.ToList(), 5);
|
|
var sortedWords = frequency.SortWords(constrainedWords, wordleUtil);
|
|
|
|
|
|
var guess = sortedWords.First();
|
|
|
|
var highestCounts =
|
|
string.Join("",
|
|
Enumerable.Range(0, 5).Select(i => letterCountPercents.Last()[i].OrderByDescending(s => s.Count).First().Letter));
|
|
|
|
WriteLetterCountPercentsCsv(letterCountPercents, constrainedWords, @"o:\tmp\WordleFreq\" + $"{steps}-{guess}", new[] { highestCounts, guess });
|
|
var response = WordleUtil.GetGuessResult(actual, guess);
|
|
wordleState.Update(guess, response);
|
|
|
|
Console.WriteLine(guess);
|
|
steps++;
|
|
|
|
} while (!wordleState.IsSolved());
|
|
}
|
|
|
|
[Test, Explicit]
|
|
public void GameTest_NaiveBayes()
|
|
{
|
|
var wordleUtil = new WordleUtil();
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var wordFrequency = new WordFrequency();
|
|
var actual = "NAIVE";
|
|
|
|
var steps = 0;
|
|
var wordleState = new WordleUtil.WordleState();
|
|
do
|
|
{
|
|
var constrainedWords =
|
|
dictionarySearcher
|
|
.FindWords(wordleState.InWord, wordleState.NotInWord, 5)
|
|
.Where(r => Regex.IsMatch(r, WordleUtil.GetRegexRestrictions(wordleState.Criteria)))
|
|
.OrderByDescending(w => wordFrequency.GetWordFreq(w))
|
|
.ToList();
|
|
|
|
var frequency = new LetterPositionFrequency(constrainedWords.ToList(), 5);
|
|
var sortedWords = frequency.SortWords(constrainedWords, wordleUtil);
|
|
|
|
//sortedWords.Reverse();
|
|
|
|
var guess = sortedWords.First();
|
|
|
|
var response = WordleUtil.GetGuessResult(actual, guess);
|
|
wordleState.Update(guess, response);
|
|
|
|
Console.WriteLine(guess);
|
|
} while (!wordleState.IsSolved());
|
|
}
|
|
|
|
[Test, Explicit]
|
|
public void GameTest_NaiveBayes_Reverse()
|
|
{
|
|
var wordleUtil = new WordleUtil();
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var wordFrequency = new WordFrequency();
|
|
var actual = "NAIVE";
|
|
|
|
|
|
var steps = 0;
|
|
var wordleState = new WordleUtil.WordleState();
|
|
do
|
|
{
|
|
var constrainedWords =
|
|
dictionarySearcher
|
|
.FindWords(wordleState.InWord, wordleState.NotInWord, 5)
|
|
.Where(r => Regex.IsMatch(r, WordleUtil.GetRegexRestrictions(wordleState.Criteria)))
|
|
.OrderByDescending(w => wordFrequency.GetWordFreq(w))
|
|
.ToList();
|
|
|
|
if (constrainedWords.First() == "NAIVE")
|
|
{
|
|
constrainedWords.RemoveAt(0);
|
|
constrainedWords.Add("NAIVE");
|
|
}
|
|
if (constrainedWords.Contains("WAIVE"))
|
|
{
|
|
constrainedWords.Remove("WAIVE");
|
|
constrainedWords.Add("WAIVE");
|
|
}
|
|
var letterCountPercents = GetLetterCountPercents(constrainedWords);
|
|
SetWordleConstraints(letterCountPercents, wordleState);
|
|
|
|
var frequency = new LetterPositionFrequency(constrainedWords.ToList(), 5);
|
|
var sortedWords = frequency.SortWords(constrainedWords, wordleUtil);
|
|
sortedWords.Reverse();
|
|
var bannedWords = new string[] { "TAINT", "AALII", "LAIGH", "SAIDS", "SAINS" };
|
|
sortedWords = sortedWords.SkipWhile(bannedWords.Contains).ToList();
|
|
|
|
var guess = sortedWords.First();
|
|
|
|
var highestCounts =
|
|
string.Join("",
|
|
Enumerable.Range(0, 5).Select(i => letterCountPercents.Last()[i].OrderBy(s => s.Count).First().Letter));
|
|
|
|
WriteLetterCountPercentsCsv(letterCountPercents, constrainedWords, @"o:\tmp\WordleFreqReverse\" + $"{steps}-{guess}", new[] { highestCounts, guess });
|
|
var response = WordleUtil.GetGuessResult(actual, guess);
|
|
wordleState.Update(guess, response);
|
|
|
|
Console.WriteLine(guess);
|
|
steps++;
|
|
|
|
} while (!wordleState.IsSolved());
|
|
}
|
|
|
|
private static void SetWordleConstraints(List<LetterCountPercent[][]> letterCountPercents, WordleUtil.WordleState wordleState)
|
|
{
|
|
foreach (var letter in wordleState.NotInWord)
|
|
{
|
|
var k = letter - 'A';
|
|
foreach (var letterCountPercent in letterCountPercents)
|
|
{
|
|
for (int j = 0; j < 5; j++)
|
|
letterCountPercent[j][k].State = "N";
|
|
}
|
|
}
|
|
|
|
for (var j = 0; j < wordleState.Criteria.Length; j++)
|
|
{
|
|
var criteria = wordleState.Criteria[j];
|
|
if (criteria.Correct != null)
|
|
{
|
|
var k = criteria.Correct.Value - 'A';
|
|
foreach (var letterCountPercent in letterCountPercents)
|
|
{
|
|
letterCountPercent[j][k].State = "C";
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(criteria.OtherPosition))
|
|
{
|
|
foreach (var letter in criteria.OtherPosition)
|
|
{
|
|
var k = letter - 'A';
|
|
foreach (var letterCountPercent in letterCountPercents)
|
|
{
|
|
letterCountPercent[j][k].State = "P";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class LetterCountPercent
|
|
{
|
|
public char Letter { get; }
|
|
public int Count { get; }
|
|
public float Percentage { get; }
|
|
|
|
/// <summary>
|
|
/// C: Correct, P: Present, N: Not Present, G: Guess, A: Active
|
|
/// </summary>
|
|
public string State { get; set; }
|
|
|
|
public LetterCountPercent(char letter, int count, double percentage, string state)
|
|
{
|
|
Letter = letter;
|
|
Count = count;
|
|
Percentage = (float)percentage;
|
|
State = state;
|
|
}
|
|
}
|
|
|
|
|
|
[Test]
|
|
public void NotInWordleList()
|
|
{
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var allFiveLeterWords = dictionarySearcher.FindWords("", "", 5);
|
|
var wordFrequency = new WordFrequency();
|
|
var wordleUtil = new WordleUtil();
|
|
var r =
|
|
from w in allFiveLeterWords
|
|
where !wordleUtil.Words.Contains(w)
|
|
let f = wordFrequency.GetWordFreq(w)
|
|
select Tuple.Create(w,f);
|
|
|
|
foreach (var s in r.OrderByDescending(t => t.Item2).Take(20))
|
|
{
|
|
Console.WriteLine(s);
|
|
}
|
|
}
|
|
|
|
[Test, Explicit]
|
|
public void LetterFrequenceStatistics_NoConstraints()
|
|
{
|
|
var frequency = new WordFrequency();
|
|
|
|
var wordleUtil = new WordleUtil();
|
|
|
|
var words = wordleUtil.Words.OrderByDescending(w => frequency.GetWordFreq(w)).ToList();
|
|
|
|
//var dictionarySearcher = new DictionarySearcher(5);
|
|
//var words = dictionarySearcher.GetWords().OrderByDescending(w => frequency.GetWordFreq(w)).ToList();
|
|
|
|
void MoveToFirst(string w)
|
|
{
|
|
words.Remove(w);
|
|
words.Insert(0, w);
|
|
}
|
|
MoveToFirst("LATER");
|
|
MoveToFirst("AFTER");
|
|
MoveToFirst("FIRST");
|
|
|
|
var results = GetLetterCountPercents(words);
|
|
|
|
var highestCounts =
|
|
string.Join("",
|
|
Enumerable.Range(0, 5).Select(i => results.Last()[i].OrderByDescending(s => s.Count).First().Letter));
|
|
|
|
WriteLetterCountPercentsCsv(results, words, @"o:\tmp\WordleFreq\NoConstraint", new []{ highestCounts, "SORES", "CARES"});
|
|
}
|
|
|
|
[Test, Explicit]
|
|
public void LetterFrequenceStatistics_NoConstraints_Reverse()
|
|
{
|
|
var frequency = new WordFrequency();
|
|
|
|
var wordleUtil = new WordleUtil();
|
|
|
|
var words = wordleUtil.Words.OrderByDescending(w => frequency.GetWordFreq(w)).ToList();
|
|
|
|
//var dictionarySearcher = new DictionarySearcher(5);
|
|
//var words = dictionarySearcher.GetWords().OrderByDescending(w => frequency.GetWordFreq(w)).ToList();
|
|
|
|
void MoveToFirst(string w)
|
|
{
|
|
words.Remove(w);
|
|
words.Insert(0, w);
|
|
}
|
|
MoveToFirst("LATER");
|
|
MoveToFirst("AFTER");
|
|
MoveToFirst("FIRST");
|
|
|
|
var results = GetLetterCountPercents(words);
|
|
|
|
var highestCounts =
|
|
string.Join("",
|
|
Enumerable.Range(0, 5).Select(i => results.Last()[i].OrderByDescending(s => s.Count).Last().Letter));
|
|
|
|
WriteLetterCountPercentsCsv(results, words, @"o:\tmp\WordleFreq\NoConstraint", new[] { highestCounts, "SORES", "CARES" });
|
|
}
|
|
|
|
private static List<LetterCountPercent[][]> GetLetterCountPercents(List<string> words)
|
|
{
|
|
var freqList = new Dictionary<char, int>[5];
|
|
for (var i = 0; i < 5; i++)
|
|
freqList[i] = Alphabet.ToDictionary(c => c, j => 0);
|
|
|
|
var wordCount = 0;
|
|
|
|
var results = new List<LetterCountPercent[][]> ();
|
|
|
|
foreach (var word in words)
|
|
{
|
|
wordCount++;
|
|
|
|
for (var wordIndex = 0; wordIndex < word.Length; wordIndex++)
|
|
{
|
|
var c = word[wordIndex];
|
|
freqList[wordIndex][c]++;
|
|
}
|
|
|
|
// get percentage
|
|
var freqPercents =
|
|
freqList.Select(
|
|
f => (
|
|
from cFreqs in f
|
|
select Tuple.Create(cFreqs.Key, cFreqs.Value * 1.0 / wordCount))
|
|
.ToDictionary(cp => cp.Item1, cp => cp.Item2))
|
|
.ToArray();
|
|
|
|
// normalize
|
|
var maxPercent = freqPercents.Max(fp => fp.Max(p => p.Value));
|
|
foreach (var freqPercent in freqPercents)
|
|
foreach (var c in freqPercent.Keys.ToArray())
|
|
freqPercent[c] /= maxPercent;
|
|
|
|
var result =
|
|
(from letter in Enumerable.Range(0, 5)
|
|
let item =
|
|
(from freq in freqList[letter]
|
|
from freqPercent in freqPercents[letter]
|
|
where freq.Key == freqPercent.Key
|
|
let state = word[letter] == freq.Key ? "A" : null
|
|
select new LetterCountPercent(freq.Key, freq.Value, freqPercent.Value, state)).ToArray()
|
|
select item).ToArray();
|
|
|
|
results.Add(result);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
private static void WriteLetterCountPercentsCsv(IReadOnlyList<LetterCountPercent[][]> results, IReadOnlyList<string> words, string folder, IList<string> g = null)
|
|
{
|
|
// hack:
|
|
IList<string> guesses = null;
|
|
if (g != null)
|
|
{
|
|
guesses = new List<string>(g);
|
|
guesses.Add(guesses.Last());
|
|
}
|
|
|
|
try
|
|
{
|
|
if (Directory.Exists(folder))
|
|
Directory.Delete(folder, true);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e);
|
|
}
|
|
Directory.CreateDirectory(folder);
|
|
|
|
using (var writer = new StreamWriter(Path.Combine(folder, "freq_words.csv")))
|
|
{
|
|
writer.WriteLine("word");
|
|
|
|
writer.WriteLine(" ");
|
|
writer.WriteLine(" ");
|
|
|
|
for (int i = 0; i < words.Count; i++)
|
|
{
|
|
writer.WriteLine(words[i]);
|
|
}
|
|
|
|
writer.WriteLine(" ");
|
|
writer.WriteLine(" ");
|
|
|
|
for (int i = 0; i < (guesses?.Count ?? 0); i++)
|
|
{
|
|
writer.WriteLine(guesses[i]);
|
|
}
|
|
}
|
|
|
|
for (int j = 0; j < 5; j++)
|
|
{
|
|
using (var writer = new StreamWriter(Path.Combine(folder, "freq_letterCounts_" + j + ".csv")))
|
|
{
|
|
writer.WriteLine(string.Join(",", Alphabet));
|
|
writer.WriteLine(string.Join(",", results[0][j].Select(lcp => 0)));
|
|
//writer.WriteLine(string.Join(",", results[0][j].Select(lcp => 0)));
|
|
for (var index = 0; index < results.Count + 3 + (guesses?.Count ?? 0); index++)
|
|
{
|
|
var indexX = index < results.Count ? index : results.Count - 1;
|
|
writer.WriteLine(string.Join(",", results[indexX][j].Select(lcp => lcp.Count)));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int j = 0; j < 5; j++)
|
|
{
|
|
using (var writer = new StreamWriter(Path.Combine(folder, "freq_letterPercents_" + j + ".csv")))
|
|
{
|
|
writer.WriteLine(string.Join(",", Alphabet));
|
|
writer.WriteLine(string.Join(",", results[0][j].Select(lcp => 0)));
|
|
writer.WriteLine(string.Join(",", results[0][j].Select(lcp => 0)));
|
|
for (var index = 0; index < results.Count + 2 + (guesses?.Count ?? 0); index++)
|
|
{
|
|
var indexX = index < results.Count ? index : results.Count - 1;
|
|
writer.WriteLine(string.Join(",", results[indexX][j].Select(lcp => lcp.Percentage)));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int j = 0; j < 5; j++)
|
|
{
|
|
using (var writer = new StreamWriter(Path.Combine(folder, "freq_letterState_" + j + ".csv")))
|
|
{
|
|
writer.WriteLine(string.Join(",", Alphabet));
|
|
writer.WriteLine(string.Join(",", results[0][j].Select(lcp => lcp.State == "A" || string.IsNullOrEmpty(lcp.State) ? " " : lcp.State)));
|
|
writer.WriteLine(string.Join(",", results[0][j].Select(lcp => lcp.State == "A" || string.IsNullOrEmpty(lcp.State) ? " " : lcp.State)));
|
|
|
|
|
|
for (var index = 0; index < results.Count; index++)
|
|
{
|
|
writer.WriteLine(string.Join(",", results[index][j].Select(lcp => string.IsNullOrEmpty(lcp.State) ? " " : lcp.State)));
|
|
}
|
|
|
|
writer.WriteLine(string.Join(",", results[results.Count - 1][j].Select(lcp => lcp.State == "A" || string.IsNullOrEmpty(lcp.State) ? " " : lcp.State)));
|
|
writer.WriteLine(string.Join(",", results[results.Count - 1][j].Select(lcp => lcp.State == "A" || string.IsNullOrEmpty(lcp.State) ? " " : lcp.State)));
|
|
|
|
|
|
for (int e = 0; e < (guesses?.Count ?? 0); e++)
|
|
{
|
|
var letter = guesses[e][j];
|
|
writer.WriteLine(string.Join(",", results[results.Count - 1][j].Select(lcp => lcp.Letter == letter ? "G" : lcp.State == "A" || string.IsNullOrEmpty(lcp.State) ? " " : lcp.State)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void NotInDictionary()
|
|
{
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var allFiveLeterWords = dictionarySearcher.FindWords("", "", 5);
|
|
var wordFrequency = new WordFrequency();
|
|
var wordleUtil = new WordleUtil();
|
|
var r =
|
|
from w in wordleUtil.Words
|
|
where !allFiveLeterWords.Contains(w)
|
|
let f = wordFrequency.GetWordFreq(w)
|
|
select Tuple.Create(w, f);
|
|
|
|
foreach (var s in r.OrderByDescending(t => t.Item2).Take(20))
|
|
{
|
|
Console.WriteLine(s);
|
|
}
|
|
}
|
|
|
|
[Test, Explicit]
|
|
public void WordleStats()
|
|
{
|
|
var actual = "GROUP";
|
|
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var allFiveLeterWords = dictionarySearcher.FindWords("", "");
|
|
var wordleUtil = new WordleUtil();
|
|
var frequency = new LetterPositionFrequency(wordleUtil, 5);
|
|
dictionarySearcher.SortDictionary(frequency);
|
|
|
|
// Console.WriteLine(dictionarySearcher.FindWords("", "", 5).Count());
|
|
|
|
var solutionSteps = new List<double>();
|
|
Parallel.ForEach(allFiveLeterWords, nextWord =>
|
|
{
|
|
var guess = nextWord;
|
|
var response = WordleUtil.GetGuessResult(actual, guess);
|
|
|
|
var wordleState = new WordleUtil.WordleState();
|
|
wordleState.Update(guess, response);
|
|
|
|
//Console.WriteLine("----");
|
|
//Console.WriteLine(guess);
|
|
|
|
var steps = 1;
|
|
while (!wordleState.IsSolved())
|
|
{
|
|
var results =
|
|
dictionarySearcher
|
|
.FindWords(wordleState.InWord, wordleState.NotInWord, 5)
|
|
.Where(r => Regex.IsMatch(r, WordleUtil.GetRegexRestrictions(wordleState.Criteria)));
|
|
guess = results.First();
|
|
//guess = frequency.ScoreWords(results).OrderBy(f => f.Item2).Last().Item1;
|
|
response = WordleUtil.GetGuessResult(actual, guess);
|
|
wordleState.Update(guess, response);
|
|
//Console.WriteLine(guess);
|
|
steps++;
|
|
}
|
|
solutionSteps.Add(steps);
|
|
});
|
|
//Console.WriteLine(string.Join(",", solutionSteps));
|
|
Console.WriteLine($"Mean: {solutionSteps.Mean()}, StdDev: {solutionSteps.StandardDeviation()}");
|
|
//Console.WriteLine(solutionSteps.Sum() * 1d / solutionSteps.Count );
|
|
}
|
|
|
|
|
|
[Test]
|
|
public void RepeatedLettersStatistics()
|
|
{
|
|
var wordleUtil = new WordleUtil();
|
|
var re =
|
|
from w in wordleUtil.Words
|
|
let repeats = WordleUtil.RepeatedLettersCount(w)
|
|
group repeats by repeats
|
|
into g
|
|
select g;
|
|
var max = re.Max(r => r.Count());
|
|
Console.WriteLine(string.Join(", ", re.Select(r => r.Key + ": " + r.Count() + $" {(r.Count() * 1.0) / max}")));
|
|
Console.WriteLine(string.Join(", ", wordleUtil.Words.Where(w => WordleUtil.RepeatedLettersCount(w) == 3)));
|
|
Console.WriteLine(string.Join(", ", wordleUtil.Words.Where(w => WordleUtil.RepeatedLettersCount(w) == 2)));
|
|
Console.WriteLine(string.Join(", ", wordleUtil.Words.Where(w => WordleUtil.RepeatedLettersCount(w) == 1)));
|
|
}
|
|
|
|
|
|
[Test]
|
|
public void SolveAllWordleWords_SortedDictionary()
|
|
{
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var wordleUtil = new WordleUtil();
|
|
var frequency = new LetterPositionFrequency(wordleUtil, 5);
|
|
dictionarySearcher.SortDictionary(frequency);
|
|
|
|
var solutionSteps = new List<double>();
|
|
Parallel.ForEach(wordleUtil.Words, actual =>
|
|
{
|
|
var steps = 0;
|
|
var wordleState = new WordleUtil.WordleState();
|
|
do
|
|
{
|
|
var results =
|
|
dictionarySearcher
|
|
.FindWords(wordleState.InWord, wordleState.NotInWord, 5)
|
|
.Where(r => Regex.IsMatch(r, WordleUtil.GetRegexRestrictions(wordleState.Criteria)));
|
|
|
|
if (steps <= 1)
|
|
results = results.SkipWhile(WordleUtil.RepeatedLetters);
|
|
|
|
var guess = results.First();
|
|
var response = WordleUtil.GetGuessResult(actual, guess);
|
|
wordleState.Update(guess, response);
|
|
|
|
//Console.WriteLine(guess);
|
|
steps++;
|
|
|
|
} while (!wordleState.IsSolved());
|
|
solutionSteps.Add(steps);
|
|
});
|
|
|
|
Console.WriteLine($"Mean: {solutionSteps.Mean()}, StdDev: {solutionSteps.StandardDeviation()}");
|
|
}
|
|
|
|
|
|
[Test]
|
|
public void SolveAllWordleWords_NaiveBayes()
|
|
{
|
|
var dictionarySearcher = new DictionarySearcher(5);
|
|
var wordleUtil = new WordleUtil();
|
|
var solutionSteps = new List<double>();
|
|
|
|
Parallel.ForEach(wordleUtil.Words, actual =>
|
|
{
|
|
var steps = 0;
|
|
var wordleState = new WordleUtil.WordleState();
|
|
do
|
|
{
|
|
var results =
|
|
dictionarySearcher
|
|
.FindWords(wordleState.InWord, wordleState.NotInWord, 5)
|
|
.Where(r => Regex.IsMatch(r, WordleUtil.GetRegexRestrictions(wordleState.Criteria)))
|
|
.ToList();
|
|
|
|
var frequency = new LetterPositionFrequency(results, 5);
|
|
results = frequency.SortWords(results, wordleUtil);
|
|
|
|
var guess = results.First();
|
|
var response = WordleUtil.GetGuessResult(actual, guess);
|
|
wordleState.Update(guess, response);
|
|
|
|
//Console.WriteLine(guess);
|
|
steps++;
|
|
|
|
} while (!wordleState.IsSolved());
|
|
solutionSteps.Add(steps);
|
|
});
|
|
|
|
Console.WriteLine($"Mean: {solutionSteps.Mean()}, StdDev: {solutionSteps.StandardDeviation()}");
|
|
}
|
|
}
|
|
} |