aoc-2019-c

Advent of Code 2019 Solutions in C
git clone https://git.sinitax.com/sinitax/aoc-2019-c
Log | Files | Refs | README | sfeed.txt

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}