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;
 }