Ok, I'm using gcc in ubuntu to compile.
Below is a boggle solver that basically loads a dictionary.txt file and then you would input a 5x5 grid of letters like below into the letter[][] array
a b c d e
f g h i j
k l m n o
p q r s t
u v w x y
one at a time at the terminal
a
b
c
ect.
however I'm trying to modify the program so that you can read in a second .txt file containing the above grid of letters in exactly that format directly into the letter[][] array (or any other combination of letters) instead of having to input each letter at the terminal and hitting enter. I've spent a few hours and it seems so simple but it's just not working. I keep getting segmentation faults and it's just not reading the grid of letters in the .txt file into the array correctly.
I've tried using both fgets and fscanf although probably incorrectly.
My problems are mostly occurring in int main() at the bottom for those who want to skip
down. I posted all the code in case you want to compile it on your own machine.
Working original version:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <time.h>
#define BOX_SIZE 5
#define MIN_WORD_LEN 3
#define NOT_SEEN 0
#define SEEN 1
#define FOUND_SIZE 1000
#define NUM_LETTERS 26
/* Define constants from dict.c */
char *found[FOUND_SIZE];
int graph[BOX_SIZE][BOX_SIZE];
char choices[BOX_SIZE*BOX_SIZE];
int letter[BOX_SIZE][BOX_SIZE];
int num_found = 0;
typedef struct trie_node TRIE_NODE;
struct trie_node {
char let;
char mark;
TRIE_NODE *next[NUM_LETTERS];
};
/* The grid of boggle letters. */
TRIE_NODE trie_root;
int trie_num_nodes;
void trie_init_node(TRIE_NODE *n)
{
int i;
n -> let = '\0';
n -> mark = 0;
for (i = 0; i < NUM_LETTERS; i++)
n ->next[i] = NULL;
}
TRIE_NODE *trie_new_node(int let)
{
TRIE_NODE *new_node;
trie_num_nodes++;
new_node = malloc(sizeof(TRIE_NODE));
assert(new_node != NULL);
trie_init_node(new_node);
new_node -> let = let;
return new_node;
}
void trie_init()
{
trie_init_node(&trie_root);
trie_num_nodes = 0;
}
void trie_add_word(char *word)
{
TRIE_NODE *curr_node = &trie_root;
char *curr_let;
int next_let;
if (word == NULL || *word == '\0')
{
fprintf(stderr, "error: can't add null word to trie \n");
}
curr_let = word;
while(*curr_let != '\0')
{
next_let = tolower(*curr_let) - 'a';
if (next_let < 0 || next_let >= NUM_LETTERS)
{
fprintf(stderr, "error: can't add word '%s' (illegal character)\n", word);
return;
}
if (curr_node->next[next_let] == NULL)
curr_node->next[next_let] = trie_new_node(next_let);
curr_node = curr_node->next[next_let];
curr_let++;
}
curr_node->mark = 1;
}
char walk_buf[128];
void trie_walk_node(TRIE_NODE *n, int depth)
{
int i;
depth++;
if (n->mark)
{
walk_buf[depth] = '\0';
puts(walk_buf);
}
for (int i = 0; i < NUM_LETTERS; i++)
{
if (n->next[i] != NULL)
{
walk_buf[depth] = i + 'a';
trie_walk_node(n->next[i], depth);
}
}
}
void trie_walk()
{
trie_walk_node(&trie_root, -1);
}
void try_print(int depth)
{
int i;
choices[depth] = '\0';
if (num_found >= FOUND_SIZE)
{
printf("too many words found\n");
return;
}
for (i = 0; i < num_found; i++)
if (!strcmp(choices, found[i]))
return;
found[num_found++] = strdup(choices);
printf("%s\n", choices);
}
void dfs(int x, int y, int depth, TRIE_NODE *trie_node)
{
int i, j;
if (x < 0 || y < 0 || x >= BOX_SIZE || y >= BOX_SIZE)
return;
if (graph[x][y] == SEEN)
return;
if ((trie_node = trie_node->next[letter[x][y]]) == NULL)
return;
choices[depth++] = letter[x][y] + 'a';
if (trie_node->mark && depth >= MIN_WORD_LEN)
try_print(depth);
graph[x][y] = SEEN;
for (j = -1; j <= 1; j++)
for (i = -1; i <= 1; i++)
if(i || j)
dfs(x+i, y+j, depth, trie_node);
graph[x][y] = NOT_SEEN;
}
int main ()
{
int i, j, let_number;
unsigned seed = (unsigned) time (0);
srand (seed);
char buf[128];
FILE *fp;
FILE *fp2;
fp = fopen("wordlist.txt", "r");
if (fp == NULL)
{
perror("Error opening dictionary.");
exit(0);
}
trie_init();
while (fgets(buf, 128, fp))
{
buf[strlen(buf)-1] = '\0';
for (i = 0; i < strlen(buf); i++)
buf[i] = tolower(buf[i]);
trie_add_word(buf);
}
for (j = 0; j < BOX_SIZE; j++) {
for (i = 0; i < BOX_SIZE; i++) {
/* grab a char */
do {
scanf("%s", buf);
} while (!isalpha(*buf));
/* make sure it's legal */
let_number = tolower(*buf) - 'a';
if (let_number < 0 || let_number >= NUM_LETTERS) {
fprintf(stderr, "illegal character '%c' in board\n", *buf);
exit(1);
}
/* put it in our matrix */
letter[i][j] = let_number;
graph[i][j] = NOT_SEEN;
}
}
/* walk the matrix */
for (j = 0; j < BOX_SIZE; j++)
for (i = 0; i < BOX_SIZE; i++)
dfs(i, j, 0, &trie_root);
return 0;
}
My attempt at what I'm trying to do //all my modifications are in main()
int main ()
{
int i, j, let_number;
char buf[128];
char buf2[128];
FILE *fp;
FILE *fp2;
fp = fopen("wordlist.txt", "r");
if (fp == NULL)
{
perror("Error opening dictionary.");
exit(0);
}
trie_init();
while (fgets(buf, 128, fp))
{
buf[strlen(buf)-1] = '\0';
for (i = 0; i < strlen(buf); i++)
buf[i] = tolower(buf[i]);
trie_add_word(buf);
}
fp2 = fopen("puzzle.txt", "r");
for (j = 0; j < BOX_SIZE; j++)
{
for (i = 0; i < BOX_SIZE; i++)
{
fscanf(fp2, "%c", &letter[i][j]);
let_number = tolower(letter[i][j]) - 'a';
letter[i][j] = let_number;
printf ("%d \n", letter[i][j]);
graph[i][j] = NOT_SEEN;
}
}
for (j = 0; j < BOX_SIZE; j++)
for (i = 0; i < BOX_SIZE; i++)
dfs(i, j, 0, &trie_root);
return 0;