commit 2ed29b3e942132d9a3b732f9e5a71d5c6b7d527d
Author: Antoine Amarilli <a3nm@a3nm.net>
Date: Sat, 31 May 2014 23:19:18 +0200
main
Diffstat:
main.c | | | 377 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 377 insertions(+), 0 deletions(-)
diff --git a/main.c b/main.c
@@ -0,0 +1,377 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define MAXN 20
+#define UBOUND 10
+
+int debug = 0;
+
+int N, K;
+// z, x, y
+// height, line, col
+unsigned char G[MAXN][MAXN][MAXN];
+// attack patterns
+unsigned char A[MAXN][MAXN][MAXN];
+// rook positions (z, x, y)
+unsigned char R[MAXN*MAXN][3];
+// rook violations
+//char V[MAXN*MAXN];
+// putative violations
+unsigned char V[MAXN][MAXN][MAXN];
+
+void print() {
+ for (int x = 0; x < N; x++) {
+ for (int y = 0; y < N; y++) {
+ int pos = -1;
+ for (int z = 0; z < N; z++) {
+ if (G[z][x][y]) {
+ pos = z;
+ break;
+ }
+ }
+ if (pos < 0)
+ printf("* ");
+ else {
+ if (pos < 9)
+ printf("%d ", pos + 1);
+ else
+ printf("%c ", 'A' + (pos - 9));
+ }
+ }
+ printf("\n");
+ }
+ if (debug) {
+ for (int i = 0; i < K; i++)
+ printf("rook %d at %d %d %d\n", i, R[i][1], R[i][2], R[i][0]);
+ }
+}
+
+void print_attacks() {
+ for (int z = 0; z < N; z++) {
+ printf("== %d ==\n", z);
+ for (int x = 0; x < N; x++) {
+ for (int y = 0; y < N; y++) {
+ int val = A[z][x][y];
+ printf("%d%d%d ", val & (1 << 0), (val & (1 << 1))>>1, (val& (1 << 2))>>2);
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+}
+
+void print_all_violations() {
+ for (int z = 0; z < N; z++) {
+ printf("== %d ==\n", z);
+ for (int x = 0; x < N; x++) {
+ for (int y = 0; y < N; y++) {
+ int val = V[z][x][y];
+ printf("%d ", val);
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+}
+
+void print_violations() {
+ int tot = 0;
+ for (int i = 0; i < K; i++) {
+ int val = V[R[i][0]][R[i][1]][R[i][2]];
+ printf("rook %d has %d violations\n", i,
+ val);
+ tot += val;
+ }
+ printf("=> %d total violations\n", tot);
+}
+
+void upd_atk_rm(int i) {
+ int z = R[i][0];
+ int x = R[i][1];
+ int y = R[i][2];
+ for (int p = 0; p < N; p++) {
+ A[p][x][y] &= ~(1 << 0);
+ A[z][p][y] &= ~(1 << 1);
+ A[z][x][p] &= ~(1 << 2);
+ }
+}
+
+void upd_atk_add(int i) {
+ int z = R[i][0];
+ int x = R[i][1];
+ int y = R[i][2];
+ for (int p = 0; p < N; p++) {
+ A[p][x][y] |= 1 << 0;
+ A[z][p][y] |= 1 << 1;
+ A[z][x][p] |= 1 << 2;
+ }
+}
+
+
+void num_attacks() {
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < N; j++)
+ for (int k = 0; k < N; k++)
+ A[i][j][k] = 0;
+ for (int i = 0; i < K; i++) {
+ if (R[i][0] < MAXN)
+ upd_atk_add(i);
+ }
+}
+
+
+
+void check_attacks() {
+ int backup[MAXN][MAXN][MAXN];
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < N; j++)
+ for (int k = 0; k < N; k++)
+ backup[i][j][k] = A[i][j][k];
+ num_attacks();
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < N; j++)
+ for (int k = 0; k < N; k++)
+ if (backup[i][j][k] != A[i][j][k]) {
+ print_attacks();
+ printf("ERROR at %d %d %d\n", i, j, k);
+ exit(1);
+ }
+}
+
+
+int num_violations() {
+ int tot = 0;
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < N; j++)
+ for (int k = 0; k < N; k++)
+ V[i][j][k] = 0;
+ for (int z = 0; z < N; z++)
+ for (int x = 0; x < N; x++)
+ for (int y = 0; y < N; y++) {
+ for (int p = 0; p < N; p++) {
+ if (p != z && (A[p][x][y] | (1 << 0)) == 7)
+ {V[z][x][y]++;}
+ if (p != x && (A[z][p][y] | (1 << 1)) == 7)
+ {V[z][x][y]++;}
+ if (p != y && (A[z][x][p] | (1 << 2)) == 7)
+ {V[z][x][y]++;}
+ }
+ if (G[z][x][y]) {
+ tot += V[z][x][y];
+ //printf("add %d to num_violations for %d %d %d\n", V[z][x][y], x, y, z);
+ }
+ }
+ return tot;
+}
+
+// int tot = 0;
+// for (int i = 0; i < K; i++) {
+// V[i] = 0;
+// int z = R[i][0];
+// int x = R[i][1];
+// int y = R[i][2];
+// for (int p = 0; p < N; p++) {
+// if (p != z && A[p][x][y] == 7)
+// {V[i]++; tot++;}
+// if (p != x && A[z][p][y] == 7)
+// {V[i]++; tot++;}
+// if (p != y && A[z][x][p] == 7)
+// {V[i]++; tot++;}
+// }
+// }
+
+void init_pos() {
+ // initial position
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < N; j++)
+ for (int k = 0; k < N; k++)
+ G[i][j][k] = 0;
+ int remaining = K;
+ int height = 0, pos = 0;
+ while (remaining > 0) {
+ int z = height;
+ int x = pos;
+ int y = (pos + height) % N;
+ G[z][x][y] = 1;
+ remaining--;
+ R[remaining][0] = z;
+ R[remaining][1] = x;
+ R[remaining][2] = y;
+ pos++;
+ if (pos >= N) {
+ pos = 0;
+ height++;
+ }
+ }
+}
+
+int choose_rook(int prev) {
+ int best = -1;
+ int nvs[MAXN*MAXN];
+ int nnvs = 0;
+ int nv;
+ for (int i = 0; i < K; i++) {
+ if (i == prev)
+ continue;
+ if ((nv = V[R[i][0]][R[i][1]][R[i][2]]) > best) {
+ best = nv;
+ }
+ }
+ for (int i = 0; i < K; i++) {
+ if (i == prev)
+ continue;
+ if ((nv = V[R[i][0]][R[i][1]][R[i][2]]) == best) {
+ nvs[nnvs++] = i;
+ }
+ }
+ return nvs[rand() % nnvs];
+}
+
+void random_move() {
+ int rook = (rand() % K);
+ //printf("move %d at random\n", rook);
+ int z = R[rook][0];
+ int x = R[rook][1];
+ int y = R[rook][2];
+ G[z][x][y] = 0;
+ upd_atk_rm(rook);
+ int nx, ny, nz;
+ while (1) {
+ nx = (rand() % N);
+ ny = (rand() % N);
+ nz = (rand() % N);
+ if (!A[nz][nx][ny] && !G[nz][nx][ny])
+ break;
+ }
+ G[nz][nx][ny] = 1;
+ R[rook][0] = nz;
+ R[rook][1] = nx;
+ R[rook][2] = ny;
+ num_attacks();
+ num_violations();
+}
+
+void position(int i) {
+ int best = N*N*N+1;
+ int bs[MAXN*MAXN*MAXN][3];
+ int nbs = 0;
+ for (int z = 0; z < N; z++)
+ for (int x = 0; x < N; x++)
+ for (int y = 0; y < N; y++)
+ if (!A[z][x][y] && !G[z][x][y])
+ if (V[z][x][y] < best) {
+ best = V[z][x][y];
+ }
+ for (int z = 0; z < N; z++)
+ for (int x = 0; x < N; x++)
+ for (int y = 0; y < N; y++)
+ if (!A[z][x][y] && !G[z][x][y])
+ if (V[z][x][y] == best) {
+ bs[nbs][0] = z;
+ bs[nbs][1] = x;
+ bs[nbs][2] = y;
+ nbs++;
+ if (debug) printf("%d %d %d is a fitting position\n", z, x, y);
+ }
+ int npos = rand() % nbs;
+ int bz = bs[npos][0];
+ int bx = bs[npos][1];
+ int by = bs[npos][2];
+ if(debug) printf("position %d to %d %d %d with viol %d\n", i, bx, by, bz, V[bz][by][by]);
+ G[bz][bx][by] = 1;
+ R[i][0] = bz;
+ R[i][1] = bx;
+ R[i][2] = by;
+ upd_atk_add(i);
+}
+
+void spawn_rook() {
+ position(K-1);
+}
+
+
+int main(int argc, char **argv) {
+ int oK;
+ int first = 1;
+ int seed;
+ N = atoi(argv[1]);
+ oK = atoi(argv[2]);
+ if (argc == 4)
+ seed = atoi(argv[3]);
+ else {
+ seed = time(NULL);
+ }
+ printf("using random seed %d\n", seed);
+ srand(seed);
+ int tot;
+ for (K = oK; K < N*N; K++) {
+ printf("try %d rooks\n", K);
+ if (first) {
+ init_pos();
+ first = 0;
+ } else {
+ spawn_rook();
+ }
+ num_attacks();
+ tot = num_violations();
+ print();
+ //print_attacks();
+ //print_violations();
+ int useless1 = 0, useless2 = 0;
+ int prev_raw = -1;
+ while (tot > 0) {
+ if (debug) print_violations();
+ int rook = choose_rook(prev_raw);
+ prev_raw = rook;
+ // when doing a useless step, offset the choice
+ //rook = (rook + useless1) % K;
+ if(debug) printf("chosen rook %d yields %d\n", prev_raw, rook);
+ if(debug) print();
+ if(debug) print_attacks();
+ int z = R[rook][0];
+ int x = R[rook][1];
+ int y = R[rook][2];
+ G[z][x][y] = 0;
+ upd_atk_rm(rook);
+ R[rook][0] = MAXN;
+ R[rook][1] = MAXN;
+ R[rook][2] = MAXN;
+ if(debug) print_attacks();
+ if(debug) check_attacks();
+ num_violations();
+ position(rook);
+ int otot = tot;
+ int pred = V[R[rook][0]][R[rook][1]][R[rook][2]];
+ if(debug) print();
+ if(debug) print_all_violations();
+ tot = num_violations();
+ if(debug) print_all_violations();
+ int npred = V[R[rook][0]][R[rook][1]][R[rook][2]];
+ if (npred != pred) {
+ printf("violation mispredict: thought %d and had %d!\n", pred, npred);
+ exit(1);
+ }
+ if(debug) print_violations();
+ if(debug) print_attacks();
+ if(debug) print();
+ //printf("total viol %d\n", tot);
+ if (tot >= otot) {
+ // no improvement
+ useless1++;
+ useless2++;
+ } else {
+ useless1 = useless2 = 0;
+ }
+ if (useless1 > UBOUND || useless2 > UBOUND) {
+ useless1 = useless2 = 0;
+ random_move();
+ }
+ }
+ printf("!!! DONE %d rooks\n", K);
+ print();
+ }
+ return 0;
+}
+
+