Browse Source

command line options, ultra magic squares

Kajetan Johannes Hammerle 3 years ago
parent
commit
bb7b9b860c
2 changed files with 111 additions and 49 deletions
  1. 110 48
      Main.c
  2. 1 1
      Makefile

+ 110 - 48
Main.c

@@ -1,103 +1,165 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#define SIZE 9
-#define SUM ((SIZE * (SIZE * SIZE + 1)) / 2)
-
-int data[SIZE][SIZE];
+int size = 0;
+int* data = NULL;
+int (*fitness)() = NULL;
 
 void init() {
-    for(int x = 0; x < SIZE; x++) {
-        for(int y = 0; y < SIZE; y++) {
-            data[x][y] = y * SIZE + x + 1;
-        }
+    int end = size * size;
+    data = malloc(sizeof(int) * end);
+    for(int i = 0; i < end; i++) {
+        data[i] = i + 1;
     }
 }
 
+int get(int x, int y) {
+    return data[y * size + x];
+}
+
 int errorFactor(int e) {
     return e * e;
 }
 
-int getFitness() {
+int getWanted() {
+    return (size * (size * size + 1)) / 2;
+}
+
+int getSemiFitness() {
     int fitness = 0;
-    for(int y = 0; y < SIZE; y++) {
+    int wanted = getWanted();
+    for(int y = 0; y < size; y++) {
         int sum = 0;
-        for(int x = 0; x < SIZE; x++) {
-            sum += data[x][y];
+        for(int x = 0; x < size; x++) {
+            sum += get(x, y);
         }
-        fitness += errorFactor(sum - SUM);
+        fitness += errorFactor(sum - wanted);
     }
-    for(int x = 0; x < SIZE; x++) {
+    for(int x = 0; x < size; x++) {
         int sum = 0;
-        for(int y = 0; y < SIZE; y++) {
-            sum += data[x][y];
+        for(int y = 0; y < size; y++) {
+            sum += get(x, y);
         }
-        fitness += errorFactor(sum - SUM);
+        fitness += errorFactor(sum - wanted);
     }
+    return fitness;
+}
+
+int getDiagonalBase() {
     int diaA = 0;
     int diaB = 0;
-    for(int i = 0; i < SIZE; i++) {
-        diaA += data[i][i];
-        diaB += data[i][(SIZE - 1) - i];
+    for(int i = 0; i < size; i++) {
+        diaA += get(i, i);
+        diaB += get(i, (size - 1) - i);
+    }
+    int wanted = getWanted();
+    int fitness = errorFactor(diaA - wanted);
+    fitness += errorFactor(diaB - wanted);
+    return fitness;
+}
+
+int getNormalFitness() {
+    return getSemiFitness() + getDiagonalBase();
+}
+
+int getPandiagonalBase() {
+    int fitness = 0;
+    int wanted = getWanted();
+    for(int x = 0; x < size; x++) {
+        int sumA = 0;
+        int sumB = 0;
+        for(int y = 0; y < size; y++) {
+            sumA += get((x + y) % size, y);
+            sumB += get((x - y + size) % size, y);
+        }
+        fitness += errorFactor(sumA - wanted);
+        fitness += errorFactor(sumB - wanted);
     }
-    fitness += errorFactor(diaA - SUM);
-    fitness += errorFactor(diaB - SUM);
     return fitness;
 }
 
+int getAssociativeBase() {
+    int fitness = 0;
+    int wanted = size * size + 1;
+    for(int x = 0; x < size; x++) {
+        for(int y = 0; y < size; y++) {
+            int sum = get(x, y) + get(size - x - 1, size - y - 1);
+            fitness += errorFactor(sum - wanted);
+        }
+    }
+    return fitness;
+}
+
+int getUltraFitness() {
+    return getSemiFitness() + getPandiagonalBase() + getAssociativeBase();
+}
+
 void print() {
-    printf("Fitness: %d\n", getFitness());
-    for(int y = 0; y < SIZE; y++) {
-        for(int x = 0; x < SIZE; x++) {
-            printf("%2d ", data[x][y]);
+    printf("Fitness: %d\n", fitness());
+    for(int y = 0; y < size; y++) {
+        for(int x = 0; x < size; x++) {
+            printf("%2d ", get(x, y));
         }
         putchar('\n');
     }
     putchar('\n');
 }
 
-void swap(int x1, int y1, int x2, int y2) {
-    int tmp = data[x1][y1];
-    data[x1][y1] = data[x2][y2];
-    data[x2][y2] = tmp;
-}
-
-void randSwap() {
-    swap(rand() % SIZE, rand() % SIZE, rand() % SIZE, rand() % SIZE);
+void swap(int a, int b) {
+    int tmp = data[a];
+    data[a] = data[b];
+    data[b] = tmp;
 }
 
 void randSwaps(int swaps) {
     for(int i = 0; i < swaps; i++) {
-        swap(rand() % SIZE, rand() % SIZE, rand() % SIZE, rand() % SIZE);
+        swap(rand() % (size * size), rand() % (size * size));
     }
 }
 
-int main() {
-    init();
-    for(int k = 0; k < 2000; k++) {
-        for(int i = 0; i < 1000000; i++) {
-            int oldFitness = getFitness();
+int main(int argAmount, char** args) {
+    if(argAmount < 5) {
+        if(argAmount <= 0) {
+            printf("... <type> <size> <tries> <generations>\n");
+        } else {
+            printf("%s <type> <size> <tries> <generations>\n", args[0]);
+        }
+        return 0;
+    }
+    int type = atoi(args[1]);
+    size = atoi(args[2]);
+    int tries = atoi(args[3]);
+    int generations = atoi(args[4]);
+
+    switch(type) {
+        case 1: fitness = getNormalFitness; break;
+        case 2: fitness = getUltraFitness; break;
+        default: puts("unknown type"); return 0;
+    }
 
-            int x1 = rand() % SIZE;
-            int y1 = rand() % SIZE;
-            int x2 = rand() % SIZE;
-            int y2 = rand() % SIZE;
+    init();
+    for(int k = 0; k < tries; k++) {
+        for(int i = 0; i < generations; i++) {
+            int oldFitness = fitness();
 
-            swap(x1, y1, x2, y2);
+            int a = rand() % (size * size);
+            int b = rand() % (size * size);
+            swap(a, b);
 
-            int newFitness = getFitness();
+            int newFitness = fitness();
             if(newFitness == 0) {
                 break;
             }
 
             if(newFitness >= oldFitness) {
-                swap(x1, y1, x2, y2);
+                swap(a, b);
             }
         }
-        if(getFitness() == 0) {
+        if(fitness() == 0) {
             print();
         }
         randSwaps(400);
     }
+    free(data);
     return 0;
 }

+ 1 - 1
Makefile

@@ -1,5 +1,5 @@
 run: build
-	./magic
+	./magic 2 5 50 200000
 
 build: Main.c 
 	gcc -o magic Main.c -Wall -Wextra -pedantic -Werror -O3