Skip to content
Snippets Groups Projects
Commit ee40be1e authored by tanguy.cavagna's avatar tanguy.cavagna :desktop:
Browse files

Non working tool

parent 5057ac2d
No related branches found
No related tags found
No related merge requests found
......@@ -21,7 +21,7 @@ int main(void) {
RUN_TEST(test_answer_shoud_be_balai);
RUN_TEST(test_validate_letter_should_be_false);
RUN_TEST(test_validate_letter_should_be_true);
RUN_TEST(test_generate_pattern_should_return_all_0);
// RUN_TEST(test_generate_pattern_should_return_all_0);
// Tool
RUN_TEST(test_compute_matches_should_be_empty);
......
......@@ -9,10 +9,12 @@ void test_compute_matches_should_be_empty(void) {
set_try("BRUTE");
Pattern *pattern = generate_pattern();
possibility_t **p = compute_matches("BRUTE", pattern);
save_computed_matches(p);
printf("%d\n", get_remaining_bank_count());
for (int i = 0; i < get_remaining_bank_count(); i++)
printf("%s\n", p[i]->word);
set_try("SALUT");
pattern = generate_pattern();
p = compute_matches("SALUT", pattern);
save_computed_matches(p);
free(pattern);
destroy_possibilities(p);
......
......@@ -8,13 +8,172 @@ char **remaining_bank;
int remaining_bank_count;
possibility_t **possibilities;
/**
* @brief Create a possibility
*
* @param word
* @param entropy
* @return
*/
possibility_t *create_possibility(char *word, double entropy) {
possibility_t *p = malloc(sizeof(possibility_t));
p->word = word;
p->word = calloc(WORD_LENGHT + 1, sizeof(char));
strcpy(p->word, word);
p->entropy = entropy;
return p;
}
/**
* @brief Destroiy a given matches set
*
* @param matches
*/
void destroy_matches(matches_t *matches) {
for (int i = 0; i < matches->count; i++)
free(matches->words[i]);
free(matches->words);
free(matches);
}
/**
* @brief Filter the remaining bank
*
* @param word
* @param pattern
* @return
*/
matches_t *filter_out_remaining_bank(char *word, Pattern *pattern, int print) {
matches_t *matches = malloc(sizeof(matches_t));
matches->count = 0;
if (print)
printf("%s\n\n", word);
// Create empty word matched array
char tmp[remaining_bank_count][WORD_LENGHT + 1];
for (int i = 0; i < remaining_bank_count; i++)
*tmp[i] = *"\0";
// Check validity for each remaning word
for (int j = 0; j < remaining_bank_count; j++) {
char current_word[WORD_LENGHT + 1];
strcpy(current_word, remaining_bank[j]);
bool valid_word = true;
for (int i = 0; i < WORD_LENGHT; i++) {
// Forced to create a string of only 1 char to get his position in the word
char current_char[2] = {word[i], '\0'};
// Filter out the non-valid words
if (pattern[i] == WRONG && (int)strcspn(current_word, current_char) != WORD_LENGHT) {
valid_word = false;
break;
}
if ((pattern[i] == MISPLACED && (int)strcspn(current_word, current_char) == WORD_LENGHT) ||
(pattern[i] == CORRECT && (int)strcspn(current_word, current_char) != i))
valid_word = false;
// Clear the current char to not impact futur letter checks
current_word[i] = ' ';
}
if (!valid_word)
continue;
strcpy(tmp[j], remaining_bank[j]);
matches->count++;
}
matches->words = malloc(matches->count * sizeof(char *));
int idx = 0;
for (int i = 0; i < remaining_bank_count; i++) {
if (strlen(tmp[i]) != 0) {
matches->words[idx] = calloc(WORD_LENGHT + 1, sizeof(char));
strcpy(matches->words[idx], tmp[i]);
idx++;
}
}
return matches;
}
/**
* @brief Compute the entropy of a given word
*
* @param word
* @return
*/
double compute_entropy(char *word) {
double sum = 0.0;
Pattern p[4] = {WRONG, MISPLACED, CORRECT, NAP};
Pattern *list[WORD_LENGHT] = {p, p, p, p, p};
Pattern *curr[WORD_LENGHT];
int n = sizeof(list) / sizeof(*list);
bool done = false;
for (int i = 0; i < n; i++)
curr[i] = list[i];
// Compute the product itself (0, 0, 0, 0, 0), (1, 0, 0, 0, 0), (2, 0, 0, 0, 0), (0, 1, 0, 0, 0), etc...
while (!done) {
// Compute current pattern entropy
matches_t *matches = filter_out_remaining_bank(word, (Pattern[WORD_LENGHT]){*curr[0], *curr[1], *curr[2], *curr[3], *curr[4]}, 0);
// Skip unmatch pattern
if (matches->count == 0) {
destroy_matches(matches);
done = true;
break;
}
// Apply Shannon's formula
double px = ((double)matches->count / (double)remaining_bank_count);
sum += px * (log2(1 / px));
destroy_matches(matches);
// Go to next pattern
int pattern_inc = 0;
curr[pattern_inc]++;
// Loop over the pattern and increment next position
while (*curr[pattern_inc] == NAP) {
curr[pattern_inc] = list[pattern_inc];
pattern_inc++;
if (pattern_inc == n) {
done = true;
break;
}
curr[pattern_inc]++;
}
}
return sum;
}
/**
* @brief Compare two given possibilites
*
* @param p1
* @param p2
* @return
*/
int compare_possibilities(const void *s1, const void *s2) {
const possibility_t *p1 = *(possibility_t **)s1;
const possibility_t *p2 = *(possibility_t **)s2;
if (p1->entropy < p2->entropy)
return -1;
else if (p1->entropy > p2->entropy)
return 1;
else
return 0;
}
//==========================
// PUBLIC
//==========================
......@@ -36,66 +195,45 @@ void destroy_tool() {
}
void destroy_possibilities(possibility_t **p) {
for (int i = 0; i < possibility_count; i++)
for (int i = 0; i < possibility_count; i++) {
free(p[i]->word);
free(p[i]);
}
free(p);
}
possibility_t **compute_matches(char *word, Pattern *pattern) {
possibility_count = 0;
char tmp_poss[remaining_bank_count][WORD_LENGHT + 1];
matches_t *matches = filter_out_remaining_bank(word, pattern, 1);
for (int i = 0; i < remaining_bank_count; i++)
*tmp_poss[i] = *"\0";
for (int i = 0; i < matches->count; i++)
printf("%s\n", matches->words[i]);
for (int j = 0; j < remaining_bank_count; j++) {
char current_word[WORD_LENGHT + 1];
strcpy(current_word, remaining_bank[j]);
bool valid_word = true;
for (int i = 0; i < WORD_LENGHT; i++) {
// Forced to create a string of only 1 char to get his position in the word
char current_char[2] = {word[i], '\0'};
possibility_count = matches->count;
// Filter out the non-valid words
if ((pattern[i] == WRONG && (int)strcspn(current_word, current_char) != WORD_LENGHT) ||
(pattern[i] == MISPLACED && (int)strcspn(current_word, current_char) == WORD_LENGHT) ||
(pattern[i] == CORRECT && (int)strcspn(current_word, current_char) != i))
valid_word = false;
// Create the new possibilities list
possibilities = calloc(possibility_count, sizeof(possibility_t *));
for (int i = 0; i < possibility_count; i++)
possibilities[i] = create_possibility(matches->words[i], compute_entropy(matches->words[i]));
// Clear the current char to not impact futur letter checks
current_word[i] = ' ';
}
destroy_matches(matches);
if (!valid_word)
continue;
// Sort possibilities by entropy ASC
qsort(possibilities, possibility_count, sizeof(possibility_t *), compare_possibilities);
strcpy(tmp_poss[j], remaining_bank[j]);
possibility_count++;
}
return possibilities;
}
void save_computed_matches(possibility_t **matches) {
// Free non-matching words
for (int i = possibility_count; i < remaining_bank_count; i++)
free(remaining_bank[i]);
int previous_remaining_count = remaining_bank_count;
// Realloc for the new matching words
remaining_bank_count = possibility_count;
remaining_bank = realloc(remaining_bank, remaining_bank_count * sizeof(char *));
// Create the new possibilities list
possibilities = calloc(remaining_bank_count, sizeof(possibility_t *));
int idx = 0;
for (int i = 0; i < previous_remaining_count; i++) {
if (strlen(tmp_poss[i]) != 0) {
strcpy(remaining_bank[idx], tmp_poss[i]);
possibilities[idx] = create_possibility(tmp_poss[i], 0.0);
idx++;
}
}
return possibilities;
for (int i = 0; i < remaining_bank_count; i++)
strcpy(remaining_bank[i], matches[i]->word);
}
int get_remaining_bank_count() { return remaining_bank_count; }
......
......@@ -3,6 +3,7 @@
#include "../word-bank/bank.h"
#include "../wordle/wordle.h"
#include <math.h>
#include <stdbool.h>
// Tool maximum possibility set
......@@ -13,6 +14,11 @@ typedef struct _possibility_t {
double entropy;
} possibility_t;
typedef struct _matches_t {
char **words;
int count;
} matches_t;
/**
* @brief Initialize the tool
*/
......@@ -38,6 +44,13 @@ void destroy_possibilities(possibility_t **p);
*/
possibility_t **compute_matches(char *word, Pattern *pattern);
/**
* @brief Save computed matches
*
* @param possibilities
*/
void save_computed_matches(possibility_t **matches);
/**
* @brief Get the remaning bank count
*
......
......@@ -13,7 +13,7 @@
// Enums
typedef enum Gamemode { SOLO, VERSUS, TOOL_ASSISTED } Gamemode;
typedef enum Pattern { WRONG, MISPLACED, CORRECT } Pattern;
typedef enum Pattern { WRONG, MISPLACED, CORRECT, NAP } Pattern; // NAP => Not A Pattern (Only used when computing all possible patterns)
/**
* @brief Initialize the game
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment