sunday.c (3708B)
1 #include <stdio.h> 2 #include <stdbool.h> 3 #include "cputime.h" 4 #define LEN(x) (sizeof(x)/sizeof(*x)) 5 6 typedef struct { 7 char grid[12][12]; 8 int w; 9 int h; 10 int xmines[12]; 11 int ymines[12]; 12 } Map; 13 14 typedef struct { 15 int x; 16 int y; 17 } Vec2; 18 19 typedef struct { 20 Vec2 data[4]; 21 int len; 22 } ArVec2; 23 24 static Vec2 mine_area[] = { 25 {.x= 0,.y=-1}, 26 {.x=-1,.y= 0}, 27 {.x= 1,.y= 0}, 28 {.x= 0,.y= 1}, 29 }; 30 31 static Vec2 heat_area[] = { 32 {.x=-1,.y=-1},{.x=0,.y=-1},{.x=1,.y=-1}, 33 {.x=-1,.y= 0}, {.x=1,.y= 0}, 34 {.x=-1,.y= 1},{.x=0,.y= 1},{.x=1,.y= 1} 35 }; 36 37 ArVec2 findPossibleMines(Map *m, Vec2 nodule) { 38 ArVec2 mines = {0}; 39 for (size_t i=0;i<LEN(mine_area);++i) { 40 Vec2 p = { .x=nodule.x+mine_area[i].x, .y=nodule.y+mine_area[i].y }; 41 if (p.x>=0&&p.x<m->w&&p.y>=0&&p.y<m->h&&m->grid[p.y][p.x]=='.') { 42 bool ok = true; 43 for (size_t j=0;j<LEN(heat_area);++j) { 44 Vec2 h = { .x=p.x+heat_area[j].x, .y=p.y+heat_area[j].y }; 45 if (h.x>=0&&h.x<m->w&&h.y>=0&&h.y<m->h&&m->grid[h.y][h.x]=='M') { 46 ok = false; 47 break; 48 } 49 } 50 if (ok) mines.data[mines.len++] = p; 51 } 52 } 53 return mines; 54 } 55 56 int countMinesX(Map *m, int x) { 57 int r = 0; 58 for (int y=0;y<m->h;++y) { 59 if (m->grid[y][x]=='M') r++; 60 } 61 return r; 62 } 63 64 int countMinesY(Map *m, int y) { 65 int r = 0; 66 for (int x=0;x<m->w;++x) { 67 if (m->grid[y][x]=='M') r++; 68 } 69 return r; 70 } 71 72 bool validateMap(Map *m, int mul) { 73 bool ok = true; 74 for (int x=0;x<m->w;++x) { 75 if (countMinesX(m, x)!=m->xmines[x]*mul) { 76 ok = false; 77 break; 78 } 79 } 80 if (!ok) return false; 81 for (int y=0;y<m->h;++y) { 82 if (countMinesY(m, y)!=m->ymines[y]*mul) { 83 ok = false; 84 break; 85 } 86 } 87 return ok; 88 } 89 90 int calcChecksum(Map *m) { 91 int r = 0; 92 for (int y=0;y<m->h;++y) { 93 for (int x=0;x<m->w;++x) { 94 if (m->grid[y][x]=='M') { 95 r += (y+1)^(x+1); 96 } 97 } 98 } 99 return r; 100 } 101 102 int findMines(Map *m, Vec2 *nodules, int nodules_s, int mul) { 103 if (nodules_s==0&&validateMap(m, mul)) { 104 return calcChecksum(m); 105 } 106 ArVec2 mines = findPossibleMines(m, nodules[0]); 107 for (int i=0;i<mines.len;++i) { 108 Map m1 = *m; 109 m1.grid[mines.data[i].y][mines.data[i].x] = 'M'; 110 int csum = findMines(&m1, nodules+1, nodules_s-1, mul); 111 if (csum!=0) return csum; 112 } 113 return 0; 114 } 115 116 int main(void) { 117 Map map = {0}; 118 for (int c=getchar();c!=EOF;c=getchar()) { 119 if (c>='0'&&c<='9') { 120 if (map.h==0) { 121 map.xmines[map.w++]=c-'0'; 122 } else { 123 map.ymines[map.h-1]=c-'0'; 124 map.w=0; 125 } 126 } else if (c=='.'||c=='O'||c=='G') { 127 map.grid[map.h-1][map.w++]=c; 128 } else if (c=='\n'&&map.w>0) { 129 map.h++; 130 } 131 } 132 map.h-=1; 133 Vec2 nodules1[32] = {0}; 134 Vec2 nodules2[32] = {0}; 135 int nodules1_s = 0; 136 int nodules2_s = 0; 137 for (int y=0;y<map.h;++y) { 138 for (int x=0;x<map.w;++x) { 139 char c = map.grid[y][x]; 140 if (c=='O') { 141 nodules1[nodules1_s++] = (Vec2){ .x=x,.y=y }; 142 nodules2[nodules2_s++] = (Vec2){ .x=x,.y=y }; 143 } 144 if (c=='G') { 145 nodules2[nodules2_s++] = (Vec2){ .x=x,.y=y }; 146 } 147 } 148 } 149 150 printf("part 1: %d\n", findMines(&map, nodules1, nodules1_s, 1)); 151 printf("part 2: %d\n", findMines(&map, nodules2, nodules2_s, 2)); 152 return 0; 153 }