Skip to content
Snippets Groups Projects

Replace letter-boxed.c

Open Hye Won Park requested to merge hpark383/p1:main into main
1 file
+ 187
0
Compare changes
  • Side-by-side
  • Inline
+ 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