diff --git a/Makefile b/Makefile index fd121255a898ed10a3967a73f15926f04306a162..994f1406de3a4a14b66b5b32fe7f7af01c24cd23 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ all: loesung -WARNINGS = -Wall -Werror +WARNINGS = -Wall #-Werror OPTIONAL = -Wextra -Wpedantic -Wshadow -DEBUG = -ggdb -fno-omit-frame-pointer -OPTIMIZE = -O3 -std=c11 +DEBUG = -g -ggdb -fno-omit-frame-pointer +OPTIMIZE = -O2 -std=c11 loesung: Makefile loesung.c $(CC) -o $@ $(WARNINGS) $(OPTIONAL) $(DEBUG) $(OPTIMIZE) loesung.c diff --git a/loesung.c b/loesung.c index e9ee5c3ccc1fbd13bec6f18b795d2e1016fda94c..22e52f53f8574889fb509c8d051eccbaf54662aa 100644 --- a/loesung.c +++ b/loesung.c @@ -7,24 +7,26 @@ typedef struct Tile { uint32_t x; uint32_t y; - struct Tile *p_next; - struct Tile *p_prev; + struct Tile *p_n; // north, used for initial list + struct Tile *p_e; // east + struct Tile *p_s; // south + struct Tile *p_w; // west } Tile; int tile_compare(const void *p, const void *q) { const Tile *s = *(const Tile**) p; const Tile *t = *(const Tile**) q; - // als erstes nach x sortieren - if (s->x < t->x) - return -1; - if (s->x > t->x) - return 1; - // danach nach y sortieren + // als erstes nach y sortieren if (s->y < t->y) return -1; if (s->y > t->y) return 1; + // danach nach x sortieren + if (s->x < t->x) + return -1; + if (s->x > t->x) + return 1; return 0; // Elemente sind gleich } @@ -54,24 +56,24 @@ Tile* list_push(List *s) { } p_tile->x = 0; p_tile->y = 0; - p_tile->p_next = s->p_top; - p_tile->p_prev = NULL; + p_tile->p_n = s->p_top; + p_tile->p_e = NULL; + p_tile->p_s = NULL; + p_tile->p_w = NULL; + s->p_top = p_tile; s->size++; - if(p_tile->p_next != NULL) { - p_tile->p_next->p_prev = p_tile; - } return p_tile; } /** Entfernen des obersten Elementes von der Liste und zurueckgeben des Tiles * - * Der List muss mindestens ein Element besitzen TODO: Notwendig? + * Der List muss mindestens ein Element besitzen */ Tile* list_pop(List *s) { Tile *p_tile = s->p_top; - s->p_top->p_next = p_tile->p_next; - s->p_top->p_prev = NULL; + s->p_top = s->p_top->p_n; + s->size--; return p_tile; } @@ -83,7 +85,7 @@ void list_free(List *s) { Tile *p_cur = s->p_top; s->p_top = NULL; while (p_cur != NULL) { - Tile *p_next = p_cur->p_next; + Tile *p_next = p_cur->p_n; free(p_cur); p_cur = p_next; } @@ -104,7 +106,9 @@ typedef struct Field { Tile t_max; List tile_list; Tile* (*tile_array); -} Field; + uint32_t num_tiles; +} Field; // TODO: entfernen dieses Structs und nutzen von kleineren Strukturen: + // list + tile_array /** Parsen einer Kachel(Tile) aus einer Zeile von StdIn * @@ -178,6 +182,7 @@ void field_init(Field *f) { // initialisieren der Liste list_init(&f->tile_list); f->tile_array = 0; + f->num_tiles = 0; } /** Freigeben des im Heap reservierten speichers des fields f */ @@ -252,14 +257,58 @@ MallocResult field_init_tile_array(Field *f) { return MallocFailed; } Tile *cur = f->tile_list.p_top; + f->num_tiles = f->tile_list.size; for (uint32_t i = 0; i < f->tile_list.size; i++) { f->tile_array[i] = cur; - cur = cur->p_next; + cur = cur->p_n; + f->tile_array[i]->p_n = NULL; } return MallocOk; } +/** Gruppieren der Felder, setzen der Pointer (north, east, south, west) vom Feld + * + * Voraussetzung: `field_init_tile_array()` muss ausgefuehrt worden sein + * Rueckgabe: 0 falls alles ok + * 1 falls Dopplungen vorkommen TODO: enum + */ +int field_find_neighbours(Field *f) { + uint32_t i = 0; // vergleich mit oberer Zeile + uint32_t begin_line = 0; + for (uint32_t j = 1; j < f->num_tiles; j++) { + Tile *p_cur = f->tile_array[j]; + Tile *p_east = f->tile_array[j-1]; + // ermitteln der ost/west-Beziehung + if (p_cur->y == p_east->y) { + if (p_cur->x == p_east->x) { + return 1; + } + if (p_cur->x == p_east->x - 1) { + p_cur->p_e = p_east; + p_east->p_w = p_cur; + } + } else { + begin_line = i; + } + // ermitteln der nord/sued-Beziehung + Tile *p_north = f->tile_array[i]; + if (p_north->y < p_cur->y - 1) { + i = begin_line; // Luecke zwischen zeilen + } else if (p_north->y == p_cur->y - 1) { + // finden, ob paar existiert, zurzeit O(n). + // TODO: lohnt sich binaere suche mit O(log n)? + for(;f->tile_array[i]->y < p_cur->y && i < begin_line; i++); + p_north = f->tile_array[i]; + if (p_north->x == p_cur->x) { + p_north->p_s = p_cur; + p_cur->p_n = p_north; + } + } + } + return 0; +} + void field_print(Field *f) { printf("# Array\n"); for (uint32_t i = 0; i < f->tile_list.size; i++) { @@ -308,6 +357,16 @@ int main (void) } qsort(field.tile_array, field.tile_list.size, sizeof(Tile*), tile_compare); + if(field_find_neighbours(&field)) { + fprintf(stderr, "Error: Duplicated entry\n"); + return EXIT_FAILURE; + } + //field_print(&field); + + // TODO: Untertilesets finden + // TODO: Problem fuer die Untertilesets loesen + // TODO: Loesung ausgeben + field_drop(&field); return EXIT_SUCCESS; }