Skip to content
Snippets Groups Projects

Replace letter-boxed.c

Open Hye Won Park requested to merge hpark383/p1:main into main
+ 187
0
#define _POSIX_C_SOURCE 200809L
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIDES 26
#define MAX_ALPHABET 10
#define INITIAL_DICT_SIZE 10000
#define MAX_WORD_SIZE 100
typedef struct {
char sides[MAX_SIDES][MAX_ALPHABET + 1];
int numSides;
} Board;
void loadBoard(const char *fileName, Board *board);
char **loadDict(const char *fileName, int *num);
int isValidWord(const char *inputWord, char **dict, Board *board, int dictNum, int *trackChar);
void freeMemory(char **dict, int dictNum);
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage: ./letter-boxed <board file> <dictionary file>\n");
exit(1);
}
Board board;
loadBoard(argv[1], &board); // load letter boxed board with board file input
int dictNum = 0; // number of words in dictionary
char **dict = loadDict(argv[2], &dictNum); // store dictionary words in 2d array
int trackChar[26] = {0}; // array to track characters in word
char currInput[MAX_WORD_SIZE];
char prevInput[MAX_WORD_SIZE] = "";
while (scanf("%s", currInput) != EOF) {
if (prevInput[0] != '\0' && prevInput[strlen(prevInput) - 1] != currInput[0]) {
printf("First letter of word does not match last letter of previous word\n");
exit(1);
}
if (!isValidWord(currInput, dict, &board, dictNum, trackChar)) {
freeMemory(dict, dictNum);
exit(0);
}
strcpy(prevInput, currInput); // update previous input
}
for (int i = 0; i < board.numSides; i++) {
for (size_t j = 0; j < strlen(board.sides[i]); j++) {
if (!trackChar[board.sides[i][j] - 'a']) {
printf("Not all letters used\n");
exit(0);
}
}
}
printf("Correct\n");
freeMemory(dict, dictNum);
return 0;
}
void loadBoard(const char *fileName, Board *board) {
FILE *file = fopen(fileName, "r");
if (!file) {
printf("Board file invalid\n");
exit(1);
}
int trackCharNum[26] = {0};
board->numSides = 0;
// read each side(line) from file and store in the board side array
while (fgets(board->sides[board->numSides], MAX_ALPHABET + 1, file) != NULL) {
board->sides[board->numSides][strcspn(board->sides[board->numSides], "\n")] = 0; // remove newline
for (size_t i = 0; i < strlen(board->sides[board->numSides]); i++) {
int charIndex = board->sides[board->numSides][i] - 'a';
if (trackCharNum[charIndex] > 0) {
printf("Invalid board\n"); // board contains a letter more than once
exit(1);
}
trackCharNum[charIndex]++;
}
board->numSides++; // next side(line) of the board
}
if (board->numSides < 3) {
printf("Invalid board\n");
exit(1);
}
fclose(file);
}
char **loadDict(const char *fileName, int *num) {
FILE *file = fopen(fileName, "r");
if (!file) {
printf("Dictionary file invalid\n");
exit(1);
}
int dictSize = INITIAL_DICT_SIZE;
char **dict = malloc(dictSize * sizeof(char *));
if (!dict) {
printf("Memory allocation of dictionary array failed\n");
exit(1);
}
char word[MAX_WORD_SIZE];
while (fscanf(file, "%s", word) != EOF) {
if (*num >= dictSize) {
dictSize *= 2;
char **newDict = realloc(dict, dictSize * sizeof(char *)); // dynamically allocate memory
if (!newDict) {
freeMemory(dict, *num);
printf("Memory allocation failed\n");
exit(1);
}
dict = newDict;
}
dict[*num] = strdup(word); // assign word in the dictionary file to the dictionary array
if (!dict[*num]) {
freeMemory(dict, *num);
printf("Memory allocation failed\n");
exit(1);
}
(*num)++; // increment num after allocation
}
fclose(file);
return dict;
}
int isValidWord(const char *inputWord, char **dict, Board *board, int dictNum, int *trackChar) {
bool foundDict = false;
for (int i = 0; i < dictNum; i++) {
if (strcmp(inputWord, dict[i]) == 0) {
foundDict = true;
break;
}
}
if (!foundDict) {
printf("Word not found in dictionary\n");
return 0;
}
int prevSideNum = -1;
for (size_t i = 0; i < strlen(inputWord); i++) {
char currChar = inputWord[i]; // loop through each character of word
bool foundBoard = false;
for (int sideNum = 0; sideNum < board->numSides; sideNum++) {
if (strchr(board->sides[sideNum], currChar) != NULL) { // returns the index of char if found in board side
foundBoard = true;
if (prevSideNum == sideNum) {
printf("Same-side letter used consecutively\n");
return 0;
}
trackChar[currChar - 'a'] = 1;
prevSideNum = sideNum; // update previous side num to the board side num in which char exists
break; // break out of the loop since the char is found in the board
}
}
if (!foundBoard) {
printf("Used a letter not present on the board\n");
return 0;
}
}
return 1;
}
void freeMemory(char **dict, int dictNum) {
for (int i = 0; i < dictNum; i++) {
free(dict[i]);
}
free(dict);
}
Loading