Skip to content

Instantly share code, notes, and snippets.

@brimonk
Created June 5, 2022 06:33
Show Gist options
  • Save brimonk/05d9572cac89c6fc336e89b356e5f042 to your computer and use it in GitHub Desktop.
Save brimonk/05d9572cac89c6fc336e89b356e5f042 to your computer and use it in GitHub Desktop.
My Wordle Solver (Probably Buggy)
// Brian Chrzanowski
// 2022-06-05 02:04:34
//
// My Wordle Solver.
//
// I'd been meaning to write one of these for a while. Basically, we slurp up the entire wordlist,
// and we literally just throw away words if they don't match the Worlde word.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#define DICTFILE "/usr/share/dict/american-english"
#define LISTLIM (1 << 20) // seems big enough :p
#define WORDLELEN (5)
char *WORDLIST[LISTLIM];
int TOTALWORDS = 0;
void strtolower(char *s)
{
for (;*s;s++) *s = tolower(*s);
}
void mktab(int *tab, char c, char *w, char *r)
{
for (int i = 0; i < WORDLELEN; i++) {
if (r == NULL || r[i] == c)
tab[w[i] - 'a']++;
}
}
int chkwon(char *s)
{
while (*s) {
if (*s != 'g')
return 0;
s++;
}
return 1;
}
int xmatch(char *candidate, char *word, char *result)
{
int tab[26];
memset(&tab, 0, sizeof tab);
mktab(tab, 'x', word, result);
for (int i = 0; i < WORDLELEN; i++) {
if (tab[candidate[i] - 'a'] > 0)
return 1;
}
return 0;
}
int gmatch(char *candidate, char *word, char *result)
{
int i;
for (i = 0; i < 5; i++)
if (result[i] == 'g' && candidate[i] != word[i])
return 0;
return 1;
}
int ymatch(char *candidate, char *word, char *result)
{
#define LETTERS 26
int yellows[LETTERS];
int clettrs[LETTERS];
memset(&yellows, 0, sizeof yellows);
memset(&clettrs, 0, sizeof clettrs);
mktab(yellows, 'y', word, result);
mktab(clettrs, 'y', candidate, NULL);
for (int i = 0; i < LETTERS; i++) {
if (0 < yellows[i] && !(clettrs[i] <= yellows[i]))
return 0;
}
return 1;
}
void crunchlist(char *word, char *result)
{
for (int i = 0; i < TOTALWORDS; i++) {
if (WORDLIST[i] == NULL)
continue;
if (xmatch(WORDLIST[i], word, result) || !(gmatch(WORDLIST[i], word, result) && ymatch(WORDLIST[i], word, result))) {
free(WORDLIST[i]);
WORDLIST[i] = NULL;
}
}
}
void printentries(int n)
{
for (int i = 0; i < TOTALWORDS && n; i++) {
if (WORDLIST[i] != NULL) {
printf("%s\n", WORDLIST[i]);
n--;
}
}
}
int main(int argc, char **argv)
{
FILE *fp;
char buf[1024];
int i;
memset(WORDLIST, 0, sizeof WORDLIST);
fp = fopen(DICTFILE, "rb");
if (!fp) {
fprintf(stderr, "couldn't open dictionary file!\n");
return 1;
}
for (i = 0; i < LISTLIM && buf == fgets(buf, sizeof buf, fp); i++) {
buf[strlen(buf) - 1] = 0;
if (strlen(buf) != 5) // wordle words are 5 chars long
continue;
#define CHARTEST(x) !(isalpha((x)) && islower((x)))
if (CHARTEST(buf[0])) continue;
if (CHARTEST(buf[1])) continue;
if (CHARTEST(buf[2])) continue;
if (CHARTEST(buf[3])) continue;
if (CHARTEST(buf[4])) continue;
assert(i < LISTLIM);
WORDLIST[TOTALWORDS++] = strdup(buf);
}
fclose(fp);
#if 0
for (i = 0; i < TOTALWORDS; i++) {
printf("%s\n", WORDLIST[i]);
}
#endif
char word[8];
char result[8];
int win_state, guess;
// As we ask the user for guesses and board states, we begin to filter the list to appropriate
// words that could be used in the future, assuming all input information is correct. To do
// this, we actually just free the item in the list and set the pointer to NULL, if it violates
// any of the information that we've got.
for (win_state = guess = 0; guess < 6 && !win_state; guess++) {
printf("Guess > ");
fgets(word, sizeof word, stdin);
word[strlen(word) - 1] = 0;
strtolower(word);
printf("State > ");
fgets(result, sizeof result, stdin);
result[strlen(result) - 1] = 0;
strtolower(result);
win_state = chkwon(result);
if (win_state)
break;
crunchlist(word, result);
printentries(10); // we literally don't do anything special to print a diverse set of guesses
}
if (win_state) {
printf("CONGRATS, YOU CHEATED!\n");
} else {
printf("You couldn't even win without cheating? Pathetic.\n");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment