aoc-2019-c

git clone https://git.sinitax.com/sinitax/aoc-2019-c
Log | Files | Refs | README | sfeed.txt

commit 2f5c51b28c1b0bc2f932aeeb6c068799494b0195
parent 7d77e0cc6ded255d08f27d9148bdc1efe0d602e1
Author: Louis Burda <quent.burda@gmail.com>
Date:   Wed, 17 Nov 2021 17:55:20 +0100

Add day 12

Diffstat:
Mlibs/include/maxint.h | 2++
Mlibs/src/maxint.c | 36++++++++++++++++++++++++++++++++++++
Asrc/12/Makefile | 13+++++++++++++
Asrc/12/input | 4++++
Asrc/12/main.c | 190+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/12/part1 | 208+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/12/part2 | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/12/test.input | 4++++
Asrc/12/test.input2 | 4++++
9 files changed, 511 insertions(+), 0 deletions(-)

diff --git a/libs/include/maxint.h b/libs/include/maxint.h @@ -58,6 +58,8 @@ void mi_mul(struct maxint *m1, const struct maxint *m2); // m1 *= m2 void mi_div(struct maxint *m1, struct maxint *m2, const struct maxint *m3); // m1 /= m3, m2 = m1 % m3 void mi_swap(struct maxint *m1, struct maxint *m2); // m1 <=> m2 int mi_cmp(const struct maxint *m1, const struct maxint *m2); // m1 < m2 ? m2 > m1 ? 1 : 0 : -1 +void mi_gcm(struct maxint *m1, const struct maxint *m2); // m1 = gcm(m1, m2) +void mi_lcm(struct maxint *m1, const struct maxint *m2); // m1 = lcm(m1, m2) char * mi_convstr(char *alloc, const struct maxint *m, int base, const char *alph); char * mi_hexstr(char *alloc, const struct maxint *m, int cap); diff --git a/libs/src/maxint.c b/libs/src/maxint.c @@ -244,6 +244,42 @@ mi_cmp(const struct maxint *m1, const struct maxint *m2) return 0; } +void +mi_gcd(struct maxint *m1, const struct maxint *m2) +{ + struct maxint rem, b; + + rem = b = MI_INIT; + mi_setv(&rem, 0, MI_POS); + mi_set(&b, m2); + + do { + mi_div(m1, &rem, &b); + mi_swap(m1, &b); + mi_swap(&b, &rem); + } while (!mi_zero(&b)); + + mi_free(&rem); + mi_free(&b); +} + +void +mi_lcm(struct maxint *m1, const struct maxint *m2) +{ + struct maxint lcm; + + lcm = MI_INIT; + mi_set(&lcm, m1); + + mi_gcd(m1, m2); + mi_swap(m1, &lcm); + + mi_mul(m1, m2); + mi_div(m1, NULL, &lcm); + + mi_free(&lcm); +} + int mi_lastset(const struct maxint *m1) { diff --git a/src/12/Makefile b/src/12/Makefile @@ -0,0 +1,13 @@ +CFLAGS = -g -I ../../libs/include -L ../../libs/build +LDLIBS = -laoc + +all: lib main + +clean: + rm main + +lib: + make -C ../../libs + +main: main.c ../../libs/build/* + $(CC) -o $@ $< $(CFLAGS) $(LDLIBS) diff --git a/src/12/input b/src/12/input @@ -0,0 +1,4 @@ +<x=-2, y=9, z=-5> +<x=16, y=19, z=9> +<x=0, y=3, z=6> +<x=11, y=0, z=11> diff --git a/src/12/main.c b/src/12/main.c @@ -0,0 +1,190 @@ +#include "aoc.h" +#include "memvec.h" +#include "maxint.h" + +#include <stdlib.h> +#include <stdio.h> + +struct vec3 { + union { + struct { + int x, y, z; + }; + int axis[3]; + }; +}; + +struct moon { + struct vec3 pos, vel; +}; + +void +moons_init(struct memvec *vec) +{ + char *p, *p2, *tok, *val; + struct moon m; + int i; + + m.vel = (struct vec3) { 0, 0, 0 }; + memvec_init(vec, 100, sizeof(struct moon)); + + tok = aoc.input; + while ((p = strchr(tok, '\n'))) { + val = tok; + for (i = 0; i < 3 && (val = strchr(val + 1, '=')); i++) + m.pos.axis[i] = strtol(val + 1, NULL, 10); + memvec_add(vec, &m); + tok = p + 1; + } +} + +void +moons_free(struct memvec *vec) +{ + memvec_free(vec); +} + +int +get_energy(struct moon *m) +{ + int pot, kin; + + pot = ABS(m->pos.x); + pot += ABS(m->pos.y); + pot += ABS(m->pos.z); + + kin = ABS(m->vel.x); + kin += ABS(m->vel.y); + kin += ABS(m->vel.z); + + return pot * kin; +} + +int +rel(int a, int b) +{ + if (a == b) return 0; + return (a < b) ? +1 : -1; +} + +void +sim_step(struct memvec *moons, int show) +{ + struct moon *m1, *m2; + static int step = 0; + int i, k, l, relv; + + /* initial state */ + for (i = 0; !step && show && i < memvec_len(moons); i++) { + m1 = memvec_get(moons, i); + debug("%i: %i %i %i , %i %i %i = %i\n", step, m1->pos.x, m1->pos.y, m1->pos.z, + m1->vel.x, m1->vel.y, m1->vel.z, get_energy(m1)); + } + + /* update velocity */ + for (i = 0; i < memvec_len(moons); i++) { + for (k = i + 1; k < memvec_len(moons); k++) { + m1 = memvec_get(moons, i); + m2 = memvec_get(moons, k); + + for (l = 0; l < 3; l++) { + relv = rel(m1->pos.axis[l], m2->pos.axis[l]); + m1->vel.axis[l] += relv; + m2->vel.axis[l] -= relv; + } + } + } + + /* update position */ + for (i = 0; i < memvec_len(moons); i++) { + m1 = memvec_get(moons, i); + for (k = 0; k < 3; k++) + m1->pos.axis[k] += m1->vel.axis[k]; + + if (show) debug("%i: %i %i %i , %i %i %i = %i\n", step+1, + m1->pos.x, m1->pos.y, m1->pos.z, m1->vel.x, + m1->vel.y, m1->vel.z, get_energy(m1)); + } + + step++; +} + +void +part1(void) +{ + struct memvec moons; + struct moon *m; + int i, energy; + + moons_init(&moons); + + for (i = 0; i < 1000; i++) + sim_step(&moons, aoc.debug); + + energy = 0; + for (i = 0; i < memvec_len(&moons); i++) + energy += get_energy(memvec_get(&moons, i)); + + aoc.answer = CHKP(aprintf("%i", energy)); + aoc.solution = "12053"; + + moons_free(&moons); +} + +void +part2(void) +{ + struct memvec init, moons; + struct maxint cycles[3]; + struct maxint *steps; + struct moon *m1, *m2; + int same, poseq, veleq; + int i, k; + char *s; + + moons_init(&init); + + s = NULL; + for (i = 0; i < 3; i++) { + moons_init(&moons); + + same = 0; + cycles[i] = MI_INIT; + mi_setv(&cycles[i], 0, MI_POS); + + while (!same) { + sim_step(&moons, aoc.debug == 2); + + same = 1; + for (k = 0; k < memvec_len(&moons); k++) { + m1 = memvec_get(&moons, k); + m2 = memvec_get(&init, k); + veleq = m1->pos.axis[i] == m2->pos.axis[i]; + poseq = m1->vel.axis[i] == m2->vel.axis[i]; + if (!veleq || !poseq) { + same = 0; + break; + } + } + + mi_add(&cycles[i], &mi_one); + } + + debug("Cycles Axis %i: %s\n", i+1, (s = mi_decstr(s, &cycles[i]))); + + moons_free(&moons); + } + free(s); + + steps = &cycles[0]; + for (i = 1; i < 3; i++) + mi_lcm(steps, &cycles[i]); + + aoc.answer = mi_decstr(NULL, steps); + aoc.solution = "320380285873116"; + + for (i = 0; i < 3; i++) + mi_free(&cycles[i]); + + moons_free(&init); +} diff --git a/src/12/part1 b/src/12/part1 @@ -0,0 +1,208 @@ +--- Day 12: The N-Body Problem --- + +The space near Jupiter is not a very safe place; you need to be careful of a big distracting red +spot, extreme radiation, and a whole lot of moons swirling around. You decide to start by tracking +the four largest moons: Io, Europa, Ganymede, and +Callisto. + +After a brief scan, you calculate the position of each moon (your puzzle input). You +just need to simulate their motion so you can avoid them. + +Each moon has a 3-dimensional position (x, y, and z) and a 3-dimensional velocity. The position of +each moon is given in your scan; the x, y, and z velocity of each moon starts at 0. + +Simulate the motion of the moons in time steps. Within each time step, first update the +velocity of every moon by applying gravity. Then, once all moons' velocities have been +updated, update the position of every moon by applying velocity. Time progresses by one +step once all of the positions are updated. + +To apply gravity, consider every pair of moons. On each axis (x, y, and +z), the velocity of each moon changes by exactly +1 or -1 to pull the moons together. +For example, if Ganymede has an x position of 3, and Callisto has a x position of 5, then Ganymede's +x velocity changes by +1 (because 5 > 3) and Callisto's x velocity changes by +-1 (because 3 < 5). However, if the positions on a given axis are the same, the velocity on that +axis does not change for that pair of moons. + +Once all gravity has been applied, apply velocity: simply add the velocity of each moon +to its own position. For example, if Europa has a position of x=1, y=2, z=3 and a velocity of x=-2, +y=0,z=3, then its new position would be x=-1, y=2, z=6. This process does not modify the velocity of +any moon. + +For example, suppose your scan reveals the following positions: + +<x=-1, y=0, z=2> +<x=2, y=-10, z=-7> +<x=4, y=-8, z=8> +<x=3, y=5, z=-1> + +Simulating the motion of these moons would produce the following: + +After 0 steps: +pos=<x=-1, y= 0, z= 2>, vel=<x= 0, y= 0, z= 0> +pos=<x= 2, y=-10, z=-7>, vel=<x= 0, y= 0, z= 0> +pos=<x= 4, y= -8, z= 8>, vel=<x= 0, y= 0, z= 0> +pos=<x= 3, y= 5, z=-1>, vel=<x= 0, y= 0, z= 0> + +After 1 step: +pos=<x= 2, y=-1, z= 1>, vel=<x= 3, y=-1, z=-1> +pos=<x= 3, y=-7, z=-4>, vel=<x= 1, y= 3, z= 3> +pos=<x= 1, y=-7, z= 5>, vel=<x=-3, y= 1, z=-3> +pos=<x= 2, y= 2, z= 0>, vel=<x=-1, y=-3, z= 1> + +After 2 steps: +pos=<x= 5, y=-3, z=-1>, vel=<x= 3, y=-2, z=-2> +pos=<x= 1, y=-2, z= 2>, vel=<x=-2, y= 5, z= 6> +pos=<x= 1, y=-4, z=-1>, vel=<x= 0, y= 3, z=-6> +pos=<x= 1, y=-4, z= 2>, vel=<x=-1, y=-6, z= 2> + +After 3 steps: +pos=<x= 5, y=-6, z=-1>, vel=<x= 0, y=-3, z= 0> +pos=<x= 0, y= 0, z= 6>, vel=<x=-1, y= 2, z= 4> +pos=<x= 2, y= 1, z=-5>, vel=<x= 1, y= 5, z=-4> +pos=<x= 1, y=-8, z= 2>, vel=<x= 0, y=-4, z= 0> + +After 4 steps: +pos=<x= 2, y=-8, z= 0>, vel=<x=-3, y=-2, z= 1> +pos=<x= 2, y= 1, z= 7>, vel=<x= 2, y= 1, z= 1> +pos=<x= 2, y= 3, z=-6>, vel=<x= 0, y= 2, z=-1> +pos=<x= 2, y=-9, z= 1>, vel=<x= 1, y=-1, z=-1> + +After 5 steps: +pos=<x=-1, y=-9, z= 2>, vel=<x=-3, y=-1, z= 2> +pos=<x= 4, y= 1, z= 5>, vel=<x= 2, y= 0, z=-2> +pos=<x= 2, y= 2, z=-4>, vel=<x= 0, y=-1, z= 2> +pos=<x= 3, y=-7, z=-1>, vel=<x= 1, y= 2, z=-2> + +After 6 steps: +pos=<x=-1, y=-7, z= 3>, vel=<x= 0, y= 2, z= 1> +pos=<x= 3, y= 0, z= 0>, vel=<x=-1, y=-1, z=-5> +pos=<x= 3, y=-2, z= 1>, vel=<x= 1, y=-4, z= 5> +pos=<x= 3, y=-4, z=-2>, vel=<x= 0, y= 3, z=-1> + +After 7 steps: +pos=<x= 2, y=-2, z= 1>, vel=<x= 3, y= 5, z=-2> +pos=<x= 1, y=-4, z=-4>, vel=<x=-2, y=-4, z=-4> +pos=<x= 3, y=-7, z= 5>, vel=<x= 0, y=-5, z= 4> +pos=<x= 2, y= 0, z= 0>, vel=<x=-1, y= 4, z= 2> + +After 8 steps: +pos=<x= 5, y= 2, z=-2>, vel=<x= 3, y= 4, z=-3> +pos=<x= 2, y=-7, z=-5>, vel=<x= 1, y=-3, z=-1> +pos=<x= 0, y=-9, z= 6>, vel=<x=-3, y=-2, z= 1> +pos=<x= 1, y= 1, z= 3>, vel=<x=-1, y= 1, z= 3> + +After 9 steps: +pos=<x= 5, y= 3, z=-4>, vel=<x= 0, y= 1, z=-2> +pos=<x= 2, y=-9, z=-3>, vel=<x= 0, y=-2, z= 2> +pos=<x= 0, y=-8, z= 4>, vel=<x= 0, y= 1, z=-2> +pos=<x= 1, y= 1, z= 5>, vel=<x= 0, y= 0, z= 2> + +After 10 steps: +pos=<x= 2, y= 1, z=-3>, vel=<x=-3, y=-2, z= 1> +pos=<x= 1, y=-8, z= 0>, vel=<x=-1, y= 1, z= 3> +pos=<x= 3, y=-6, z= 1>, vel=<x= 3, y= 2, z=-3> +pos=<x= 2, y= 0, z= 4>, vel=<x= 1, y=-1, z=-1> + +Then, it might help to calculate the total energy in the system. The total energy for a +single moon is its potential energy multiplied by its kinetic energy. A +moon's potential energy is the sum of the absolute values of its x, y, and z position +coordinates. A moon's kinetic energy is the sum of the absolute values of its velocity +coordinates. Below, each line shows the calculations for a moon's potential energy (pot), kinetic +energy (kin), and total energy: + +Energy after 10 steps: +pot: 2 + 1 + 3 = 6; kin: 3 + 2 + 1 = 6; total: 6 * 6 = 36 +pot: 1 + 8 + 0 = 9; kin: 1 + 1 + 3 = 5; total: 9 * 5 = 45 +pot: 3 + 6 + 1 = 10; kin: 3 + 2 + 3 = 8; total: 10 * 8 = 80 +pot: 2 + 0 + 4 = 6; kin: 1 + 1 + 1 = 3; total: 6 * 3 = 18 +Sum of total energy: 36 + 45 + 80 + 18 = 179 + +In the above example, adding together the total energy for all moons after 10 steps produces the +total energy in the system, 179. + +Here's a second example: + +<x=-8, y=-10, z=0> +<x=5, y=5, z=10> +<x=2, y=-7, z=3> +<x=9, y=-8, z=-3> + +Every ten steps of simulation for 100 steps produces: + +After 0 steps: +pos=<x= -8, y=-10, z= 0>, vel=<x= 0, y= 0, z= 0> +pos=<x= 5, y= 5, z= 10>, vel=<x= 0, y= 0, z= 0> +pos=<x= 2, y= -7, z= 3>, vel=<x= 0, y= 0, z= 0> +pos=<x= 9, y= -8, z= -3>, vel=<x= 0, y= 0, z= 0> + +After 10 steps: +pos=<x= -9, y=-10, z= 1>, vel=<x= -2, y= -2, z= -1> +pos=<x= 4, y= 10, z= 9>, vel=<x= -3, y= 7, z= -2> +pos=<x= 8, y=-10, z= -3>, vel=<x= 5, y= -1, z= -2> +pos=<x= 5, y=-10, z= 3>, vel=<x= 0, y= -4, z= 5> + +After 20 steps: +pos=<x=-10, y= 3, z= -4>, vel=<x= -5, y= 2, z= 0> +pos=<x= 5, y=-25, z= 6>, vel=<x= 1, y= 1, z= -4> +pos=<x= 13, y= 1, z= 1>, vel=<x= 5, y= -2, z= 2> +pos=<x= 0, y= 1, z= 7>, vel=<x= -1, y= -1, z= 2> + +After 30 steps: +pos=<x= 15, y= -6, z= -9>, vel=<x= -5, y= 4, z= 0> +pos=<x= -4, y=-11, z= 3>, vel=<x= -3, y=-10, z= 0> +pos=<x= 0, y= -1, z= 11>, vel=<x= 7, y= 4, z= 3> +pos=<x= -3, y= -2, z= 5>, vel=<x= 1, y= 2, z= -3> + +After 40 steps: +pos=<x= 14, y=-12, z= -4>, vel=<x= 11, y= 3, z= 0> +pos=<x= -1, y= 18, z= 8>, vel=<x= -5, y= 2, z= 3> +pos=<x= -5, y=-14, z= 8>, vel=<x= 1, y= -2, z= 0> +pos=<x= 0, y=-12, z= -2>, vel=<x= -7, y= -3, z= -3> + +After 50 steps: +pos=<x=-23, y= 4, z= 1>, vel=<x= -7, y= -1, z= 2> +pos=<x= 20, y=-31, z= 13>, vel=<x= 5, y= 3, z= 4> +pos=<x= -4, y= 6, z= 1>, vel=<x= -1, y= 1, z= -3> +pos=<x= 15, y= 1, z= -5>, vel=<x= 3, y= -3, z= -3> + +After 60 steps: +pos=<x= 36, y=-10, z= 6>, vel=<x= 5, y= 0, z= 3> +pos=<x=-18, y= 10, z= 9>, vel=<x= -3, y= -7, z= 5> +pos=<x= 8, y=-12, z= -3>, vel=<x= -2, y= 1, z= -7> +pos=<x=-18, y= -8, z= -2>, vel=<x= 0, y= 6, z= -1> + +After 70 steps: +pos=<x=-33, y= -6, z= 5>, vel=<x= -5, y= -4, z= 7> +pos=<x= 13, y= -9, z= 2>, vel=<x= -2, y= 11, z= 3> +pos=<x= 11, y= -8, z= 2>, vel=<x= 8, y= -6, z= -7> +pos=<x= 17, y= 3, z= 1>, vel=<x= -1, y= -1, z= -3> + +After 80 steps: +pos=<x= 30, y= -8, z= 3>, vel=<x= 3, y= 3, z= 0> +pos=<x= -2, y= -4, z= 0>, vel=<x= 4, y=-13, z= 2> +pos=<x=-18, y= -7, z= 15>, vel=<x= -8, y= 2, z= -2> +pos=<x= -2, y= -1, z= -8>, vel=<x= 1, y= 8, z= 0> + +After 90 steps: +pos=<x=-25, y= -1, z= 4>, vel=<x= 1, y= -3, z= 4> +pos=<x= 2, y= -9, z= 0>, vel=<x= -3, y= 13, z= -1> +pos=<x= 32, y= -8, z= 14>, vel=<x= 5, y= -4, z= 6> +pos=<x= -1, y= -2, z= -8>, vel=<x= -3, y= -6, z= -9> + +After 100 steps: +pos=<x= 8, y=-12, z= -9>, vel=<x= -7, y= 3, z= 0> +pos=<x= 13, y= 16, z= -3>, vel=<x= 3, y=-11, z= -5> +pos=<x=-29, y=-11, z= -1>, vel=<x= -3, y= 7, z= 4> +pos=<x= 16, y=-13, z= 23>, vel=<x= 7, y= 1, z= 1> + +Energy after 100 steps: +pot: 8 + 12 + 9 = 29; kin: 7 + 3 + 0 = 10; total: 29 * 10 = 290 +pot: 13 + 16 + 3 = 32; kin: 3 + 11 + 5 = 19; total: 32 * 19 = 608 +pot: 29 + 11 + 1 = 41; kin: 3 + 7 + 4 = 14; total: 41 * 14 = 574 +pot: 16 + 13 + 23 = 52; kin: 7 + 1 + 1 = 9; total: 52 * 9 = 468 +Sum of total energy: 290 + 608 + 574 + 468 = 1940 + +What is the total energy in the system after simulating the moons given in your scan +for 1000 steps? + + diff --git a/src/12/part2 b/src/12/part2 @@ -0,0 +1,50 @@ +--- Part Two --- + +All this drifting around in space makes you wonder about the nature of the universe. Does history +really repeat itself? You're curious whether the moons will ever return to a previous state. + +Determine the number of steps that must occur before all of the moons' +positions and velocities exactly match a previous point in time. + +For example, the first example above takes 2772 steps before they exactly match a previous point in +time; it eventually returns to the initial state: + +After 0 steps: +pos=<x= -1, y= 0, z= 2>, vel=<x= 0, y= 0, z= 0> +pos=<x= 2, y=-10, z= -7>, vel=<x= 0, y= 0, z= 0> +pos=<x= 4, y= -8, z= 8>, vel=<x= 0, y= 0, z= 0> +pos=<x= 3, y= 5, z= -1>, vel=<x= 0, y= 0, z= 0> + +After 2770 steps: +pos=<x= 2, y= -1, z= 1>, vel=<x= -3, y= 2, z= 2> +pos=<x= 3, y= -7, z= -4>, vel=<x= 2, y= -5, z= -6> +pos=<x= 1, y= -7, z= 5>, vel=<x= 0, y= -3, z= 6> +pos=<x= 2, y= 2, z= 0>, vel=<x= 1, y= 6, z= -2> + +After 2771 steps: +pos=<x= -1, y= 0, z= 2>, vel=<x= -3, y= 1, z= 1> +pos=<x= 2, y=-10, z= -7>, vel=<x= -1, y= -3, z= -3> +pos=<x= 4, y= -8, z= 8>, vel=<x= 3, y= -1, z= 3> +pos=<x= 3, y= 5, z= -1>, vel=<x= 1, y= 3, z= -1> + +After 2772 steps: +pos=<x= -1, y= 0, z= 2>, vel=<x= 0, y= 0, z= 0> +pos=<x= 2, y=-10, z= -7>, vel=<x= 0, y= 0, z= 0> +pos=<x= 4, y= -8, z= 8>, vel=<x= 0, y= 0, z= 0> +pos=<x= 3, y= 5, z= -1>, vel=<x= 0, y= 0, z= 0> + +Of course, the universe might last for a very long time before repeating. Here's a +copy of the second example from above: + +<x=-8, y=-10, z=0> +<x=5, y=5, z=10> +<x=2, y=-7, z=3> +<x=9, y=-8, z=-3> + +This set of initial positions takes 4686774924 steps before it repeats a previous state! Clearly, +you might need to find a more efficient way to simulate the universe. + +How many steps does it take to reach the first state that exactly matches a previous +state? + + diff --git a/src/12/test.input b/src/12/test.input @@ -0,0 +1,4 @@ +<x=-8, y=-10, z=0> +<x=5, y=5, z=10> +<x=2, y=-7, z=3> +<x=9, y=-8, z=-3> diff --git a/src/12/test.input2 b/src/12/test.input2 @@ -0,0 +1,4 @@ +<x=-1, y=0, z=2> +<x=2, y=-10, z=-7> +<x=4, y=-8, z=8> +<x=3, y=5, z=-1>