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


      1#include "aoc.h"
      2#include "allocator.h"
      3#include "dvec_s.h"
      4#include "util.h"
      5#include "maxint.h"
      6
      7#include <assert.h>
      8#include <stdio.h>
      9#include <stdlib.h>
     10
     11struct vec3 {
     12	union {
     13		struct {
     14			int x, y, z;
     15		};
     16		int axis[3];
     17	};
     18};
     19
     20struct moon {
     21	struct vec3 pos, vel;
     22};
     23
     24void
     25moons_init(struct dvec *vec)
     26{
     27	char *p, *tok, *val;
     28	struct moon m, *slot;
     29	int i;
     30
     31	m.vel = (struct vec3) { 0, 0, 0 };
     32	dvec_init(vec, 100, sizeof(struct moon), &stdlib_strict_heap_allocator);
     33
     34	tok = aoc.input;
     35	while ((p = strchr(tok, '\n'))) {
     36		val = tok;
     37		for (i = 0; i < 3 && (val = strchr(val + 1, '=')); i++)
     38			m.pos.axis[i] = (int) strtol(val + 1, NULL, 10);
     39		slot = dvec_add_slot(vec);
     40		memcpy(slot, &m, sizeof(struct moon));
     41		tok = p + 1;
     42	}
     43}
     44
     45void
     46moons_deinit(struct dvec *vec)
     47{
     48	dvec_deinit(vec);
     49}
     50
     51int
     52get_energy(struct moon *m)
     53{
     54	int pot, kin;
     55
     56	pot = ABS(m->pos.x);
     57	pot += ABS(m->pos.y);
     58	pot += ABS(m->pos.z);
     59
     60	kin = ABS(m->vel.x);
     61	kin += ABS(m->vel.y);
     62	kin += ABS(m->vel.z);
     63
     64	return pot * kin;
     65}
     66
     67int
     68rel(int a, int b)
     69{
     70	if (a == b) return 0;
     71	return (a < b) ? +1 : -1;
     72}
     73
     74void
     75sim_step(struct dvec *moons, int show)
     76{
     77	struct moon *m1, *m2;
     78	static int step = 0;
     79	size_t i, k, l;
     80	int relv;
     81
     82	/* initial state */
     83	for (i = 0; !step && show && i < dvec_len(moons); i++) {
     84		m1 = dvec_at(moons, i);
     85		aoc_debug("%i: %i %i %i , %i %i %i = %i\n", step, m1->pos.x, m1->pos.y, m1->pos.z,
     86			m1->vel.x, m1->vel.y, m1->vel.z, get_energy(m1));
     87	}
     88
     89	/* update velocity */
     90	for (i = 0; i < dvec_len(moons); i++) {
     91		for (k = i + 1; k < dvec_len(moons); k++) {
     92			m1 = dvec_at(moons, i);
     93			m2 = dvec_at(moons, k);
     94
     95			for (l = 0; l < 3; l++) {
     96				relv = rel(m1->pos.axis[l], m2->pos.axis[l]);
     97				m1->vel.axis[l] += relv;
     98				m2->vel.axis[l] -= relv;
     99			}
    100		}
    101	}
    102
    103	/* update position */
    104	for (i = 0; i < dvec_len(moons); i++) {
    105		m1 = dvec_at(moons, i);
    106		for (k = 0; k < 3; k++)
    107			m1->pos.axis[k] += m1->vel.axis[k];
    108
    109		if (show) aoc_debug("%i: %i %i %i , %i %i %i = %i\n", step+1,
    110			m1->pos.x, m1->pos.y, m1->pos.z, m1->vel.x,
    111			m1->vel.y, m1->vel.z, get_energy(m1));
    112	}
    113
    114	step++;
    115}
    116
    117void
    118part1(void)
    119{
    120	struct dvec moons;
    121	size_t i;
    122	int energy;
    123
    124	moons_init(&moons);
    125
    126	for (i = 0; i < 1000; i++)
    127		sim_step(&moons, aoc.debug);
    128
    129	energy = 0;
    130	for (i = 0; i < dvec_len(&moons); i++)
    131		energy += get_energy(dvec_at(&moons, i));
    132
    133	aoc.answer = aprintf("%i", energy);
    134	aoc.solution = "12053";
    135
    136	moons_deinit(&moons);
    137}
    138
    139void
    140part2(void)
    141{
    142	struct dvec init, moons;
    143	struct maxint cycles[3];
    144	struct maxint imm = MI_INIT;
    145	mi_ul tmp;
    146	struct maxint *steps;
    147	struct moon *m1, *m2;
    148	int same, poseq, veleq;
    149	char buf[64];
    150	size_t i, k;
    151
    152	moons_init(&init);
    153
    154	for (i = 0; i < 3; i++)
    155		mi_init(&cycles[i]);
    156
    157	for (i = 0; i < 3; i++) {
    158		moons_init(&moons);
    159
    160		same = 0;
    161		cycles[i] = MI_INIT;
    162		mi_setv(&cycles[i], 0, MI_POS);
    163
    164		while (!same) {
    165			sim_step(&moons, aoc.debug == 2);
    166
    167			same = 1;
    168			for (k = 0; k < dvec_len(&moons); k++) {
    169				m1 = dvec_at(&moons, k);
    170				m2 = dvec_at(&init, k);
    171				veleq = m1->pos.axis[i] == m2->pos.axis[i];
    172				poseq = m1->vel.axis[i] == m2->vel.axis[i];
    173				if (!veleq || !poseq) {
    174					same = 0;
    175					break;
    176				}
    177			}
    178
    179			mi_add(&cycles[i], &cycles[i], mi_imm(&imm, &tmp, 1, MI_POS));
    180		}
    181
    182		mi_dec(&cycles[i], buf, sizeof(buf), 0);
    183		aoc_debug("Cycles Axis %i: %s\n", i+1, buf);
    184
    185		moons_deinit(&moons);
    186	}
    187
    188	steps = &cycles[0];
    189	for (i = 1; i < 3; i++)
    190		mi_lcm(steps, steps, &cycles[i]);
    191
    192	mi_dec(steps, buf, sizeof(buf), 0);
    193	aoc.answer = strdup(buf);
    194	aoc.solution = "320380285873116";
    195
    196	for (i = 0; i < 3; i++)
    197		mi_deinit(&cycles[i]);
    198
    199	moons_deinit(&init);
    200}