How to waste an afternoon writing bad code to help your girlfriend cheat at Wordle...
Tags: csharp, wordle
Published: 2022-05-07 07:55:30

As the title says, I wrote this to help my GF cheat at wordle.

Is the code commented? Heck no!
Is their error checking? Hardly any!
Am I incorrectly relying on a dictionary to preserve the order of keys as they are added? Yup!
And lets not forget my use of a goto statement and too many globals!

The app she is using is the android Lion Studios Wordle app, and I don't know what word list they are using. The closest I have found is the NASPA NSWL2020 word list, but there are still some words that appear in that list that the app doesn't recognize. (Incidentally, the New York Times uses the Collins word list)

Lets say your first word is "reads" and it shows that you have have an 'r' and an 'a', with the 'a' being in the correct location.
the parameters would be entered as such:

wordlesolver ra ed 11a11 r1

First parameter: Indicates letters in word.
Second parameter: Indicates letters not in word.
Third parameter: Show where letters are in word.
Fourth and above: Shows which letters are not in specified positions.

You can skip the first and second parameters by entering a '0', e.g., wordlesolver 0 0 11a11 r1.
You can skip the third parameter completely, and to indicate multiple letters that are not in indicated positions you can continue adding 2 character info, e.g.,
wordlesolver ra ed r1 t2 g4

wordlesolver ril eadspotf 11111 r1 i2 l2 l3 i3 r4 will produce the result "lyric".

Use the up arrow to get the last command and add the additional information.

Yes, the parameters could be parsed wayyyyyyyyy better, probably by just listing the words with the a number to indicate letters that are in the word and are in the correct spot, but this is about as much effort as I was willing to put into it.

Suggested words are created by the following method...
The first # is the number of letters in the word that have not been used and are in the possible solution list. The remaining numbers are the letter frequency score I generate for the word. Words are list in score order. In theory I would only need to list one word, but because the app occasionally doesn't recognize a word, multiple are listed.

```
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static Dictionary<string, int> word_dict = File.ReadAllLines(@"c:\a\words.txt").Distinct().OrderBy(x => x).ToDictionary(x => x, x => 0);
    static Dictionary<char, int> letter_dict = new() { { 'a', 0 }, { 'b', 0 }, { 'c', 0 }, { 'd', 0 }, { 'e', 0 }, { 'f', 0 }, { 'g', 0 }, { 'h', 0 }, { 'i', 0 }, { 'j', 0 }, { 'k', 0 }, { 'l', 0 }, { 'm', 0 }, { 'n', 0 }, { 'o', 0 }, { 'p', 0 }, { 'q', 0 }, { 'r', 0 }, { 's', 0 }, { 't', 0 }, { 'u', 0 }, { 'v', 0 }, { 'w', 0 }, { 'x', 0 }, { 'y', 0 }, { 'z', 0 } };
    static List<string> include = new();

    static void ParseArgs(string[] args)
    {
        int len = args.Length;

        foreach (string word in word_dict.Keys)
        {
            if (len > 2 && args[2].Length == 5)
                for (int j = 0; j < 5; j++)
                    if (char.IsLetter(args[2][j]))
                        if (word[j] != args[2][j])
                            goto end;

            if (len > 0 && args[0] != "0")
                for (int j = 0; j < args[0].Length; j++)
                    if (!word.Contains(args[0][j]))
                        goto end;

            if (len > 1 && args[1] != "0")
                for (int j = 0; j < args[1].Length; j++)
                    if (word.Contains(args[1][j]))
                        goto end;

            if (len > 3)
                for (int j = 0; j < len - 3; j++)
                    if (word[args[j + 3][1] - '0' - 1] == args[j + 3][0])
                        goto end;

            include.Add(word);

        end:;
        }
    }


    static void GetSolutions(string first)
    {
        foreach (string word in include)
            for (int i = 0; i < 5; i++)
                if (!first.Contains(word[i]))
                    letter_dict[word[i]]++;

        letter_dict = letter_dict.Where(x => x.Value > 0).OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

        if (include.Count <= 20)
        {
            Console.WriteLine("All possible solutions: ");
            foreach (string item in include)
                Console.Write($"{item} ");
        }
        else
            Console.Write($"There are {include.Count} possible solutions. ");

        Console.WriteLine("\n");
    }


    static void GetSuggestedWords()
    {
        foreach (string word in word_dict.Keys)
            foreach (char item in letter_dict.Keys.Distinct())
                if (word.Contains(item))
                    word_dict[word] += letter_dict[item] + 100000;

        word_dict = word_dict.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

        if (word_dict[word_dict.Keys.First()] >= 200000)
        {
            Console.WriteLine("Suggested word / Word score:");
            int count = 0;

            foreach (string item in word_dict.Keys)
                if (word_dict[item]! >= 200000)
                {
                    Console.Write("{0} {1} ", item, word_dict[item]);
                    count++;
                    if (count == 9)
                        break;
                }
        }

        Console.WriteLine("\n");
    }


    static void Main(string[] args)
    {
        Console.Clear();

        if (args.Length == 0)
        {
            args = new string[1];
            args[0] = "0";
        }

        ParseArgs(args);
        GetSolutions(args[0]);
        GetSuggestedWords();
    }

```