easters

easters.dev solutions (C)
git clone git://bsandro.tech/easters
Log | Files | Refs | LICENSE

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 }