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}