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 (4519B)


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