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


      1#include "aoc.h"
      2#include "iccmp.h"
      3#include "list.h"
      4#include "maxint.h"
      5#include "util.h"
      6
      7#include <assert.h>
      8#include <stdbool.h>
      9#include <stdint.h>
     10#include <stdlib.h>
     11
     12struct packet {
     13	struct maxint x, y;
     14	size_t src_ip, dst_ip;
     15
     16	struct list_link link;
     17};
     18
     19static struct packet nat_packet;
     20static bool nat_avail = false;
     21
     22void
     23feed_input(struct icc *icc, mi_ul imm)
     24{
     25	while (icc->state != ICC_HALT) {
     26		if (icc->state == ICC_INPUT) {
     27			mi_setv(&icc->in, imm, MI_POS);
     28			icc_step_inst(icc);
     29			break;
     30		}
     31		icc_step_inst(icc);
     32	}
     33}
     34
     35void
     36free_packet(void *p)
     37{
     38	struct packet *packet;
     39
     40	packet = p;
     41	mi_deinit(&packet->x);
     42	mi_deinit(&packet->y);
     43	free(packet);
     44}
     45
     46bool
     47recv_packet(struct list *queues, struct maxint *val, int state, size_t ip)
     48{
     49	static struct packet *packet;
     50	struct list_link *link;
     51	char buf[64];
     52
     53	aoc_debug("INPUT %i\n", ip);
     54	if (list_empty(&queues[ip])) {
     55		mi_setv(val, 1, MI_NEG);
     56		return false;
     57	} else {
     58		switch(state) {
     59		case 0:
     60			link = list_front(&queues[ip]);
     61			packet = LIST_UPCAST(link, struct packet, link);
     62			aoc_debug("%i <- %i (", packet->src_ip, packet->dst_ip);
     63			mi_dec(&packet->x, buf, sizeof(buf), 0);
     64			aoc_debug("%s, ", buf);
     65			mi_dec(&packet->y, buf, sizeof(buf), 0);
     66			aoc_debug("%s)\n", buf);
     67			mi_set(val, &packet->x);
     68			break;
     69		case 1:
     70			mi_set(val, &packet->y);
     71			list_link_pop(&packet->link);
     72			free_packet(packet);
     73			break;
     74		}
     75		return true;
     76	}
     77}
     78
     79void
     80send_packet(struct list *queues, struct maxint *val, int state, size_t ip)
     81{
     82	static struct packet *packet;
     83	size_t dst;
     84	char buf[64];
     85
     86	aoc_debug("OUTPUT %i\n", ip);
     87	switch (state) {
     88	case 0:
     89		dst = (size_t) mi_cast_ul(val);
     90		if (dst == 255) {
     91			packet = &nat_packet;
     92		} else {
     93			packet = malloc(sizeof(struct packet));
     94			mi_init(&packet->x);
     95			mi_init(&packet->y);
     96		}
     97		packet->src_ip = ip;
     98		packet->dst_ip = dst;
     99		packet->link = LIST_LINK_INIT;
    100		break;
    101	case 1:
    102		mi_set(&packet->x, val);
    103		break;
    104	case 2:
    105		mi_set(&packet->y, val);
    106		if (packet->dst_ip != 255) {
    107			assert(packet->dst_ip < 50);
    108			list_insert_back(&queues[packet->dst_ip], &packet->link);
    109		} else {
    110			nat_avail = true;
    111		}
    112		aoc_debug("%i <- %i (", packet->dst_ip, packet->src_ip);
    113		mi_dec(&packet->x, buf, sizeof(buf), 0);
    114		aoc_debug("%s, ", buf);
    115		mi_dec(&packet->y, buf, sizeof(buf), 0);
    116		aoc_debug("%s)\n", buf);
    117		break;
    118	}
    119}
    120
    121bool
    122nic_tick(struct icc *icc, struct list *queues, size_t ip)
    123{
    124	int out_state, in_state;
    125	bool idle, done;
    126
    127	done = false;
    128	idle = true;
    129	in_state = 0;
    130	out_state = 0;
    131	while (!done && icc->state != ICC_HALT) {
    132		switch (icc->state) {
    133		case ICC_INPUT:
    134			idle &= !recv_packet(queues, &icc->in, in_state, ip);
    135			in_state = (in_state + 1) % 2;
    136			if (!in_state) done = true;
    137			break;
    138		case ICC_OUTPUT:
    139			send_packet(queues, &icc->out, out_state, ip);
    140			out_state = (out_state + 1) % 3;
    141			idle = false;
    142			break;
    143		defualt:
    144			assert(icc->state == ICC_RUN);
    145		}
    146		icc_step_inst(icc);
    147	}
    148	assert(in_state == 0 && out_state == 0);
    149
    150	return idle;
    151}
    152
    153void
    154part1(void)
    155{
    156	struct list queues[50];
    157	struct icc icc[50];
    158	char buf[64];
    159	size_t i;
    160
    161	for (i = 0; i < 50; i++) {
    162		list_init(&queues[i]);
    163		icc_init(&icc[i]);
    164		icc_parse_inst(&icc[i], aoc.input, aoc.input_size);
    165		feed_input(&icc[i], (mi_ul) i);
    166	}
    167
    168	mi_init(&nat_packet.x);
    169	mi_setv(&nat_packet.x, 0, MI_POS);
    170	mi_init(&nat_packet.y);
    171	mi_setv(&nat_packet.y, 0, MI_POS);
    172
    173	while (!nat_avail) {
    174		aoc_debug("-- TICK --\n");
    175		for (i = 0; i < 50; i++)
    176			nic_tick(&icc[i], queues, i);
    177	}
    178
    179	mi_dec(&nat_packet.y, buf, sizeof(buf), 0);
    180	aoc.answer = aprintf("%s", buf);
    181	aoc.solution = "20225";
    182
    183	mi_deinit(&nat_packet.x);
    184	mi_deinit(&nat_packet.y);
    185	for (i = 0; i < 50; i++) {
    186		list_free_items(&queues[i], free_packet,
    187			LIST_OFFSET(struct packet, link));
    188		icc_deinit(&icc[i]);
    189	}
    190}
    191
    192void
    193part2(void)
    194{
    195	struct list queues[256];
    196	struct icc icc[50];
    197	struct packet *packet;
    198	size_t answer;
    199	size_t last;
    200	bool idle;
    201	size_t i;
    202
    203	for (i = 0; i < 50; i++) {
    204		list_init(&queues[i]);
    205		icc_init(&icc[i]);
    206		icc_parse_inst(&icc[i], aoc.input, aoc.input_size);
    207		feed_input(&icc[i], (mi_ul) i);
    208	}
    209
    210	mi_init(&nat_packet.x);
    211	mi_setv(&nat_packet.x, 0, MI_POS);
    212	mi_init(&nat_packet.y);
    213	mi_setv(&nat_packet.y, 0, MI_POS);
    214
    215	last = SIZE_MAX;
    216	while (1) {
    217		aoc_debug("-- TICK --\n");
    218
    219		idle = true;
    220		for (i = 0; i < 50; i++)
    221			idle &= nic_tick(&icc[i], queues, i);
    222
    223		if (idle) {
    224			assert(nat_avail);
    225			packet = malloc(sizeof(struct packet));
    226			mi_init(&packet->x);
    227			mi_set(&packet->x, &nat_packet.x);
    228			mi_init(&packet->y);
    229			mi_set(&packet->y, &nat_packet.y);
    230			packet->dst_ip = nat_packet.dst_ip;
    231			packet->src_ip = nat_packet.src_ip;
    232			packet->link = LIST_LINK_INIT;
    233			list_insert_back(&queues[0], &packet->link);
    234
    235			if (mi_cast_ul(&packet->y) == last) {
    236				answer = last;
    237				break;
    238			}
    239			last = mi_cast_ul(&packet->y);
    240
    241		}
    242	}
    243
    244	aoc.answer = aprintf("%lu", answer);
    245	aoc.solution = "14348";
    246
    247	mi_deinit(&nat_packet.x);
    248	mi_deinit(&nat_packet.y);
    249	for (i = 0; i < 50; i++) {
    250		list_free_items(&queues[i], free_packet,
    251			LIST_OFFSET(struct packet, link));
    252		icc_deinit(&icc[i]);
    253	}
    254}