diff --git a/problems/skiing-in-singapore/README.md b/problems/skiing-in-singapore/README.md index 757cde1..7520198 100644 --- a/problems/skiing-in-singapore/README.md +++ b/problems/skiing-in-singapore/README.md @@ -1,8 +1,4 @@ # Skiing in Singapore -I came across this programming excercise from redmart that caught my interest. At the same time im in the midst of the harvard's cs50 course which i took through edx as a refresher. So I thought of taking up the programming excercise challenge and try to implement it using c. So without further ado, the challenge description goes like this: - -==================== - Sometimes it's nice to take a break and code up a solution to a small, fun problem. Here is one some of our engineers enjoyed recently called Skiing In Singapore. Well you can’t really ski in Singapore. But let’s say you hopped on a flight to the Niseko ski resort in Japan. Being a software engineer you can’t help but value efficiency, so naturally you want to ski as long as possible and as fast as possible without having to ride back up on the ski lift. So you take a look at the map of the mountain and try to find the longest ski run down. diff --git a/problems/spreadsheet/README.md b/problems/spreadsheet/README.md new file mode 100644 index 0000000..21805ce --- /dev/null +++ b/problems/spreadsheet/README.md @@ -0,0 +1,27 @@ +# Programming Challenge + +A spreadsheet consists of a two-dimensional array of cells, labeled A1, A2, etc. Rows are identified using letters, columns by numbers. Each cell contains either an integer (its value) or an expression. Expressions contain integers, cell references, and the operators '+', '-', '\*', '/' with the usual rules of evaluation – note that the input is RPN and should be evaluated in stack order. + +The spreadsheet input is defined as follows: + +1. Line 1: two integers, defining the width and height of the spreadsheet (n, m) + +2. n\*m lines each containing an expression which is the value of the corresponding cell (cells enumerated in the order A1, A2, A, B1, ...) + +## The Input +3 2 +A2 +4 5 * +A1 +A1 B2 / 2 + +3 +39 B1 B2 * / + +## The Output +3 2 +20.00000 +20.00000 +20.00000 +8.66667 +3.00000 +1.50000 diff --git a/solutions/c/spreadsheet/3x2.txt b/solutions/c/spreadsheet/3x2.txt new file mode 100644 index 0000000..05f2106 --- /dev/null +++ b/solutions/c/spreadsheet/3x2.txt @@ -0,0 +1,7 @@ +3 2 +A2 +4 5 * +A1 +A1 B2 / 2 + +3 +39 B1 B2 * / diff --git a/solutions/c/spreadsheet/Makefile b/solutions/c/spreadsheet/Makefile new file mode 100644 index 0000000..549b86d --- /dev/null +++ b/solutions/c/spreadsheet/Makefile @@ -0,0 +1,11 @@ + +all: spreadsheet + +spreadsheet: spreadsheet.c matrix.c matrix.h stackcalc.h stackcalc.c regex.h regex.c commons.h commons.c + clang -ggdb3 -O0 -std=c99 -Wall -Werror -o spreadsheet spreadsheet.c matrix.c regex.c commons.c stackcalc.c -I/usr/local/include -L/usr/local/lib/ -lpcre2-8 + +test: matrix_test.c regex.c commons.c regex.h matrix.h stackcalc.h stackcalc.c + clang -o matrixTest -ggdb3 -Wall -Werror -O0 -std=c99 -I/usr/local/include matrix_test.c matrix.c regex.c commons.c stackcalc.c -L/usr/local/lib/ -lpcre2-8 -lcmocka + +clean: + rm -f *.o a.out spreadsheet core diff --git a/solutions/c/spreadsheet/README.md b/solutions/c/spreadsheet/README.md new file mode 100644 index 0000000..78ef85e --- /dev/null +++ b/solutions/c/spreadsheet/README.md @@ -0,0 +1,12 @@ +# Dependencies + +This program depends on the following: +1. pcre2-10.20 - Pattern matching, regular expression +2. cmocka-1.0.0 - For Unit Tests + +Please refer to their respective documentations on how to install these libraries into your respective system + +# Execution +It is required that the $LD\_LIBRARY\_PATH environment variable be set to the directory where the pcre.so is located if it is located other than /usr/lib + + diff --git a/solutions/c/spreadsheet/commons.c b/solutions/c/spreadsheet/commons.c new file mode 100644 index 0000000..3e01306 --- /dev/null +++ b/solutions/c/spreadsheet/commons.c @@ -0,0 +1,14 @@ +#include "commons.h" + +int getNumberOfDigits(int n) +{ + if (n < 0) return -1; + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + + return -1; +} diff --git a/solutions/c/spreadsheet/commons.h b/solutions/c/spreadsheet/commons.h new file mode 100644 index 0000000..b52873e --- /dev/null +++ b/solutions/c/spreadsheet/commons.h @@ -0,0 +1,6 @@ + +/** + * Returns the number of digits in the integer n + */ +int getNumberOfDigits(int n); + diff --git a/solutions/c/spreadsheet/matrix.c b/solutions/c/spreadsheet/matrix.c new file mode 100644 index 0000000..98c713d --- /dev/null +++ b/solutions/c/spreadsheet/matrix.c @@ -0,0 +1,215 @@ +#define _XOPEN_SOURCE 700 +#define PCRE2_CODE_UNIT_WIDTH 8 + +#include +#include +#include +#include +#include + +#include "regex.h" +#include "matrix.h" +#include "commons.h" + +// ~ Static function propotypes ================== +static int isCyclicError(const Worksheet *worksheet, const char *visitedCells, CellReference *cellReference); + +/** + * Initializes the worksheet cells of size rows * columns. + * + * Returns 0 if an error is encountered. + */ +int initWorksheet(Worksheet *worksheet, int rows, int columns) { + worksheet->rows = rows; + worksheet->cols = columns; + + char ***matrix = (char ***) malloc(sizeof(char **) * rows); + for(int i = 0; i < rows; i++) { + matrix[i] = (char **) malloc(sizeof(char *) * columns); + + for(int j = 0; j < columns; j++) { + matrix[i][j] = (char *) calloc(sizeof(char) * CELL_CONTENT_LIMIT, sizeof(char)); + } + } + + worksheet->cells = matrix; + return 1; +} + +int closeWorksheet(Worksheet *w) +{ + for(int i = 0; i < w->rows; i++) + { + for(int j = 0; j < w->cols; j++) + { + free(w->cells[i][j]); + } + free(w->cells[i]); + } + free(w->cells); + free(w); + return 1; +} + +/** + * Sets s to the worksheet cell at row, column. + * + * Returns 0 if strlen(s) > CELL_CONTENT_LIMIT + */ +int setValue(Worksheet *worksheet, int row, int column, char* s) { + if (strlen(s) <= CELL_CONTENT_LIMIT) { + strncpy(worksheet->cells[row][column], s, strlen(s)); + return 1; + } else { + return 0; + } +} + +/** + * Returns the value at row, col + */ +char* getValue(const Worksheet *worksheet, int row, int column) { + return worksheet->cells[row][column]; +} + +int getValue2(const Worksheet *w, char **buffer, int row, int column) +{ + if (w == NULL) return 0; + if (w->cells[row][column] == NULL) return 0; + + *buffer = malloc(sizeof(char) * strlen(w->cells[row][column]) + 1); + strcpy(*buffer, w->cells[row][column]); + + return 1; +} + +/** + * Converts the given location (row, column) to a spreadsheet cell reference i.e. A1 + */ +CellReference *convertToCellReference(const MatrixLocation *location) +{ + CellReference *ref = malloc(sizeof(CellReference)); + + char *colRef = malloc(sizeof(char) * getNumberOfDigits(location->col) + 1); + sprintf(colRef, "%d", location->col + 1); + + // row ref + col ref + null terminator + ref->cellReference = malloc(sizeof(char) * (1 + strlen(colRef) + 1) + 1); + sprintf(ref->cellReference, "%c%s", (char)(location->row + ROW_TO_ASCII_OFFSET), colRef); + free(colRef); + + return ref; +} + +/** + * Returns a pointer to a MatrixLocation structure + */ +MatrixLocation *convertToMatrixLocation(const CellReference *ref) +{ + MatrixLocation *loc = malloc(sizeof(MatrixLocation)); + loc->row = ((int) toupper(ref->cellReference[0])) - ROW_TO_ASCII_OFFSET; + + char *col = calloc(sizeof(char) + strlen(ref->cellReference), sizeof(char)); + col = strncpy(col, ref->cellReference + 1, strlen(ref->cellReference) - 1); + loc->col = atoi(col) - 1; + free(col); + return loc; +} + +/** + * Checks if a given formula at row, col refers to some cells which themselves + * refer back to row,col + * + * Returns 0 if an error is encountered. + */ +int isCyclicRefError(const Worksheet *worksheet, int row, int col) +{ + MatrixLocation m = { row, col }; + + CellReference *cellRef = convertToCellReference(&m); + int result = isCyclicError(worksheet, "", cellRef); + + free(cellRef->cellReference); + free(cellRef); + return result; +} + +/** + * An internal function for checking cyclic reference dependency error. + * + * ========== + * Returns 1 if cyclic dependency is found, 0 if otherwise + */ +static int isCyclicError(const Worksheet *worksheet, const char *visitedCells, CellReference *cellRef) +{ + pcre2_match_data *match_data = NULL; + char *saveptr = NULL; + int rc = 0; + + MatrixLocation *m = convertToMatrixLocation(cellRef); + + char *cellValue = NULL; + getValue2(worksheet, &cellValue, m->row, m->col); + free(m); + + if (cellValue == NULL) + { + return 0; + } + + // do work on working copy + char *token = NULL; + token = strtok_r(cellValue, " ", &saveptr); + pcre2_code *re = getCellReferencePattern(); + while(token != NULL) + { + match_data = pcre2_match_data_create(20, NULL); + int subjectLength = strlen(token); + rc = pcre2_match(re, (PCRE2_SPTR) token, subjectLength, 0, 0, match_data, NULL); + + if (rc > 0) + { + // search if current cellref is in the visited cells + pcre2_code *searchVal = compilePattern(token); + int isCyclicDependency = pcre2_match(searchVal, (PCRE2_SPTR) visitedCells, strlen(visitedCells), 0, 0, match_data, NULL); + if (isCyclicDependency > 0) + { + free(cellValue); + free(match_data); + free(searchVal); + free(re); + return 1; + } + + free(searchVal); + + //length of existing visitedCells + space character + length of cellRef to be appended + null terminator + char *newVisitedCells = malloc(sizeof(char) * (strlen(visitedCells) + 1 + strlen(cellRef->cellReference)) + 1); + strcpy(newVisitedCells, visitedCells); + strcat(newVisitedCells, " "); + strcat(newVisitedCells, cellRef->cellReference); + + CellReference *tokenCellRef = malloc(sizeof(CellReference)); + tokenCellRef->cellReference = token; + + if(isCyclicError(worksheet, (const char *) newVisitedCells, tokenCellRef)) + { + free(cellValue); + free(newVisitedCells); + free(match_data); + free(re); + return 1; + } + + free(newVisitedCells); + free(tokenCellRef); + } + token = strtok_r(NULL, " ", &saveptr); + free(match_data); + } + + free(cellValue); + free(re); + return 0; +} + diff --git a/solutions/c/spreadsheet/matrix.h b/solutions/c/spreadsheet/matrix.h new file mode 100644 index 0000000..5ee4d72 --- /dev/null +++ b/solutions/c/spreadsheet/matrix.h @@ -0,0 +1,73 @@ + +typedef struct +{ + char ***cells; + int rows; + int cols; +} Worksheet; + +typedef struct +{ + int row; + int col; +} MatrixLocation; + +typedef struct +{ + char *cellReference; +} CellReference; + +// The maximum content of a cell (4k) +#define CELL_CONTENT_LIMIT 2048 + +#define ROW_TO_ASCII_OFFSET 65 + +/** + * Initializes the 2d matrix of size rows * columns. + * + * Returns 0 if an error is encountered. + */ +int initWorksheet(Worksheet *worksheet, int rows, int columns); + +/** + * Closes and releases the resources of the worksheet + */ +int closeWorksheet(Worksheet *w); + +/** + * Returns 1 if a cyclic dependency is detected. 0 if otherwise. + */ +int isCyclicRefError(const Worksheet *worksheet, int row, int col); + +/** + * Sets cellContent into the worksheet + */ +int setValue(Worksheet *worksheet, int row, int column, char *cellContent); + +/** + * Returns the value at row, col + */ +char* getValue(const Worksheet *worksheet, int row, int column); + +/** + * Returns the value at row, col and writes it into the buffer. + * + * Usage: + * + * char *buffer; + * getValue2(w, &buffer, row, column); + * + */ +int getValue2(const Worksheet *w, char **buffer, int row, int column); + +/** + * Returns a pointer to a CellReference structure + */ +CellReference *convertToCellReference(const MatrixLocation *matrixLocation); + +/** + * Returns a pointer to a MatrixLocation structure + */ +MatrixLocation *convertToMatrixLocation(const CellReference *cellReference); + + diff --git a/solutions/c/spreadsheet/matrixTest b/solutions/c/spreadsheet/matrixTest new file mode 100755 index 0000000..4d6f10b Binary files /dev/null and b/solutions/c/spreadsheet/matrixTest differ diff --git a/solutions/c/spreadsheet/regex.c b/solutions/c/spreadsheet/regex.c new file mode 100644 index 0000000..6fc1b2a --- /dev/null +++ b/solutions/c/spreadsheet/regex.c @@ -0,0 +1,29 @@ +#include "regex.h" + +pcre2_code * getCellReferencePattern(void) +{ + int errorcode = 0; + PCRE2_SIZE erroroffset; + pcre2_code *re = pcre2_compile((PCRE2_SPTR8) CELL_REFERENCE_PATTERN, -1, 0, + &errorcode, &erroroffset, NULL); + if (re == NULL) + { + return 0; + } + + return re; +} + +pcre2_code *compilePattern(char *pattern) +{ + int errorcode = 0; + PCRE2_SIZE erroroffset; + pcre2_code *re = pcre2_compile((PCRE2_SPTR8) pattern, -1, 0, + &errorcode, &erroroffset, NULL); + if (re == NULL) + { + return 0; + } + + return re; +} diff --git a/solutions/c/spreadsheet/regex.h b/solutions/c/spreadsheet/regex.h new file mode 100644 index 0000000..f3d8c7e --- /dev/null +++ b/solutions/c/spreadsheet/regex.h @@ -0,0 +1,17 @@ +#define PCRE2_CODE_UNIT_WIDTH 8 + +#include +#include +#include +#include + +static const char *CELL_REFERENCE_PATTERN = "[A-Za-z]\\d+"; + +pcre2_code *getCellReferencePattern(void); + +/** + * Creates a regular expression pattern based on {pattern} + */ +pcre2_code *compilePattern(char *pattern); + + diff --git a/solutions/c/spreadsheet/spreadsheet b/solutions/c/spreadsheet/spreadsheet new file mode 100755 index 0000000..df3da78 Binary files /dev/null and b/solutions/c/spreadsheet/spreadsheet differ diff --git a/solutions/c/spreadsheet/spreadsheet.c b/solutions/c/spreadsheet/spreadsheet.c new file mode 100644 index 0000000..8540238 --- /dev/null +++ b/solutions/c/spreadsheet/spreadsheet.c @@ -0,0 +1,211 @@ +#define _XOPEN_SOURCE 700 +#define PCRE2_CODE_UNIT_WIDTH 8 + +#include +#include +#include +#include +#include + +#include "regex.h" +#include "matrix.h" +#include "stackcalc.h" + +static void matrix_size(char *line, int *row, int *col); +static void matrix_readinput(Worksheet *w, char *file); +static void matrix_evaluate_worksheet(Worksheet *w); +static double matrix_evaluate_expression(const Worksheet *w, char *expression, int row, int col); +static int matrix_is_operator(char *val); + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + printf("Usage: spreadsheet \n"); + exit(1); + } + + Worksheet *w = malloc(sizeof(Worksheet)); + matrix_readinput(w, argv[1]); + matrix_evaluate_worksheet(w); + closeWorksheet(w); + +} + +static void matrix_readinput(Worksheet *w, char *file) +{ + FILE *fp = fopen(file, "r"); + if (fp == NULL) + { + fprintf(stderr, "Cant open input file\n"); + exit(1); + } + + int colCounter = -1, rowCounter = 0; + char *line = NULL; + size_t read = 0, len = 0; + while((read = getline(&line, &len, fp)) != -1) + { + if(colCounter == -1) + { + int r = 0, c = 0; + + // reads the matrix size from the + // first line of the input file + matrix_size(line, &r, &c); + + // initilizes the matrix of size r * c + initWorksheet(w, r, c); + } + else + { + setValue(w, rowCounter, colCounter, line); + if (isCyclicRefError(w, rowCounter, colCounter)) + { + printf("Cycling dependency starting at row: %d, col: %d\n", rowCounter, colCounter); + exit(1); + } + } + + colCounter++; + + if (colCounter > 0 && (colCounter % w->cols) == 0) + { + colCounter = 0; + rowCounter++; + } + } + + free(line); + fclose(fp); +} + +/** + * Reads the matrix size given in the line and stores it in the + * row and col parameters + */ +static void matrix_size(char *line, int *row, int *col) +{ + char *token = strtok(line, " "); + *col = atoi(token); + + token = strtok(NULL, " "); + *row = atoi(token); +} + +static void matrix_evaluate_worksheet(Worksheet *w) +{ + for(int i = 0; i < w->rows; i++) + { + for(int j = 0; j< w->cols; j++) + { + char *expression = NULL; + getValue2(w, &expression, i, j); + double d = matrix_evaluate_expression(w, expression, i, j); + printf("Row: %d; Col: %d; Value: %.5f\n", i, j, d); + free(expression); + } + } +} + +static double matrix_evaluate_expression(const Worksheet *w, char *expression, int row, int col) +{ + if (expression == NULL) return 0; + + pcre2_code *re = getCellReferencePattern(); + Stack *stack = malloc(sizeof(Stack)); + pcre2_match_data *match_data = NULL; + int rc = 0; + + char *saveptr = NULL; + char *token = NULL; + + expression[strlen(expression) - 1] = '\0'; + token = strtok_r(expression, " ", &saveptr); + + while(token != NULL) + { + int len = strlen(token); + match_data = pcre2_match_data_create(20, NULL); + rc = pcre2_match(re, (PCRE2_SPTR) token, len, 0, 0, match_data, NULL); + + if (rc > 0) + { + CellReference *cellRef = malloc(sizeof(CellReference)); + cellRef->cellReference = malloc((sizeof(char) * strlen(token)) + 1); + strcpy(cellRef->cellReference, token); + + MatrixLocation *loc = convertToMatrixLocation(cellRef); + char *cellExpression = NULL; + getValue2(w, &cellExpression, loc->row, loc->col); + + double result = matrix_evaluate_expression(w, cellExpression, loc->row, loc->col); + + Node *node = malloc(sizeof(Node)); + node->value = result; + push(stack, node); + + free(cellExpression); + free(cellRef->cellReference); + free(cellRef); + free(loc); + } + else + { + if (matrix_is_operator(token)) + { + Node *op1 = pop(stack); + Node *op2 = pop(stack); + + double val1 = op1->value; + double val2 = op2->value; + + double result = 0.0; + + if (strcmp(token, "+") == 0) result = val1 + val2; + if (strcmp(token, "-") == 0) result = val2 - val1; + if (strcmp(token, "*") == 0) result = val1 * val2; + if (strcmp(token, "/") == 0) result = val2 / val1; + + free(op1); + free(op2); + + Node *newValue = malloc(sizeof(Node)); + newValue->value = result; + push(stack, newValue); + } + else + { + Node *newValue = malloc(sizeof(Node)); + newValue->value = atoi(token); + push(stack, newValue); + } + } + + token = strtok_r(NULL, " ", &saveptr); + free(match_data); + } + + Node *node = pop(stack); + double retVal = node->value; + + free(stack); + free(node); + free(re); + return retVal; +} + +static int matrix_is_operator(char *val) +{ + if (strcmp(val, "+") == 0 || + strcmp(val, "-") == 0 || + strcmp(val, "*") == 0 || + strcmp(val, "/") == 0) + { + return 1; + } + + return 0; +} + diff --git a/solutions/c/spreadsheet/stackcalc.c b/solutions/c/spreadsheet/stackcalc.c new file mode 100644 index 0000000..6d54ac9 --- /dev/null +++ b/solutions/c/spreadsheet/stackcalc.c @@ -0,0 +1,27 @@ +#define PCRE2_CODE_UNIT_WIDTH 8 + +#include +#include + +#include "matrix.h" +#include "stackcalc.h" + +void push(Stack *stack, Node *node) +{ + // create new nodelist head + node->next = stack->nodeList; + stack->nodeList = node; + stack->len++; +} + +Node *pop(Stack *stack) +{ + Node *nodeList = stack->nodeList; + Node *newHead = nodeList->next; + + // remove reference to the next + nodeList->next = NULL; + stack->nodeList = newHead; + + return nodeList; +} diff --git a/solutions/c/spreadsheet/stackcalc.h b/solutions/c/spreadsheet/stackcalc.h new file mode 100644 index 0000000..b1ec9c2 --- /dev/null +++ b/solutions/c/spreadsheet/stackcalc.h @@ -0,0 +1,22 @@ + +typedef struct Node +{ + double value; + struct Node *next; +} Node; + +typedef struct +{ + Node *nodeList; + int len; +} Stack; + +/** + * Pushes node into the stack + */ +void push(Stack *stack, Node *node); + +/** + * Pops a node from the stack. Returns NULL if stack is empty + */ +Node *pop(Stack *stack); diff --git a/solutions/c/spreadsheet/tests/Makefile b/solutions/c/spreadsheet/tests/Makefile new file mode 100644 index 0000000..41c3e39 --- /dev/null +++ b/solutions/c/spreadsheet/tests/Makefile @@ -0,0 +1,6 @@ +all: tests + +tests: matrix_test.c ../regex.c ../commons.c ../regex.h ../matrix.h ../stackcalc.h + clang -o matrixTest -ggdb3 -Wall -Werror -O0 -std=c99 -I/usr/local/include matrix_test.c ../matrix.c ../regex.c ../commons.c ../stackcalc.c -L/usr/local/lib/ -lpcre2-8 -lcmocka + + diff --git a/solutions/c/spreadsheet/tests/core b/solutions/c/spreadsheet/tests/core new file mode 100644 index 0000000..07f2ecf Binary files /dev/null and b/solutions/c/spreadsheet/tests/core differ diff --git a/solutions/c/spreadsheet/tests/matrixTest b/solutions/c/spreadsheet/tests/matrixTest new file mode 100755 index 0000000..151851f Binary files /dev/null and b/solutions/c/spreadsheet/tests/matrixTest differ diff --git a/solutions/c/spreadsheet/tests/matrix_test.c b/solutions/c/spreadsheet/tests/matrix_test.c new file mode 100644 index 0000000..202a429 --- /dev/null +++ b/solutions/c/spreadsheet/tests/matrix_test.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#include + +#include "../matrix.h" +#include "../regex.h" +#include "../commons.h" +#include "../stackcalc.h" + +static void testConvertToCellReference(void **state) +{ + MatrixLocation m; + m.row = 0; + m.col = 0; + + CellReference *ref = convertToCellReference(&m); + assert_string_equal("A1", ref->cellReference); + + free(ref); + + m.row = 1; + m.col = 2; + + ref = convertToCellReference(&m); + assert_string_equal("B3", ref->cellReference); + + free(ref); +} + +static void testConvertToMatrixLocation(void **state) +{ + CellReference c; + c.cellReference = "A1"; + + MatrixLocation *m = convertToMatrixLocation(&c); + + assert_int_equal(0, m->row); + assert_int_equal(0, m->col); + + free(m); + + c.cellReference = "B5"; + m = convertToMatrixLocation(&c); + assert_int_equal(1, m->row); + assert_int_equal(4, m->col); + + free(m); +} + +static void testSetAndGetWorkSheetValue(void **state) +{ + Worksheet *w = malloc(sizeof(Worksheet)); + initWorksheet(w, 4, 4); + setValue(w, 0, 0, "A2 + 1"); + assert_string_equal("A2 + 1", getValue(w, 0, 0)); + free(w); +} + +static void testCyclicDependency(void **state) +{ + Worksheet *w = malloc(sizeof(Worksheet)); + initWorksheet(w, 4, 4); + + setValue(w, 0, 0, "A2 + 1"); + assert_string_equal("A2 + 1", getValue(w, 0, 0)); + assert_int_equal(0, isCyclicRefError(w, 0, 0)); + + setValue(w, 0, 1, "A1"); + assert_string_equal("A1", getValue(w, 0, 1)); + assert_int_equal(1, isCyclicRefError(w, 0, 1)); +} + +static void testStack(void **state) +{ + Stack *stack = malloc(sizeof(Stack)); + stack->len = 0; + + Node *node = malloc(sizeof(Node)); + node->value = 10.0; + push(stack, node); + + Node *node2 = malloc(sizeof(Node)); + node2->value = 12.0; + push(stack, node2); + + Node *poppedNode1 = pop(stack); + assert_true(12.0 == poppedNode1->value); + + Node *poppedNode2 = pop(stack); + assert_true(10.0 == poppedNode2->value); + + free(node); + free(node2); + free(stack); +} + +int main(int argc, char *argv[]) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(testConvertToCellReference), + cmocka_unit_test(testConvertToMatrixLocation), + cmocka_unit_test(testSetAndGetWorkSheetValue), + cmocka_unit_test(testCyclicDependency), + cmocka_unit_test(testStack), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +}