part2.c (5519B)
1#include "allocator.h" 2#include "hmap.h" 3#include "hmap_s.h" 4#include "aoc.h" 5#include "vec_s.h" 6#include "dvec_s.h" 7#include "util.h" 8 9#include <assert.h> 10#include <stddef.h> 11#include <stdint.h> 12#include <stdlib.h> 13 14struct layer { 15 char cells[5][5]; 16 uint8_t adj[5][5]; 17}; 18 19struct cell { 20 size_t adj; 21 char c; 22}; 23 24static void 25load_map(struct hmap *map) 26{ 27 const char *lpos, *lend; 28 struct layer *layer; 29 size_t x, y, len; 30 char line[256]; 31 32 y = 0; 33 layer = malloc(sizeof(struct layer)); 34 lpos = aoc.input; 35 lend = lpos + aoc.input_size; 36 while (readtok(line, sizeof(line), '\n', &lpos, lend)) { 37 len = strlen(line); 38 for (x = 0; x < len; x++) 39 layer->cells[y][x] = line[x]; 40 y += 1; 41 } 42 43 hmap_add(map, (struct hmap_key) {.ss = 0}, 44 (struct hmap_val) {.p = layer}); 45} 46 47static void 48print_layer(struct hmap *map, ssize_t z) 49{ 50 struct hmap_link *link; 51 const struct layer *layer; 52 size_t x, y; 53 54 link = hmap_get(map, (struct hmap_key) {.ss = z}); 55 if (link) layer = link->value.p; 56 for (y = 0; y < 5; y++) { 57 for (x = 0; x < 5; x++) { 58 if (x == 2 && y == 2) { 59 aoc_debug("?"); 60 } else if (link) { 61 aoc_debug("%c", layer->cells[y][x]); 62 } else { 63 aoc_debug("."); 64 } 65 } 66 aoc_debug("\n"); 67 } 68} 69 70static void 71print_layers(struct hmap *map, ssize_t minz, ssize_t maxz) 72{ 73 ssize_t z; 74 75 for (z = minz; z <= maxz; z++) { 76 aoc_debug("Z %li\n", z); 77 print_layer(map, z); 78 aoc_debug("\n"); 79 } 80} 81 82static size_t 83map_count(struct hmap *map) 84{ 85 const struct layer *layer; 86 struct hmap_iter iter; 87 size_t x, y, count; 88 89 count = 0; 90 for (HMAP_ITER(map, iter)) { 91 layer = iter.link->value.p; 92 for (y = 0; y < 5; y++) { 93 for (x = 0; x < 5; x++) { 94 if (x == 2 && y == 2) 95 continue; 96 if (layer->cells[y][x] == '#') 97 count += 1; 98 } 99 } 100 } 101 102 return count; 103} 104 105static size_t 106top_cells(const struct layer *layer) 107{ 108 size_t i, count; 109 110 count = 0; 111 for (i = 0; i < 5; i++) 112 count += layer->cells[0][i] == '#'; 113 114 return count; 115} 116 117static size_t 118right_cells(const struct layer *layer) 119{ 120 size_t i, count; 121 122 count = 0; 123 for (i = 0; i < 5; i++) 124 count += layer->cells[i][4] == '#'; 125 126 return count; 127} 128 129static size_t 130bottom_cells(const struct layer *layer) 131{ 132 size_t i, count; 133 134 count = 0; 135 for (i = 0; i < 5; i++) 136 count += layer->cells[4][i] == '#'; 137 138 return count; 139} 140 141static size_t 142left_cells(const struct layer *layer) 143{ 144 size_t i, count; 145 146 count = 0; 147 for (i = 0; i < 5; i++) 148 count += layer->cells[i][0] == '#'; 149 150 return count; 151} 152 153static size_t 154cell_count(struct hmap *map, struct layer *layer, 155 struct vec2i *pos, size_t dir, ssize_t z) 156{ 157 struct hmap_link *link; 158 const struct layer *nlayer; 159 size_t count; 160 161 count = 0; 162 if (pos->x == 2 && pos->y == 2) { 163 link = hmap_get(map, (struct hmap_key) {.ss = z + 1}); 164 if (!link) return 0; 165 nlayer = link->value.p; 166 switch (dir) { 167 case ADJ_NORTH: 168 return bottom_cells(nlayer); 169 case ADJ_EAST: 170 return left_cells(nlayer); 171 case ADJ_SOUTH: 172 return top_cells(nlayer); 173 case ADJ_WEST: 174 return right_cells(nlayer); 175 } 176 return count; 177 } else if (pos->x < 0 || pos->x >= 5 || pos->y < 0 || pos->y >= 5) { 178 link = hmap_get(map, (struct hmap_key) {.ss = z - 1}); 179 if (!link) return 0; 180 nlayer = link->value.p; 181 if (pos->x < 0) { 182 return nlayer->cells[2][1] == '#'; 183 } else if (pos->x >= 5) { 184 return nlayer->cells[2][3] == '#'; 185 } else if (pos->y < 0) { 186 return nlayer->cells[1][2] == '#'; 187 } else if (pos->y >= 5) { 188 return nlayer->cells[3][2] == '#'; 189 } 190 } else { 191 return layer->cells[pos->y][pos->x] == '#'; 192 } 193 194 assert(0); 195} 196 197static void 198step(struct hmap *map) 199{ 200 struct hmap_iter iter; 201 struct hmap_link **linkp; 202 struct hmap_link *link; 203 struct vec2i pos, npos; 204 ssize_t z, minz, maxz; 205 struct layer *layer; 206 size_t i, count; 207 char *cell; 208 209 minz = maxz = 0; 210 for (HMAP_ITER(map, iter)) { 211 layer = iter.link->value._p; 212 if (memchr(layer->cells, '#', 5 * 5)) { 213 minz = MIN(minz, iter.link->key.ss); 214 maxz = MAX(maxz, iter.link->key.ss); 215 } 216 } 217 minz -= 1; 218 maxz += 1; 219 220 for (z = minz; z <= maxz; z++) { 221 linkp = hmap_link_pos(map, 222 (struct hmap_key) {.ss = z}); 223 if (!*linkp) { 224 layer = malloc(sizeof(struct layer)); 225 memset(layer->cells, '.', 5 * 5); 226 *linkp = hmap_link_alloc(map, 227 (struct hmap_key) {.ss = z}, 228 (struct hmap_val) {.p = layer}, NULL); 229 } else { 230 layer = (*linkp)->value._p; 231 } 232 233 for (pos.y = 0; pos.y < 5; pos.y++) { 234 for (pos.x = 0; pos.x < 5; pos.x++) { 235 count = 0; 236 for (i = 0; i < 4; i++) { 237 vec2i_add(&npos, &pos, &adj[i]); 238 count += cell_count(map, 239 layer, &npos, i, z); 240 } 241 layer->adj[pos.y][pos.x] = (uint8_t) count; 242 } 243 } 244 } 245 246 for (z = minz; z <= maxz; z++) { 247 for (pos.y = 0; pos.y < 5; pos.y++) { 248 for (pos.x = 0; pos.x < 5; pos.x++) { 249 link = hmap_get(map, 250 (struct hmap_key) {.ss = z}); 251 layer = link->value._p; 252 cell = &layer->cells[pos.y][pos.x]; 253 count = layer->adj[pos.y][pos.x]; 254 if (*cell == '#' && count != 1) { 255 *cell = '.'; 256 } else if (*cell == '.' && (count == 1 || count == 2)) { 257 *cell = '#'; 258 } 259 } 260 } 261 } 262} 263 264 265void 266part2(void) 267{ 268 struct hmap_iter iter; 269 struct hmap map; 270 size_t i, answer; 271 272 hmap_init(&map, 32, ssizet_hmap_hash, ssizet_hmap_keycmp, 273 &stdlib_strict_heap_allocator); 274 load_map(&map); 275 276 for (i = 0; i < 200; i++) { 277 step(&map); 278 aoc_debug("-- MIN %lu --\n\n", i); 279 print_layers(&map, -5, 5); 280 } 281 282 answer = map_count(&map); 283 aoc.answer = aprintf("%lu", answer); 284 aoc.solution = "1985"; 285 286 for (HMAP_ITER(&map, iter)) 287 free(iter.link->value._p); 288 hmap_deinit(&map); 289}