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


      1#include "aoc.h"
      2#include "icc.h"
      3#include "util.h"
      4#include "allocator.h"
      5
      6#include <assert.h>
      7#include <string.h>
      8#include <stdlib.h>
      9#include <stdio.h>
     10#include <stdint.h>
     11
     12void
     13run_amp(struct icc *icc, int phase, int input, int *out)
     14{
     15	int in_cnt, out_cnt;
     16
     17	in_cnt = out_cnt = 0;
     18	while (icc->state != ICC_HALT) {
     19		icc_step_inst(icc);
     20		switch (icc->state) {
     21		case ICC_INPUT:
     22			assert(in_cnt <= 1);
     23			icc->in = (in_cnt == 0) ? phase : input;
     24			in_cnt++;
     25			break;
     26		case ICC_OUTPUT:
     27			assert(out_cnt == 0);
     28			*out = icc->out;
     29			out_cnt++;
     30			break;
     31		}
     32	}
     33}
     34
     35void
     36bf_phase(struct icc *icc, struct dvec *inst, size_t *state,
     37	size_t max_depth, size_t depth, int in, int *max, size_t *maxstate)
     38{
     39	size_t i, k;
     40	int out;
     41
     42	if (depth == max_depth) {
     43		aoc_debug("SETTING %i%i%i%i%i -> %i\n", state[0], state[1],
     44			state[2], state[3], state[4], in);
     45		if (*max == 0 || in > *max) {
     46			*max = in;
     47			memcpy(maxstate, state, sizeof(int) * max_depth);
     48		}
     49		return;
     50	}
     51
     52	for (i = 0; i < max_depth; i++) {
     53		/* dont reuse phase setting */
     54		for (k = 0; k < depth; k++)
     55			if (state[k] == i) break;
     56		if (k != depth) continue;
     57
     58		state[depth] = i;
     59		icc_reset(icc, inst);
     60		aoc_debug("START AMP %i (%i):\n", depth, i);
     61		run_amp(icc, (int) i, in, &out);
     62		aoc_debug("END AMP %i (%i): %i -> %i\n", depth, i, in, out);
     63		bf_phase(icc, inst, state, max_depth,
     64			depth + 1, out, max, maxstate);
     65	}
     66}
     67
     68int
     69run_phase_loop(struct icc *iccs, struct dvec *inst, size_t *state, size_t n)
     70{
     71	size_t i;
     72	int passes, done;
     73	int *ins, out, in_cnt;
     74
     75	ins = malloc(n * sizeof(int));
     76	assert(ins != NULL);
     77
     78	for (i = 0; i < n; i++)
     79		icc_reset(&iccs[i], inst);
     80
     81	ins[0] = 0;
     82	passes = done = 0;
     83	while (!done) {
     84		for (i = 0; i < n; i++) {
     85			in_cnt = 0;
     86			aoc_debug("START AMP %i (%i):\n", i, state[i]);
     87			while (iccs[i].state != ICC_HALT) {
     88				icc_step_inst(&iccs[i]);
     89				switch (iccs[i].state) {
     90				case ICC_INPUT:
     91					iccs[i].in =
     92						(!passes && !in_cnt
     93						? (int) state[i] : ins[i]);
     94					in_cnt++;
     95					break;
     96				case ICC_OUTPUT:
     97					ins[(i+1) % n] = iccs[i].out;
     98					break;
     99				}
    100				if (iccs[i].state == ICC_OUTPUT)
    101					break;
    102			}
    103			if (iccs[i].state == ICC_HALT)
    104				done = 1;
    105			aoc_debug("END AMP %i (%i): %i -> %i\n", i,
    106					state[i], ins[i], ins[(i+1) % n]);
    107		}
    108		passes += 1;
    109	}
    110
    111	out = ins[0];
    112	free(ins);
    113
    114	return out;
    115}
    116
    117void
    118bf_phase_loop(size_t *state, size_t max_depth, size_t depth,
    119	struct icc *iccs, void *inst, int *max, size_t *maxstate)
    120{
    121	size_t i, k;
    122	int out;
    123
    124	if (depth == max_depth) {
    125		out = run_phase_loop(iccs, inst, state, max_depth);
    126		aoc_debug("SETTING %i%i%i%i%i -> %i\n", state[0], state[1],
    127			state[2], state[3], state[4], out);
    128		if (*max == 0 || out > *max) {
    129			*max = out;
    130			memcpy(maxstate, state, sizeof(int) * max_depth);
    131		}
    132		return;
    133	}
    134
    135	for (i = 0; i < max_depth; i++) {
    136		for (k = 0; k < depth; k++)
    137			if (state[k] - 5 == i) break;
    138		if (k != depth) continue;
    139
    140		state[depth] = i + 5;
    141		bf_phase_loop(state, max_depth, depth + 1, iccs, inst, max, maxstate);
    142	}
    143}
    144
    145void
    146part1(void)
    147{
    148	struct icc icc;
    149	struct dvec inst;
    150	size_t state[5], maxstate[5];
    151	int max;
    152
    153	icc_init(&icc);
    154	icc_parse_inst(&icc, aoc.input, aoc.input_size);
    155
    156	dvec_init(&inst, sizeof(int), 0, &stdlib_heap_allocator);
    157	dvec_copy(&inst, &icc.instructions);
    158
    159	max = 0;
    160	bf_phase(&icc, &inst, state, 5, 0, 0, &max, maxstate);
    161
    162	aoc_debug("\nMAX SETTING: %i%i%i%i%i\n", maxstate[0], maxstate[1],
    163		maxstate[2], maxstate[3], maxstate[4]);
    164
    165	aoc.answer = aprintf("%i", max);
    166	aoc.solution = "24625";
    167
    168	dvec_deinit(&inst);
    169	icc_deinit(&icc);
    170}
    171
    172void
    173part2(void)
    174{
    175	size_t state[5], maxstate[5];
    176	struct icc iccs[5];
    177	struct dvec inst;
    178	int i, max;
    179
    180	icc_init(&iccs[0]);
    181	icc_parse_inst(&iccs[0], aoc.input, aoc.input_size);
    182
    183	dvec_init(&inst, sizeof(int), 0, &stdlib_heap_allocator);
    184	dvec_copy(&inst, &iccs[0].instructions);
    185
    186	for (i = 1; i < 5; i++) {
    187		icc_init(&iccs[i]);
    188		icc_copy(&iccs[i], &iccs[0]);
    189	}
    190
    191	max = 0;
    192	bf_phase_loop(state, 5, 0, iccs, &inst, &max, maxstate);
    193
    194	aoc_debug("\nMAX SETTING: %i%i%i%i%i\n", maxstate[0], maxstate[1],
    195		maxstate[2], maxstate[3], maxstate[4]);
    196
    197	aoc.answer = aprintf("%i", max);
    198	aoc.solution = "36497698";
    199
    200	dvec_deinit(&inst);
    201	for (i = 0; i < 5; i++)
    202		icc_deinit(&iccs[i]);
    203}