diff --git a/ex4/ex4.c b/ex4/ex4.c index 97016cc686ec4794f73e8854d71525288fc720f2..1d1275987fff5b445760768402d19f523da922b8 100644 --- a/ex4/ex4.c +++ b/ex4/ex4.c @@ -9,37 +9,264 @@ * */ +#include <assert.h> #include <math.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> + +// Matrix.h + +typedef struct Matrix { + int32_t m; + int32_t n; + int32_t **data; +} Matrix; + +Matrix *matrix_init(int32_t m, int32_t n); +void matrix_destroy(Matrix **matrix); +int32_t matrix_get(Matrix *matrix, int32_t y, int32_t x); +void matrix_set(Matrix *matrix, int32_t y, int32_t x, int32_t value); + +// Matrix.c + +Matrix *matrix_init(int32_t m, int32_t n) { + Matrix *matrix = (Matrix *)malloc(sizeof(Matrix)); + matrix->m = m; + matrix->n = n; + matrix->data = (int32_t **)malloc(sizeof(int32_t *) * m); + + for (int32_t i = 0; i < matrix->m; i += 1) { + matrix->data[i] = (int32_t *)calloc(n, sizeof(int32_t)); + } + + return matrix; +} + +void matrix_destroy(Matrix **matrix) { + for (int32_t i = 0; i < (*matrix)->m; i += 1) { + free((*matrix)->data[i]); + } + + free((*matrix)->data); + free(*matrix); + *matrix = NULL; +} + +int32_t matrix_get(Matrix *matrix, int32_t y, int32_t x) { + return matrix->data[y][x]; +} + +void matrix_set(Matrix *matrix, int32_t y, int32_t x, int32_t value) { + matrix->data[y][x] = value; +} + +void matrix_print(Matrix *matrix) { + for (int i = 0; i < matrix->m; i += 1) { + for (int j = 0; j < matrix->n; j += 1) { + printf("%2d ", matrix->data[i][j]); + } + + printf("\n"); + } +} + +// Quadtree.h + +#define CHILDREN_COUNT 4 + +typedef struct Node { + int data; + struct Node *children[CHILDREN_COUNT]; +} Node; + +int32_t _max(int32_t a, int32_t b); +Node *node_init(); +Node *quadtree_init(int32_t depth); +void quadtree_destroy(Node **root); +int32_t quadtree_depth(Node *root); +bool quadtree_is_leaf(Node *root); +Node *quadtree_search(Node *root, int32_t depth, int32_t y, int32_t x); +Node *matrix_to_quadtree(Matrix *matrix); +Matrix *quadtree_to_matrix(Node *root); + +// Quadtree.c + +int32_t _max(int32_t a, int32_t b) { + return a > b ? a : b; +} + +Node *node_init() { + Node *node = (Node *)malloc(sizeof(Node)); + node->data = 0; + + for (int32_t i = 0; i < CHILDREN_COUNT; i += 1) { + node->children[i] = NULL; + } + + return node; +} + +Node *quadtree_init(int32_t depth) { + Node *root = node_init(); + + if (depth == 0) { + return root; + } + + for (int32_t i = 0; i < CHILDREN_COUNT; i += 1) { + root->children[i] = quadtree_init(depth - 1); + } + + return root; +} + +void quadtree_destroy(Node **root) { + if (!quadtree_is_leaf(*root)) { + for (int32_t i = 0; i < CHILDREN_COUNT; i += 1) { + quadtree_destroy(&(*root)->children[i]); + } + } + + free(*root); + *root = NULL; +} + +int32_t quadtree_depth(Node *root) { + if (root == NULL) { + return -1; + } + + if (quadtree_is_leaf(root)) { + return 0; + } + + int32_t biggest_depth = 0; + + for (int32_t i = 0; i < CHILDREN_COUNT; i += 1) { + biggest_depth = _max(biggest_depth, quadtree_depth(root->children[i])); + } + + return biggest_depth + 1; +} + +bool quadtree_is_leaf(Node *root) { + return root->children[0] == NULL; +} + +Node *quadtree_search(Node *root, int32_t depth, int32_t y, int32_t x) { + for (int32_t d = depth - 1; d >= 0; d -= 1) { + if (quadtree_is_leaf(root)) { + return root; + } + + int32_t i = (y >> d) & 1; + int32_t j = (x >> d) & 1; + root = root->children[2 * i + j]; + } + + return root; +} + +Node *matrix_to_quadtree(Matrix *matrix) { + int32_t depth = (int32_t)log2(matrix->m); + Node *root = quadtree_init(depth); + + for (int32_t i = 0; i < matrix->m; i += 1) { + for (int32_t j = 0; j < matrix->n; j += 1) { + Node *node = quadtree_search(root, depth, i, j); + node->data = matrix_get(matrix, i, j); + } + } + + return root; +} + +Matrix *quadtree_to_matrix(Node *root) { + int32_t depth = quadtree_depth(root); + int32_t size = (int32_t)pow(2, depth); + Matrix *matrix = matrix_init(size, size); + + for (int32_t i = 0; i < matrix->m; i++) { + for (int32_t j = 0; j < matrix->n; j++) { + Node *node = quadtree_search(root, depth, i, j); + int32_t value = node->data; + matrix_set(matrix, i, j, value); + } + } + + return matrix; +} + +// --- + +Node *clone(Node *root) { + if (root == NULL) { + return NULL; + } + + Node *output = node_init(); + output->data = root->data; + + for (int i = 0; i < 4; i += 1) { + output->children[i] = clone(root->children[i]); + } + + return output; +} int main() { - // int32_t values_length = 5; - // double values[values_length]; - - // for (int32_t i = 0; i < values_length; i += 1) { - // double value; - // scanf("%lf", &value); - // values[i] = value; - // } - - // int32_t values_length = 5; - // int32_t values[values_length]; - - // for (int32_t i = 0; i < values_length; i += 1) { - // int32_t value; - // scanf("%d", &value); - // values[i] = value; - // } - - // char a[100]; - // int32_t b; - // scanf("%s %d", a, &b); - // printf("%s %d\n", a, b); - - printf("ex1\n"); + int n = 16; + int32_t input[16][16] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 3, 3, 3, 3, 0, 0, 7, 7, 7, 7, 0, 0, 11, 11, 11}, + {0, 3, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 11, 0, 0}, + {0, 3, 3, 3, 0, 0, 0, 7, 7, 7, 0, 0, 0, 11, 11, 11}, + {0, 3, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 11, 0, 0}, + {0, 3, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 11, 11, 11}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 3, 3, 3, 3, 0, 0, 7, 7, 7, 7, 0, 0, 11, 11, 11}, + {0, 3, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 11, 0, 0}, + {0, 3, 3, 3, 0, 0, 0, 7, 7, 7, 0, 0, 0, 11, 11, 11}, + {0, 3, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 11, 0, 0}, + {0, 3, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 11, 11, 11}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 3, 3, 3, 3, 0, 0, 7, 7, 7, 7, 0, 0, 11, 11, 11}, + }; + + Matrix *matrix_input = matrix_init(n, n); + + for (int i = 0; i < n; i += 1) { + for (int j = 0; j < n; j += 1) { + matrix_set(matrix_input, i, j, input[i][j]); + } + } + + Node *tree = matrix_to_quadtree(matrix_input); + Node *tree_cloned = clone(tree); + quadtree_destroy(&tree); + Matrix *matrix_output = quadtree_to_matrix(tree_cloned); + quadtree_destroy(&tree_cloned); + + // matrix_print(matrix_input); + matrix_print(matrix_output); + + // Assert that the two matrices are not the same in memory and that they have the same data. + assert(matrix_input != matrix_output); + assert(matrix_input->data != matrix_output->data); + for (int i = 0; i < matrix_input->m; i += 1) { + assert(matrix_input->data[i] != matrix_output->data[i]); + + for (int j = 0; j < matrix_input->n; j += 1) { + assert(matrix_input->data[i][j] == matrix_output->data[i][j]); + assert(matrix_input->data[i][j] == matrix_output->data[i][j]); + } + } + + matrix_destroy(&matrix_input); + matrix_destroy(&matrix_output); return EXIT_SUCCESS; }