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

main.c (4985B)


      1#include "aoc.h"
      2#include "allocator.h"
      3#include "iccmp.h"
      4#include "hmap.h"
      5#include "util.h"
      6
      7#include <assert.h>
      8#include <stdbool.h>
      9#include <stdio.h>
     10#include <stdlib.h>
     11
     12struct vec2 {
     13	int x, y;
     14};
     15
     16struct panel {
     17	struct vec2 pos;
     18	int color;
     19};
     20
     21int black = 0, white = 1;
     22
     23/* counter clockwise dx dy */
     24struct vec2 dirs[] = {
     25	{  0, -1 }, /* up */
     26	{  1,  0 }, /* right */
     27	{  0,  1 }, /* down */
     28	{ -1,  0 }  /* left */
     29};
     30
     31const char *solmap = "\
     32.............................................\n\
     33.............................................\n\
     34...#..#.###...##...##..####.#.....##..###....\n\
     35...#..#.#..#.#..#.#..#.#....#....#..#.#..#...\n\
     36...#..#.#..#.#....#..#.###..#....#....#..#...\n\
     37...#..#.###..#....####.#....#....#....###....\n\
     38...#..#.#.#..#..#.#..#.#....#....#..#.#......\n\
     39....##..#..#..##..#..#.#....####..##..#......\
     40";
     41
     42uint32_t
     43hmap_pos_hash(struct hmap_key key)
     44{
     45	const struct vec2 *vec = key.p;
     46	uint32_t hash;
     47
     48	hash = (uint32_t) vec->x;
     49	hash |= ((uint32_t) vec->y) << 16;
     50
     51	return hash;
     52}
     53
     54bool
     55hmap_pos_keycmp(struct hmap_key k1, struct hmap_key k2)
     56{
     57	const struct vec2 *v1 = k1.p, *v2 = k2.p;
     58
     59	return v1->x == v2->x && v1->y == v2->y;
     60}
     61
     62char *
     63gen_map(struct hmap *panels, struct vec2 *pos, int rot)
     64{
     65	const char symbol[4] = "^>v<";
     66	struct vec2 min, max, dims;
     67	struct hmap_iter iter;
     68	const struct vec2 *ppos;
     69	int i, color;
     70	char *map;
     71
     72	min.x = min.y = -2;
     73	max.x = max.y = 2;
     74	for (HMAP_ITER(panels, iter)) {
     75		ppos = iter.link->key.p;
     76		min.x = MIN(min.x, ppos->x);
     77		min.y = MIN(min.y, ppos->y);
     78		max.x = MAX(max.x, ppos->x);
     79		max.y = MAX(max.y, ppos->y);
     80	}
     81
     82	if (pos) {
     83		min.x = MIN(min.x, pos->x);
     84		min.y = MIN(min.y, pos->y);
     85		max.x = MAX(max.x, pos->x);
     86		max.y = MAX(max.y, pos->y);
     87	}
     88
     89	dims.x = max.x - min.x + 1;
     90	dims.y = max.y - min.y + 1;
     91	assert(dims.x > 0 && dims.y > 0);
     92	map = malloc(((size_t) dims.x + 1) * (size_t) dims.y);
     93	assert(map != NULL);
     94	memset(map, '.', ((size_t) dims.x + 1) * (size_t) dims.y);
     95
     96	for (HMAP_ITER(panels, iter)) {
     97		ppos = iter.link->key.p;
     98		color = iter.link->value.i;
     99		map[(ppos->y - min.y) * (dims.x + 1) + (ppos->x - min.x)] = color ? '#' : '.';
    100	}
    101
    102	if (pos) {
    103		map[(pos->y - min.y) * (dims.x + 1) + (pos->x - min.x)] = symbol[rot];
    104	}
    105
    106	for (i = 0; i < dims.y; i++)
    107		map[dims.x + i * (dims.x + 1)] = '\n';
    108	map[(dims.x + 1) * dims.y - 1] = '\0';
    109
    110	return map;
    111}
    112
    113void
    114panels_init(struct hmap *panels, int start_color)
    115{
    116	struct hmap_link **link;
    117	int color, rot, brot;
    118	struct vec2 pos;
    119	struct icc icc;
    120	void *key;
    121	char *map;
    122	enum {
    123		STATE_COLOR,
    124		STATE_ROTATE
    125	} state;
    126
    127	icc_init(&icc);
    128	icc_parse_inst(&icc, aoc.input, aoc.input_size);
    129
    130	pos.x = pos.y = 0;
    131	key = memdup(&pos, sizeof(pos));
    132	hmap_add(panels, (struct hmap_key) {.p = key },
    133		(struct hmap_val) {.i = start_color});
    134
    135	rot = 0;
    136	color = 0;
    137	state = STATE_COLOR;
    138	while (icc.state != ICC_HALT) {
    139		icc_step_inst(&icc);
    140		switch (icc.state) {
    141		case ICC_OUTPUT:
    142			if (state == STATE_COLOR) {
    143				color = (int) mi_cast_ul(&icc.out);
    144				assert(color == 0 || color == 1);
    145				aoc_debug("OUTPUT %i %i: %i\n", pos.x, pos.y, color);
    146				link = hmap_link_pos(panels,
    147					(struct hmap_key) {.p = &pos});
    148				if (*link) {
    149					(*link)->value.i = color;
    150				} else {
    151					key = memdup(&pos, sizeof(pos));
    152					*link = hmap_link_alloc(panels,
    153						(struct hmap_key) {.p = key},
    154						(struct hmap_val) {.i = color},
    155						NULL);
    156				}
    157				state = STATE_ROTATE;
    158			} else if (state == STATE_ROTATE) {
    159				brot = (int) mi_cast_ul(&icc.out);
    160				assert(brot == 0 || brot == 1);
    161				aoc_debug("ROT %i %i: %i\n", pos.x, pos.y, brot);
    162				rot = (rot + (brot ? 1 : -1) + 4) % 4;
    163				pos.x += dirs[rot].x;
    164				pos.y += dirs[rot].y;
    165				if (aoc.debug) {
    166					map = gen_map(panels, &pos, rot);
    167					aoc_debug("%s", map);
    168					free(map);
    169				}
    170				state = STATE_COLOR;
    171			}
    172			break;
    173		case ICC_INPUT:
    174			link = hmap_link_get(panels,
    175				(struct hmap_key) {.p = &pos});
    176			if (link) {
    177				aoc_debug("INPUT %i %i: %i\n", pos.x, pos.y,
    178					(*link)->value.i);
    179				mi_setv(&icc.in, (mi_ul) (*link)->value.i,
    180					MI_POS);
    181			} else {
    182				aoc_debug("INPUT %i %i: 0\n", pos.x, pos.y);
    183				mi_setv(&icc.in, 0, MI_POS);
    184			}
    185			break;
    186		}
    187	}
    188
    189	icc_deinit(&icc);
    190}
    191
    192void
    193part1(void)
    194{
    195	struct hmap panels;
    196	struct hmap_iter iter;
    197	int count;
    198
    199	hmap_init(&panels, 100, hmap_pos_hash, hmap_pos_keycmp,
    200		&stdlib_strict_heap_allocator);
    201	panels_init(&panels, black);
    202
    203	count = 0;
    204	for (HMAP_ITER(&panels, iter))
    205		count += 1;
    206	aoc.answer = aprintf("%i", count);
    207	aoc.solution = "2088";
    208
    209	for (HMAP_ITER(&panels, iter))
    210		free(iter.link->key._p);
    211	hmap_deinit(&panels);
    212}
    213
    214void
    215part2(void)
    216{
    217	struct hmap panels;
    218	struct hmap_iter iter;
    219	char *map;
    220
    221	hmap_init(&panels, 100, hmap_pos_hash, hmap_pos_keycmp,
    222		&stdlib_strict_heap_allocator);
    223	panels_init(&panels, white);
    224
    225	map = gen_map(&panels, NULL, 0);
    226	aoc.answer = map;
    227	aoc.solution = solmap;
    228
    229	for (HMAP_ITER(&panels, iter))
    230		free(iter.link->key._p);
    231	hmap_deinit(&panels);
    232}