From 6b5954d0e5f536971acc0e3a69b0f75d2c1f9d2b Mon Sep 17 00:00:00 2001
From: Manuel Bucher <manuel.bucher@hu-berlin.de>
Date: Fri, 22 Jun 2018 17:54:19 +0200
Subject: [PATCH] overwrite loesung with loesung2

---
 Makefile   |   6 +-
 loesung.c  | 599 +++++++++++++++++++++--------------------------------
 loesung2.c | 378 ---------------------------------
 3 files changed, 236 insertions(+), 747 deletions(-)
 mode change 100644 => 100755 loesung.c
 delete mode 100755 loesung2.c

diff --git a/Makefile b/Makefile
index ebb9bf3..742516b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
-all: loesung2
+all: loesung
 
 WARNINGS = -Wall #-Werror
 OPTIONAL = -Wextra -Wpedantic -Wshadow
 DEBUG = -g -ggdb -fno-omit-frame-pointer
 OPTIMIZE = -Og -std=c11
 
-loesung: Makefile loesung2.c
-	$(CC) -o $@ $(WARNINGS) $(OPTIONAL) $(DEBUG) $(OPTIMIZE) loesung2.c
+loesung: Makefile loesung.c
+	$(CC) -o $@ $(WARNINGS) $(OPTIONAL) $(DEBUG) $(OPTIMIZE) loesung.c
 clean:
 	rm -f loesung
 
diff --git a/loesung.c b/loesung.c
old mode 100644
new mode 100755
index 0f10c42..5b37b0b
--- a/loesung.c
+++ b/loesung.c
@@ -1,203 +1,91 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <stdint.h> // fixed sized integer
 #include <stdbool.h> // booleans
 
 #define INF UINT32_MAX
 
+/********** Kachel definition **********/
 typedef struct Tile {
     uint32_t x;
     uint32_t y;
-    struct Tile *p_matching; // matching partner
-    struct Tile *p_next; // used for list and queue
-    struct Tile *p_n; // north has to be first
-    struct Tile *p_e; // east
-    struct Tile *p_s; // south
-    struct Tile *p_w; // west
-    uint32_t dist;
+    uint32_t neigh[4]; // Nachbarn
+    struct Tile *p_next; // queue
+    uint32_t pair; // matching partner
+    uint32_t dist; // entfernung zu Knoten 0 im Schichtgraph
 } Tile;
 
-
-// Reservieren und initialisieren des Speicherplatz eines Tiles
-void tile_init(Tile* this) {
-    this->x = 0;
-    this->y = 0;
-    this->p_matching = NULL;
-    this->p_next = NULL;
-    this->p_n = NULL;
-    this->p_e = NULL;
-    this->p_s = NULL;
-    this->p_w = NULL;
+// initialisieren des Speichers von einem Tile
+void tile_init(Tile *this) {
+    memset(this, 0, sizeof(Tile));
     this->dist = INF;
 }
 
 int tile_compare(const void *p, const void *q) {
-    const Tile *s = *(const Tile**) p;
-    const Tile *t = *(const Tile**) q;
-    // 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;
+    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
+    if (s->y < t->y) return -1;
+    if (s->y > t->y) return 1;
     return 0; // Elemente sind gleich
 }
 
-inline bool tile_is_odd(Tile* this) {
-    return ((this->x ^ this->y)&1) != 0;
+// Kacheln wie im Schachbrettmuster einordnen
+uint32_t tile_odd(Tile* this) {
+    return ((this->x ^ this->y)&1);
 }
 
-/*************** List von Tiles *********************/
-/** List von Tiles */
-typedef struct List {
-    Tile *p_top;
+/********** Kachelfeld **********/
+typedef struct Field {
+    // Array von Tiles, tile 0 is imagenary tile for hk-algorithmus
+    // Tiles werden mit 1 bis num_tiles exklusive indiziert
+    Tile *tiles;
     uint32_t num_tiles;
-    uint32_t num_odd; // #ungerade Felder (`x - y` ist ungerade)
-    Tile max;
-    Tile min;
-} List;
-
-/** Initialisieren einer leeren Liste */
-void list_init(List *this) {
-    this->p_top = NULL;
-    this->num_tiles = 0;
-    this->num_odd = 0;
-    this->min.x = UINT32_MAX;
-    this->min.y = UINT32_MAX;
-    this->max.x = 0;
-    this->max.y = 0;
-}
-
-/** Min-Max funktionen fuer uint32_t */
-inline uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; }
-inline uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; }
-
-/** Hinzufuegen von einem Tile zur Liste
- *
- * Voraussetzung: Die Liste muss initialisiert sein.
- * Rueckgabe: Hinzugefuegtes, initialisiertes Tile
- */
-void list_push(List *this, Tile *p_tile) {
-    p_tile->p_next = this->p_top;
-    this->p_top = p_tile;
-    // Reichweite der Liste ermitteln
-    this->min.x = min(this->min.x, p_tile->x);
-    this->min.y = min(this->min.y, p_tile->y);
-    this->max.x = max(this->max.x, p_tile->x);
-    this->max.y = max(this->max.y, p_tile->y);
-    this->num_tiles++;
-    this->num_odd += tile_is_odd(p_tile);
+    uint32_t size;
+    uint32_t num_odd;
+} Field;
+
+// returns 0 if successful, nonzero if failed
+int field_init(Field *this) {
+    memset(this, 0, sizeof(Field));
+    this->tiles = malloc(sizeof(Tile));
+    this->num_tiles = 1;
+    this->size = 1;
+    return this->tiles == 0;
 }
 
-/** Freigeben des reservierten Speichers von der Liste
- *
- * Alle Tiles mit free vom Speicher freigeben
- */
-void list_free(List *this) {
-    Tile *p_cur = this->p_top;
-    this->p_top = NULL;
-    while (p_cur != NULL) {
-        Tile *p_next = p_cur->p_next;
-        free(p_cur);
-        p_cur = p_next;
-    }
-}
-
-/** pruefen, ob genausoviele gerade und ungerade Kacheln existieren,
- * ohne einen Overflow zu erzeugen
- * notwendiges Kriterium
- */
-bool list_necessity(List *this) {
-    return this->num_tiles - this->num_odd == this->num_odd;
-}
-
-/** Zurueckgeben, ob graph ein vollstaendiges Rechteck ist */
-bool list_rectangle(List *this) {
-    // verwenden von `uint64_t` um einen ueberlauf zu vermeiden
-    return (uint64_t)(this->max.x - this->min.x+1) * (uint64_t)(this->max.y - this->min.y+1)
-            == (uint64_t)this->num_tiles;
-}
-
-/** Ausgeben der Liste als Rechteck
- *
- * Voraussetzung: notwendiges Kriterium erfuellt & es handelt sich um ein Rechteck
- */
-void list_print_rectangle(List *this) {
-    for (uint32_t x = this->min.x;; x++) {
-        for (uint32_t y = this->min.y;; y+=2) {
-            if (y == this->max.y) {
-                if ((x - this->min.x) % 2 == 0) {
-                    // vertikaler Stein
-                    printf("%u %u;%u %u\n", x, y, x+1, y);
-                }
-                break;
-            }
-            printf("%u %u;%u %u\n", x, y, x, y+1);
-            if (y == this->max.y-1) {
-                break; // ende des Zeile erreicht
-            }
-        }
-        if(x == this->max.x) {
-            break;
-        }
+// if an error occurs, all memory get freed
+int field_push(Field *this, Tile *p_tile) {
+    if (this->size == this->num_tiles) {
+        if (this->size == 1u<<31) return 1; // catch overflow
+        this->size *= 2; // Armortisiert O(1)
+        Tile *new = realloc(this->tiles, this->size*sizeof(Tile));
+        if (new == NULL) return 1; // catch failed realloc
+        this->tiles = new;
     }
-}
-
-/** Schlange von Tiles */
-typedef struct Queue {
-    Tile *p_first;
-    Tile *p_last;
-} Queue;
-
-void queue_init(Queue* this) {
-    this->p_first = NULL;
-    this->p_last = NULL;
-}
-
-void queue_push(Queue* this, Tile* p_tile) {
-    if (this->p_last != NULL) {
-        this->p_last->p_next = p_tile;
-    } else {
-        this->p_first = p_tile;
-    }
-    this->p_last = p_tile;
-    p_tile->p_next = NULL;
-}
-
-inline Tile *queue_first(Queue* this) {
-    return this->p_first;
-}
-
-inline bool queue_empty(Queue* this) {
-    return this->p_first == NULL;
-}
-
-Tile *queue_pop(Queue* this) {
-    Tile *p_tile = this->p_first;
-    this->p_first = p_tile->p_next;
-    if (this->p_first == NULL) {
-        this->p_last = NULL;
-    }
-    return p_tile;
+    this->num_odd += tile_odd(p_tile);
+    memcpy(this->tiles+this->num_tiles, p_tile, sizeof(Tile));
+    this->num_tiles++;
+    return 0;
 }
 
 /** Parsen einer Kachel(Tile) aus einer Zeile von StdIn
  *
- * Die Zahlen weReaden in das uebergebene Struct pTile geschrieben, sind aber
- * nur gueltig, wenn der Rueckgabewert `Ok` ist.
+ * Die Werte werden in die uebergebene Kachel geschrieben, sind aber
+ * nur gueltig, wenn der Rueckgabewert `ReadOk` ist.
  *
  * Voraussetzung: p_tile muss initialisiert sein
  */
 typedef enum ReadResult {
     ReadOk,
     ReadEof,
-    ReadErrIntegerOverflow,
-    ReadErrNonDigitCharacter,
+    ReadErrOverflow,
+    ReadErrInvalidChar,
     ReadErrTooFewNumbers,
     ReadErrTooManyNumbers,
     ReadErrOutOfMemory,
@@ -223,18 +111,16 @@ ReadResult read_line(Tile* p_tile){
             // 429496730 = 2^32 / 10, daher wenn `p_cur` groesser ist, wird ein
             // overflow erzeugt
             if (*p_cur > 429496729) {
-                return ReadErrIntegerOverflow;
+                return ReadErrOverflow;
             }
             (*p_cur) *= 10;
             int digit = c - '0';
             if (*p_cur > UINT32_MAX - digit) {
-                return ReadErrIntegerOverflow;
+                return ReadErrOverflow;
             }
             (*p_cur) += digit;
         } else if (c == ' ') {
-            if (cur_whitespace == false) {
-                cur_whitespace = true;
-            }
+            cur_whitespace = true;
         } else if (c == '\n') {
             if (cur_number == 2) {
                 return ReadOk;
@@ -242,11 +128,10 @@ ReadResult read_line(Tile* p_tile){
                 return ReadErrTooFewNumbers;
             }
         } else {
-            return ReadErrNonDigitCharacter;
+            return ReadErrInvalidChar;
         }
         c = getchar(); // get next character
     }
-    return ReadOk;
 }
 
 /** Liest das Input von StdIn und schreibt das Ergebnis in die uebergebene Liste
@@ -254,33 +139,26 @@ ReadResult read_line(Tile* p_tile){
  * Laufzeit: O(n)
  * Speicherbedarf: O(n)
  *
- * Parameter:
- *  - List* f ist ein Pointer auf eine initialisierte List, wird mit Eingabe
- *    gefuellt, im Fehlerfall ist die groesse `num_tiles` die Zeile, in welche
- *    der Fehler aufgetreten ist
- *
  * Return:
  *  - ReadResult:
  *     ReadOk, falls das lesen Erfolgreich war
- *     ReadErr..., falls die Eingabe ungueltig ist. `f` ist dann nicht vollstaendig
- *               initialisiert
+ *     ReadErr..., falls die Eingabe ungueltig ist oder zu wenig Speicher vorhanden.
+ *             `num_tiles` indiziert die Zeile, in der der Fehler aufgetreten ist
  */
-ReadResult parse_input(List *this) {
+ReadResult field_parse(Field *this) {
     while (1) {
-        Tile *p_tile = malloc(sizeof(Tile));
-        if (p_tile == NULL) {
-            return ReadErrOutOfMemory;
-        }
-        tile_init(p_tile);
-        ReadResult result = read_line(p_tile);
+        Tile next;
+        tile_init(&next);
+        ReadResult result = read_line(&next);
         switch (result) {
         case ReadOk:
             // einfuegen in die Liste
-            list_push(this, p_tile);
+            if (field_push(this, &next)) {
+                return ReadErrOutOfMemory;
+            }
             break;
         case ReadEof:
-            free(p_tile);
-            if (this->num_tiles == 0) {
+            if (this->num_tiles == 1) {
                 return ReadEof;
             } else {
                 return ReadOk;
@@ -291,221 +169,210 @@ ReadResult parse_input(List *this) {
     }
 }
 
-/** Array in heap for accessing tiles in O(1)
- */
-typedef struct Array {
-    uint32_t num_tiles;
-    Tile null;
-    Tile* (*tiles);
-} Array;
-
-/** Freigeben des im Heap reservierten Speichers des tile_arrays f
- * inklusive der Tiles */
-void array_drop(Array *this) {
-    if(this->tiles != NULL) {
-        for(uint32_t i = 1; i < this->num_tiles; i++) {
-            free(this->tiles[i]);
-        }
-        free(this->tiles);
-    }
-}
-
-typedef enum MallocResult {
-    MallocFailed,
-    MallocOk,
-} MallocResult;
-/** Initialisieren des Tile-Arrays
- *
- * Laufzeit: O(n)
- */
-MallocResult array_from_list(Array *this, List* p_list) {
-    this->num_tiles = p_list->num_tiles+1;
-    this->tiles = malloc(this->num_tiles * sizeof(Tile*));
-    if(this->tiles == NULL) {
-        return MallocFailed;
-    }
-    tile_init(&this->null); // create null tile for hk
-    this->tiles[0] = &this->null;
-    Tile *cur = p_list->p_top;
-    for (uint32_t i = 1; i < this->num_tiles; i++) {
-        this->tiles[i] = cur;
-        cur = cur->p_next;
-        this->tiles[i]->p_next = NULL;
-    }
-    return MallocOk;
-}
-
-/** Gruppieren der Felder, setzen der Pointer (north, east, south, west) vom Feld
- *
- * Voraussetzung: `field_init_tile_array()` muss ausgefuehrt worden sein
+/** Setzen der Nachbarn der Kacheln
  * Rueckgabe: 0 falls alles ok
- *            1 falls Dopplungen vorkommen TODO: enum
+ *            1 falls Dopplungen vorkommen
  */
-int array_find_neighbours(Array *this) {
-    uint32_t i = 1; // vergleich mit oberer Zeile
-    uint32_t begin_line = 1;
-    for (uint32_t j = 2; j < this->num_tiles; j++) {
-        Tile *p_cur = this->tiles[j];
-        Tile *p_east = this->tiles[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;
+int field_neighbours(Field *this) {
+    uint32_t top = 1; // vergleich mit oberer Zeile
+    uint32_t begin_line = 1; // start der aktuellen Zeile
+    Tile *t = this->tiles;
+    for (uint32_t cur = 2; cur < this->num_tiles; cur++) {
+        // ermitteln der x-Beziehung
+        uint32_t east = cur-1;
+        if (t[cur].x == t[east].x) { // gleiche Zeile
+            if (t[cur].y == t[east].y) { // gleiche Spalte
+                return 1; // Doppelung
+            } else if (t[cur].y-1 == t[east].y) {
+                t[cur].neigh[1] = east;
+                t[east].neigh[3] = cur;
             }
         } else {
-            begin_line = i;
+            top = begin_line;
+            begin_line = cur; // neue Zeile
         }
-        // ermitteln der nord/sued-Beziehung
-        Tile *p_north = this->tiles[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).
-            for(;this->tiles[i]->y < p_cur->y && i < begin_line; i++);
-            p_north = this->tiles[i];
-            if (p_north->x == p_cur->x) {
-                p_north->p_s = p_cur;
-                p_cur->p_n = p_north;
+        // ermitteln der Zeilen-Beziehung
+        if (t[begin_line].x != 0 && t[top].x < t[begin_line].x - 1) {
+            // Zeilensprung => Warten bis zur naechsten Zeile angekommen
+        } else if (t[top].x == t[cur].x - 1) {
+            // finden, ob paar nach oben existiert O(n) fuer alle Nachbarn nach oben/unten.
+            for(;t[top].y < t[cur].y && top < begin_line; top++);
+
+            // aktuelle obere Kachel koennte benachbart sein
+            if (t[top].y == t[cur].y) { // nicht auf naechste Zeile uebergegangen
+                // Neue Verbindung oben/unten gefunden
+                t[top].neigh[2] = cur;
+                t[cur].neigh[0] = top;
             }
         }
     }
     return 0;
 }
 
-void array_print(Array *this) {
-    printf("# Array\n");
-    for (uint32_t i = 0; i < this->num_tiles; i++) {
-        printf("%u %u\n", this->tiles[i]->x, this->tiles[i]->y);
+void field_print(Field *this) {
+    printf("[\n");
+    Tile *t = this->tiles;
+    for (uint32_t i = 1; i < this->num_tiles; i++){
+        printf("\t(%u %u): {", t[i].x, this->tiles[i].y);
+        for (int j = 0; j < 4; j++) {
+            if(t[i].neigh[j] != 0) {
+                Tile *neigh = &t[t[i].neigh[j]];
+                printf(" (%u %u)", neigh->x, neigh->y);
+            }
+        }
+        printf(" }\n");
+    }
+    printf("]\n");
+}
+
+/********** Schlange von Tiles **********/
+typedef struct Queue {
+    Tile *p_first;
+    Tile *p_last;
+} Queue;
+
+void queue_init(Queue* this) {
+    this->p_first = NULL;
+    this->p_last = NULL;
+}
+
+void queue_push(Queue* this, Tile* p_tile) {
+    if (this->p_last != NULL) {
+        this->p_last->p_next = p_tile;
+    } else {
+        this->p_first = p_tile;
     }
+    this->p_last = p_tile;
+    p_tile->p_next = NULL;
 }
 
-/* algorithmus von Hopcroft und Karp */
-bool hk_bfs(Array *this) {
-    Queue q;
-    queue_init(&q); // queue von odd Tiles
+bool queue_empty(Queue* this) {
+    return this->p_first == NULL;
+}
 
-    for (int i = 0; i < this->num_tiles; i++) {
-        Tile *p_cur = this->tiles[i];
-        if (tile_is_odd(p_cur)) {
+Tile *queue_pop(Queue* this) {
+    Tile *p_tile = this->p_first;
+    this->p_first = p_tile->p_next;
+    if (this->p_first == NULL) {
+        this->p_last = NULL;
+    }
+    return p_tile;
+}
+
+/********** Algorithmus von Hopcroft und Karp **********/
+bool hk_bfs(Field *this) {
+    Queue q; // Schlange von Kacheln
+    queue_init(&q);
+    Tile *t = this->tiles;
+    for (int i = 1; i < this->num_tiles; i++) {
+        // nur gerade Kacheln werden zur queue hinzufuegen
+        if (tile_odd(&t[i])) {
             continue;
         }
-        if (p_cur->p_matching == NULL) {
-            // Freier Knoten -> Zur Schlange hinzufuegen
-            p_cur->dist = 0; // Erste Spalte im Schichtgraphen
-            queue_push(&q, p_cur);
+        if (t[i].pair == 0) {
+            t[i].dist = 0;
+            queue_push(&q, &t[i]);
         } else {
-            p_cur->dist = INF; // Spaetere Spalte im Schichtgraphen (alle Kanten?)
+            t[i].dist = INF;
         }
     }
-    this->null.dist = INF;
+    t[0].dist = INF;
     while (!queue_empty(&q)) {
-        Tile *p_cur = queue_pop(&q);
-        if (p_cur->dist < INF) {
-            for (int i = 0; i < 4; i++) {
-                Tile *p_neigh = p_cur->p_n+i;
-                if (p_neigh == NULL)
-                    continue;
-                // Kante noch nicht im Schichtgraphen?
-                if(p_neigh->dist == INF) {
-                    Tile *matching = p_neigh->p_matching;
-                    if (matching == NULL) {
-                        return true; // Es gibt einen augmentierenden Pfad
-                    }
-                    matching->dist = p_cur->dist + 1;
-                    queue_push(&q, matching);
-                }
+        Tile *e = queue_pop(&q); // nehme naechste gerade Kachel
+        if (e->dist >= t[0].dist)
+            continue;
+        for (int i = 0; i < 4; i++) {
+            Tile* p_neigh = &t[e->neigh[i]];
+            Tile* p_pair = &t[p_neigh->pair];
+            if(p_pair->dist == INF) {
+                p_pair->dist = e->dist+1;
+                queue_push(&q, p_pair);
             }
         }
     }
-    return false;
+    return t[0].dist != INF;
 }
 
-bool hk_dfs(Tile *this) {
-    if (this == NULL)
+bool hk_dfs(Field *this, uint32_t e) {
+    if (e == 0)
         return true;
-
+    Tile *t = this->tiles;
+    Tile *p_even = &t[e];
     for (int i = 0; i < 4; i++) {
-        Tile *p_neigh = this->p_n+i; // Benachbart zu odd
+        // Benachbart zu e
+        uint32_t o = p_even->neigh[i]; // Nachbar, ungerade Kachel
+        Tile* p_odd = &t[o];
+        if (t[p_odd->pair].dist == p_even->dist+1) {
+            // Augmentiere den Pfad, falls durch Tiefensuche gefunden
+            if (hk_dfs(this, p_odd->pair)) {
+                p_even->pair = o;
+                p_odd->pair = e;
+                return true;
+            }
+        }
     }
+    // Kein augmentierender Pfad von e aus
+    p_even->dist = INF;
     return false;
 }
 
-int main (void)
-{
-    // erstellen des Liste zum parsen des inputs
-    List tile_list;
-    list_init(&tile_list); // Liste ist owner von Tiles
-    ReadResult result = parse_input(&tile_list); // lesen des Inputs
-    switch (result) {
-    case ReadOk:
-        break;
-    case ReadEof:
-        // bei leerer Eingabe nichts ausgeben
-        return EXIT_SUCCESS;
-    case ReadErrIntegerOverflow:
-        fprintf(stderr, "Error in line %d: too big integer\n", tile_list.num_tiles);
-        list_free(&tile_list);
-        return EXIT_FAILURE;
-    case ReadErrNonDigitCharacter:
-        fprintf(stderr, "Error in line %d: invalid character\n", tile_list.num_tiles);
-        list_free(&tile_list);
-        return EXIT_FAILURE;
-    case ReadErrTooFewNumbers:
-        fprintf(stderr, "Error in line %d: Too few numbers, expected exactly 2\n",
-                tile_list.num_tiles);
-        list_free(&tile_list);
-        return EXIT_FAILURE;
-    case ReadErrTooManyNumbers:
-        fprintf(stderr, "Error in line %d: Too much numbers, expected exactly 2\n",
-                tile_list.num_tiles);
-        list_free(&tile_list);
-        return EXIT_FAILURE;
-    case ReadErrOutOfMemory:
-        fprintf(stderr, "Error in line %d: Failed to allocate more memory",
-                tile_list.num_tiles);
-        list_free(&tile_list);
-        return EXIT_FAILURE;
+void hk_print(Field *this) {
+    Tile *t = this->tiles;
+    for (uint32_t i = 1; i < this->num_tiles; i++) {
+        //printf("%u\n", i);
+        if (this->tiles[i].pair == 0) {
+            printf("None\n");
+            return;
+        }
     }
-
-    Array tile_array;
-    // uebertragen der Liste in ein Array, und uebergeben des ownership der Tiles
-    // an das Array
-    if(array_from_list(&tile_array, &tile_list) == MallocFailed) {
-        fprintf(stderr, "Error: Failed to allocate enough memory");
-        list_free(&tile_list); // fehlgeschlagen, noch ist liste owner.
-        return EXIT_FAILURE;
+    for (uint32_t i = 1; i < this->num_tiles; i++) {
+        if (tile_odd(&t[i]))
+            continue;
+        uint32_t p = t[i].pair;
+        printf("%u %u;%u %u\n", t[i].x, t[i].y, t[p].x, t[p].y);
     }
+}
 
-    // ignoriert null-tile
-    qsort(tile_array.tiles, tile_array.num_tiles-1, sizeof(Tile*), tile_compare);
-
-    if(array_find_neighbours(&tile_array)) {
-        fprintf(stderr, "Error: Duplicated entry\n");
-        array_drop(&tile_array);
-        return EXIT_FAILURE;
+void hk(Field *this) {
+    uint32_t result = 0;
+    while(hk_bfs(this)) {
+        for (uint32_t i = 1; i < this->num_tiles; i++) {
+            if (tile_odd(&this->tiles[i]))
+                continue;
+            if (this->tiles[i].pair == 0 && hk_dfs(this, i))
+                result++;
+        }
     }
+    hk_print(this);
+}
 
-    // Check nach Validitaet erst nach Suche nach Dopplungen moeglich
-    if (!list_necessity(&tile_list)) {
-        printf("None\n");
-        array_drop(&tile_array);
-        return EXIT_SUCCESS;
+int main() {
+    Field f;
+    if(field_init(&f)) {
+        fprintf(stderr, "Failed to allocate memory");
+        return EXIT_FAILURE;
     }
-
-    // check nach Rechteck erst nach check fuer Doppelungen moeglich
-    if (list_rectangle(&tile_list)) {
-        list_print_rectangle(&tile_list);
-        array_drop(&tile_array);
-        return EXIT_SUCCESS;
+    int result = EXIT_FAILURE;
+    switch(field_parse(&f)) {
+    case ReadOk:
+        qsort(f.tiles+1, f.num_tiles-1, sizeof(Tile), tile_compare);
+        if (field_neighbours(&f) != 0) {
+            fprintf(stderr, "Error: Duplicated entry\n"); // Duplikat exisitert
+            break;
+        }
+        if (f.num_tiles - f.num_odd == f.num_odd) {
+            printf("None\n");
+        }
+        hk(&f); // Algorithmus von Hopcroft und Karp
+        result = EXIT_SUCCESS;
+        break;
+    case ReadEof:               result = EXIT_SUCCESS; break;
+    case ReadErrOverflow:       fprintf(stderr, "%u: too big integer\n", f.num_tiles); break;
+    case ReadErrInvalidChar:    fprintf(stderr, "%u: invalid character\n", f.num_tiles); break;
+    case ReadErrTooFewNumbers:  fprintf(stderr, "%u: too few numbers\n", f.num_tiles); break;
+    case ReadErrTooManyNumbers: fprintf(stderr, "%u: too many numbers\n", f.num_tiles); break;
+    case ReadErrOutOfMemory:    fprintf(stderr, "%u: not enough memory\n", f.num_tiles); break;
     }
-
-    // Algorithmus von Hopcroft und Karp
-
-
-    array_drop(&tile_array);
-    return EXIT_SUCCESS;
+    free(f.tiles);
+    return result;
 }
diff --git a/loesung2.c b/loesung2.c
deleted file mode 100755
index 5b37b0b..0000000
--- a/loesung2.c
+++ /dev/null
@@ -1,378 +0,0 @@
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h> // fixed sized integer
-#include <stdbool.h> // booleans
-
-#define INF UINT32_MAX
-
-/********** Kachel definition **********/
-typedef struct Tile {
-    uint32_t x;
-    uint32_t y;
-    uint32_t neigh[4]; // Nachbarn
-    struct Tile *p_next; // queue
-    uint32_t pair; // matching partner
-    uint32_t dist; // entfernung zu Knoten 0 im Schichtgraph
-} Tile;
-
-// initialisieren des Speichers von einem Tile
-void tile_init(Tile *this) {
-    memset(this, 0, sizeof(Tile));
-    this->dist = INF;
-}
-
-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
-    if (s->y < t->y) return -1;
-    if (s->y > t->y) return 1;
-    return 0; // Elemente sind gleich
-}
-
-// Kacheln wie im Schachbrettmuster einordnen
-uint32_t tile_odd(Tile* this) {
-    return ((this->x ^ this->y)&1);
-}
-
-/********** Kachelfeld **********/
-typedef struct Field {
-    // Array von Tiles, tile 0 is imagenary tile for hk-algorithmus
-    // Tiles werden mit 1 bis num_tiles exklusive indiziert
-    Tile *tiles;
-    uint32_t num_tiles;
-    uint32_t size;
-    uint32_t num_odd;
-} Field;
-
-// returns 0 if successful, nonzero if failed
-int field_init(Field *this) {
-    memset(this, 0, sizeof(Field));
-    this->tiles = malloc(sizeof(Tile));
-    this->num_tiles = 1;
-    this->size = 1;
-    return this->tiles == 0;
-}
-
-// if an error occurs, all memory get freed
-int field_push(Field *this, Tile *p_tile) {
-    if (this->size == this->num_tiles) {
-        if (this->size == 1u<<31) return 1; // catch overflow
-        this->size *= 2; // Armortisiert O(1)
-        Tile *new = realloc(this->tiles, this->size*sizeof(Tile));
-        if (new == NULL) return 1; // catch failed realloc
-        this->tiles = new;
-    }
-    this->num_odd += tile_odd(p_tile);
-    memcpy(this->tiles+this->num_tiles, p_tile, sizeof(Tile));
-    this->num_tiles++;
-    return 0;
-}
-
-/** Parsen einer Kachel(Tile) aus einer Zeile von StdIn
- *
- * Die Werte werden in die uebergebene Kachel geschrieben, sind aber
- * nur gueltig, wenn der Rueckgabewert `ReadOk` ist.
- *
- * Voraussetzung: p_tile muss initialisiert sein
- */
-typedef enum ReadResult {
-    ReadOk,
-    ReadEof,
-    ReadErrOverflow,
-    ReadErrInvalidChar,
-    ReadErrTooFewNumbers,
-    ReadErrTooManyNumbers,
-    ReadErrOutOfMemory,
-} ReadResult;
-ReadResult read_line(Tile* p_tile){
-    int c = getchar();
-    if (c == EOF) {
-        return ReadEof;
-    }
-    int cur_number = 0;
-    bool cur_whitespace = true;
-    uint32_t *p_cur; // aktuell zu parsende Zahl
-    while(1) {
-        if ('0' <= c && c <= '9') {
-            if (cur_whitespace) {
-                if(cur_number == 2) {
-                    return ReadErrTooManyNumbers;
-                }
-                p_cur = (&p_tile->x)+cur_number;
-                cur_whitespace = false;
-                cur_number++;
-            }
-            // 429496730 = 2^32 / 10, daher wenn `p_cur` groesser ist, wird ein
-            // overflow erzeugt
-            if (*p_cur > 429496729) {
-                return ReadErrOverflow;
-            }
-            (*p_cur) *= 10;
-            int digit = c - '0';
-            if (*p_cur > UINT32_MAX - digit) {
-                return ReadErrOverflow;
-            }
-            (*p_cur) += digit;
-        } else if (c == ' ') {
-            cur_whitespace = true;
-        } else if (c == '\n') {
-            if (cur_number == 2) {
-                return ReadOk;
-            } else {
-                return ReadErrTooFewNumbers;
-            }
-        } else {
-            return ReadErrInvalidChar;
-        }
-        c = getchar(); // get next character
-    }
-}
-
-/** Liest das Input von StdIn und schreibt das Ergebnis in die uebergebene Liste
- *
- * Laufzeit: O(n)
- * Speicherbedarf: O(n)
- *
- * Return:
- *  - ReadResult:
- *     ReadOk, falls das lesen Erfolgreich war
- *     ReadErr..., falls die Eingabe ungueltig ist oder zu wenig Speicher vorhanden.
- *             `num_tiles` indiziert die Zeile, in der der Fehler aufgetreten ist
- */
-ReadResult field_parse(Field *this) {
-    while (1) {
-        Tile next;
-        tile_init(&next);
-        ReadResult result = read_line(&next);
-        switch (result) {
-        case ReadOk:
-            // einfuegen in die Liste
-            if (field_push(this, &next)) {
-                return ReadErrOutOfMemory;
-            }
-            break;
-        case ReadEof:
-            if (this->num_tiles == 1) {
-                return ReadEof;
-            } else {
-                return ReadOk;
-            }
-        default: // error
-            return result;
-        }
-    }
-}
-
-/** Setzen der Nachbarn der Kacheln
- * Rueckgabe: 0 falls alles ok
- *            1 falls Dopplungen vorkommen
- */
-int field_neighbours(Field *this) {
-    uint32_t top = 1; // vergleich mit oberer Zeile
-    uint32_t begin_line = 1; // start der aktuellen Zeile
-    Tile *t = this->tiles;
-    for (uint32_t cur = 2; cur < this->num_tiles; cur++) {
-        // ermitteln der x-Beziehung
-        uint32_t east = cur-1;
-        if (t[cur].x == t[east].x) { // gleiche Zeile
-            if (t[cur].y == t[east].y) { // gleiche Spalte
-                return 1; // Doppelung
-            } else if (t[cur].y-1 == t[east].y) {
-                t[cur].neigh[1] = east;
-                t[east].neigh[3] = cur;
-            }
-        } else {
-            top = begin_line;
-            begin_line = cur; // neue Zeile
-        }
-        // ermitteln der Zeilen-Beziehung
-        if (t[begin_line].x != 0 && t[top].x < t[begin_line].x - 1) {
-            // Zeilensprung => Warten bis zur naechsten Zeile angekommen
-        } else if (t[top].x == t[cur].x - 1) {
-            // finden, ob paar nach oben existiert O(n) fuer alle Nachbarn nach oben/unten.
-            for(;t[top].y < t[cur].y && top < begin_line; top++);
-
-            // aktuelle obere Kachel koennte benachbart sein
-            if (t[top].y == t[cur].y) { // nicht auf naechste Zeile uebergegangen
-                // Neue Verbindung oben/unten gefunden
-                t[top].neigh[2] = cur;
-                t[cur].neigh[0] = top;
-            }
-        }
-    }
-    return 0;
-}
-
-void field_print(Field *this) {
-    printf("[\n");
-    Tile *t = this->tiles;
-    for (uint32_t i = 1; i < this->num_tiles; i++){
-        printf("\t(%u %u): {", t[i].x, this->tiles[i].y);
-        for (int j = 0; j < 4; j++) {
-            if(t[i].neigh[j] != 0) {
-                Tile *neigh = &t[t[i].neigh[j]];
-                printf(" (%u %u)", neigh->x, neigh->y);
-            }
-        }
-        printf(" }\n");
-    }
-    printf("]\n");
-}
-
-/********** Schlange von Tiles **********/
-typedef struct Queue {
-    Tile *p_first;
-    Tile *p_last;
-} Queue;
-
-void queue_init(Queue* this) {
-    this->p_first = NULL;
-    this->p_last = NULL;
-}
-
-void queue_push(Queue* this, Tile* p_tile) {
-    if (this->p_last != NULL) {
-        this->p_last->p_next = p_tile;
-    } else {
-        this->p_first = p_tile;
-    }
-    this->p_last = p_tile;
-    p_tile->p_next = NULL;
-}
-
-bool queue_empty(Queue* this) {
-    return this->p_first == NULL;
-}
-
-Tile *queue_pop(Queue* this) {
-    Tile *p_tile = this->p_first;
-    this->p_first = p_tile->p_next;
-    if (this->p_first == NULL) {
-        this->p_last = NULL;
-    }
-    return p_tile;
-}
-
-/********** Algorithmus von Hopcroft und Karp **********/
-bool hk_bfs(Field *this) {
-    Queue q; // Schlange von Kacheln
-    queue_init(&q);
-    Tile *t = this->tiles;
-    for (int i = 1; i < this->num_tiles; i++) {
-        // nur gerade Kacheln werden zur queue hinzufuegen
-        if (tile_odd(&t[i])) {
-            continue;
-        }
-        if (t[i].pair == 0) {
-            t[i].dist = 0;
-            queue_push(&q, &t[i]);
-        } else {
-            t[i].dist = INF;
-        }
-    }
-    t[0].dist = INF;
-    while (!queue_empty(&q)) {
-        Tile *e = queue_pop(&q); // nehme naechste gerade Kachel
-        if (e->dist >= t[0].dist)
-            continue;
-        for (int i = 0; i < 4; i++) {
-            Tile* p_neigh = &t[e->neigh[i]];
-            Tile* p_pair = &t[p_neigh->pair];
-            if(p_pair->dist == INF) {
-                p_pair->dist = e->dist+1;
-                queue_push(&q, p_pair);
-            }
-        }
-    }
-    return t[0].dist != INF;
-}
-
-bool hk_dfs(Field *this, uint32_t e) {
-    if (e == 0)
-        return true;
-    Tile *t = this->tiles;
-    Tile *p_even = &t[e];
-    for (int i = 0; i < 4; i++) {
-        // Benachbart zu e
-        uint32_t o = p_even->neigh[i]; // Nachbar, ungerade Kachel
-        Tile* p_odd = &t[o];
-        if (t[p_odd->pair].dist == p_even->dist+1) {
-            // Augmentiere den Pfad, falls durch Tiefensuche gefunden
-            if (hk_dfs(this, p_odd->pair)) {
-                p_even->pair = o;
-                p_odd->pair = e;
-                return true;
-            }
-        }
-    }
-    // Kein augmentierender Pfad von e aus
-    p_even->dist = INF;
-    return false;
-}
-
-void hk_print(Field *this) {
-    Tile *t = this->tiles;
-    for (uint32_t i = 1; i < this->num_tiles; i++) {
-        //printf("%u\n", i);
-        if (this->tiles[i].pair == 0) {
-            printf("None\n");
-            return;
-        }
-    }
-    for (uint32_t i = 1; i < this->num_tiles; i++) {
-        if (tile_odd(&t[i]))
-            continue;
-        uint32_t p = t[i].pair;
-        printf("%u %u;%u %u\n", t[i].x, t[i].y, t[p].x, t[p].y);
-    }
-}
-
-void hk(Field *this) {
-    uint32_t result = 0;
-    while(hk_bfs(this)) {
-        for (uint32_t i = 1; i < this->num_tiles; i++) {
-            if (tile_odd(&this->tiles[i]))
-                continue;
-            if (this->tiles[i].pair == 0 && hk_dfs(this, i))
-                result++;
-        }
-    }
-    hk_print(this);
-}
-
-int main() {
-    Field f;
-    if(field_init(&f)) {
-        fprintf(stderr, "Failed to allocate memory");
-        return EXIT_FAILURE;
-    }
-    int result = EXIT_FAILURE;
-    switch(field_parse(&f)) {
-    case ReadOk:
-        qsort(f.tiles+1, f.num_tiles-1, sizeof(Tile), tile_compare);
-        if (field_neighbours(&f) != 0) {
-            fprintf(stderr, "Error: Duplicated entry\n"); // Duplikat exisitert
-            break;
-        }
-        if (f.num_tiles - f.num_odd == f.num_odd) {
-            printf("None\n");
-        }
-        hk(&f); // Algorithmus von Hopcroft und Karp
-        result = EXIT_SUCCESS;
-        break;
-    case ReadEof:               result = EXIT_SUCCESS; break;
-    case ReadErrOverflow:       fprintf(stderr, "%u: too big integer\n", f.num_tiles); break;
-    case ReadErrInvalidChar:    fprintf(stderr, "%u: invalid character\n", f.num_tiles); break;
-    case ReadErrTooFewNumbers:  fprintf(stderr, "%u: too few numbers\n", f.num_tiles); break;
-    case ReadErrTooManyNumbers: fprintf(stderr, "%u: too many numbers\n", f.num_tiles); break;
-    case ReadErrOutOfMemory:    fprintf(stderr, "%u: not enough memory\n", f.num_tiles); break;
-    }
-    free(f.tiles);
-    return result;
-}
-- 
GitLab