aoc-2019-c

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

commit 20c9d752bab453ade281fc814950636577093428
parent 744cb4c6f5e12f84d5a77d8eee69a60c81d53fee
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sun,  2 Apr 2023 10:19:44 -0400

Add day 19

Diffstat:
A19/info.mk | 4++++
A19/input | 2++
A19/main.c | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A19/part1 | 43+++++++++++++++++++++++++++++++++++++++++++
A19/part2 | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcommon/iccmp.c | 29++++++++++++++++++++++++-----
6 files changed, 286 insertions(+), 5 deletions(-)

diff --git a/19/info.mk b/19/info.mk @@ -0,0 +1,4 @@ +19_SRC = 19/main.c common/main.c common/iccmp.c common/aoc.c common/util.c +19_SRC += lib/liballoc/build/liballoc.a lib/libmaxint/build/libmaxint.a +19_SRC += lib/libhmap/build/libhmap.a lib/libdvec/build/libdvec.a +19_HDR = common/aoc.h common/iccmp.h common/util.h diff --git a/19/input b/19/input @@ -0,0 +1,2 @@ +109,424,203,1,21102,11,1,0,1105,1,282,21102,1,18,0,1105,1,259,1201,1,0,221,203,1,21101,0,31,0,1105,1,282,21102,38,1,0,1106,0,259,21001,23,0,2,22101,0,1,3,21101,0,1,1,21102,1,57,0,1105,1,303,2101,0,1,222,21001,221,0,3,20102,1,221,2,21102,259,1,1,21101,80,0,0,1106,0,225,21101,0,111,2,21102,1,91,0,1105,1,303,2102,1,1,223,20101,0,222,4,21102,1,259,3,21102,1,225,2,21102,1,225,1,21101,0,118,0,1105,1,225,20101,0,222,3,21102,148,1,2,21102,1,133,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21102,148,1,0,1106,0,259,2101,0,1,223,20102,1,221,4,21001,222,0,3,21101,0,17,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21101,0,195,0,106,0,109,20207,1,223,2,20102,1,23,1,21102,-1,1,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2102,1,-4,249,22101,0,-3,1,21202,-2,1,2,21202,-1,1,3,21102,1,250,0,1105,1,225,22102,1,1,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2105,1,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,22102,1,-2,-2,109,-3,2106,0,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,21202,-2,1,3,21101,0,343,0,1105,1,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21102,384,1,0,1106,0,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21202,1,1,-4,109,-5,2106,0,0 + diff --git a/19/main.c b/19/main.c @@ -0,0 +1,155 @@ +#include "aoc.h" +#include "iccmp.h" +#include "allocator.h" +#include "dvec_s.h" +#include "util.h" + +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> + +bool +deploy(struct icc *icc, size_t x, size_t y) +{ + int input; + + input = 0; + while (icc->state != ICC_HALT) { + icc_step_inst(icc); + switch (icc->state) { + case ICC_INPUT: + switch (input) { + case 0: + mi_setv(&icc->in, x, MI_POS); + input++; + break; + case 1: + mi_setv(&icc->in, y, MI_POS); + input++; + break; + } + break; + case ICC_OUTPUT: + return mi_cast_ul(&icc->out); + } + } + + assert(false); +} + +void +part1(void) +{ + struct icc icc, save; + size_t x, y; + size_t answer; + bool inbeam; + bool inbeam_p; + size_t beam_start; + + icc_init(&icc); + icc_parse_inst(&icc, aoc.input, aoc.input_size); + + while (icc.state == ICC_RUN) + icc_step_inst(&icc); + assert(icc.state == ICC_INPUT); + + icc_init(&save); + icc_copy(&save, &icc); + + answer = 0; + beam_start = 0; + for (y = 0; y < 50; y++) { + inbeam_p = false; + for (x = beam_start; x < 50; x++) { + icc_copy(&icc, &save); + inbeam = deploy(&icc, x, y); + aoc_debug("%lu %lu %i\n", y, x, inbeam); + if (inbeam && !inbeam_p) + beam_start = x; + if (!inbeam && inbeam_p) + break; + inbeam_p = inbeam; + + answer += inbeam; + } + } + + aoc.answer = aprintf("%lu", answer); + aoc.solution = "141"; + + icc_deinit(&icc); +} + +void +part2(void) +{ + const size_t sqw = 100, sqh = 100; + struct icc icc, save; + struct dvec ends; + size_t x, y; + size_t answer; + size_t beam_start; + size_t beam_end; + size_t *end; + bool inbeam; + + icc_init(&icc); + icc_parse_inst(&icc, aoc.input, aoc.input_size); + + while (icc.state == ICC_RUN) + icc_step_inst(&icc); + assert(icc.state == ICC_INPUT); + + icc_init(&save); + icc_copy(&save, &icc); + + dvec_init(&ends, sizeof(size_t), 10, &stdlib_strict_heap_allocator); + + answer = 0; + + beam_start = beam_end = 0; + for (y = 0; ; y++) { + inbeam = false; + for (x = beam_start; !inbeam; x++) { + if (x > beam_start + 10) { + aoc_debug("SKIP %lu\n", y); + end = dvec_add_slot(&ends); + *end = 0; + goto skip; + } + icc_copy(&icc, &save); + inbeam = deploy(&icc, x, y); + } + beam_start = x - 1; + + inbeam = true; + if (beam_end < beam_start) beam_end = beam_start + 1; + for (x = beam_end; inbeam; x++) { + icc_copy(&icc, &save); + inbeam = deploy(&icc, x, y); + } + beam_end = x - 1; + + end = dvec_add_slot(&ends); + *end = beam_end; + + if (y >= sqh - 1) { + end = dvec_at(&ends, y - (sqh - 1)); + if (*end >= beam_start + sqw) { + answer = beam_start * 10000 + (y - (sqh - 1)); + goto exit; + } + } + +skip: + aoc_debug("%lu %lu %lu\n", y, beam_start, beam_end); + } + +exit: + aoc.answer = aprintf("%lu", answer); + + dvec_deinit(&ends); + icc_deinit(&save); + icc_deinit(&icc); +} diff --git a/19/part1 b/19/part1 @@ -0,0 +1,43 @@ +--- Day 19: Tractor Beam --- + +Unsure of the state of Santa's ship, you borrowed the tractor beam technology from Triton. Time to +test it out. + +When you're safely away from anything else, you activate the tractor beam, but nothing happens. +It's hard to tell whether it's working if there's nothing to use it on. Fortunately, your ship's +drone system can be configured to deploy a drone to specific coordinates and then check whether it's +being pulled. There's even an Intcode program (your puzzle input) that gives you access to the drone +system. + +The program uses two input instructions to request the X and Y position to which the drone should be +deployed. Negative numbers are invalid and will confuse the drone; all numbers should be zero or +positive. + +Then, the program will output whether the drone is stationary (0) or being pulled by something (1). +For example, the coordinate X=0, Y=0 is directly in front of the tractor beam emitter, so the drone +control program will always report 1 at that location. + +To better understand the tractor beam, it is important to get a good picture of the beam itself. For +example, suppose you scan the 10x10 grid of points closest to the emitter: + + X + 0-> 9 + 0#......... + |.#........ + v..##...... + ...###.... + ....###... +Y .....####. + ......#### + ......#### + .......### + 9........## + +In this example, the number of points affected by the tractor beam in the 10x10 area closest to the +emitter is 27. + +However, you'll need to scan a larger area to understand the shape of the beam. How many points are +affected by the tractor beam in the 50x50 area closest to the emitter? (For each of X and Y, this +will be 0 through 49.) + + diff --git a/19/part2 b/19/part2 @@ -0,0 +1,58 @@ +--- Part Two --- + +You aren't sure how large Santa's ship is. You aren't even sure if you'll need to use this thing on +Santa's ship, but it doesn't hurt to be prepared. You figure Santa's ship might fit in a 100x100 +square. + +The beam gets wider as it travels away from the emitter; you'll need to be a minimum distance away +to fit a square of that size into the beam fully. (Don't rotate the square; it should be aligned to +the same axes as the drone grid.) + +For example, suppose you have the following tractor beam readings: + +#....................................... +.#...................................... +..##.................................... +...###.................................. +....###................................. +.....####............................... +......#####............................. +......######............................ +.......#######.......................... +........########........................ +.........#########...................... +..........#########..................... +...........##########................... +...........############................. +............############................ +.............#############.............. +..............##############............ +...............###############.......... +................###############......... +................#################....... +.................########OOOOOOOOOO..... +..................#######OOOOOOOOOO#.... +...................######OOOOOOOOOO###.. +....................#####OOOOOOOOOO##### +.....................####OOOOOOOOOO##### +.....................####OOOOOOOOOO##### +......................###OOOOOOOOOO##### +.......................##OOOOOOOOOO##### +........................#OOOOOOOOOO##### +.........................OOOOOOOOOO##### +..........................############## +..........................############## +...........................############# +............................############ +.............................########### + +In this example, the 10x10 square closest to the emitter that fits entirely within the tractor beam +has been marked O. Within it, the point closest to the emitter (the only highlighted O) is at X=25, +Y=20. + +Find the 100x100 square closest to the emitter that fits entirely within the tractor beam; within +that square, find the point closest to the emitter. What value do you get if you take that point's +X coordinate, multiply it by 10000, then add the point's Y coordinate? (In the example above, this +would be 250020.) + + diff --git a/common/iccmp.c b/common/iccmp.c @@ -105,12 +105,33 @@ icc_deinit(struct icc *icc) void icc_copy(struct icc *dst, struct icc *src) { + struct hmap_iter hmap_iter; + struct maxint *key, *value; + dst->state = src->state; mi_set(&dst->rip, &src->rip); mi_set(&dst->base, &src->base); mi_set(&dst->in, &src->in); mi_set(&dst->out, &src->out); - hmap_copy(&dst->instructions, &src->instructions); + + for (HMAP_ITER(&dst->instructions, &hmap_iter)) { + mi_deinit(hmap_iter.link->key._p); + free(hmap_iter.link->key._p); + mi_deinit(hmap_iter.link->value._p); + free(hmap_iter.link->value._p); + } + hmap_clear(&dst->instructions); + + for (HMAP_ITER(&src->instructions, &hmap_iter)) { + key = malloc(sizeof(struct maxint)); + mi_init(key); + mi_set(key, hmap_iter.link->key.p); + value = malloc(sizeof(struct maxint)); + mi_init(value); + mi_set(value, hmap_iter.link->value.p); + hmap_add(&dst->instructions, (struct hmap_key) {.p = key}, + (struct hmap_val) {.p = value}); + } } void @@ -144,13 +165,11 @@ icc_parse_inst(struct icc *icc, const char *str, size_t len) key = malloc(sizeof(struct maxint)); assert(key != NULL); - - val = malloc(sizeof(struct maxint)); - assert(val != NULL); - mi_init(key); mi_setv(key, (mi_ul) rip, MI_POS); + val = malloc(sizeof(struct maxint)); + assert(val != NULL); mi_init(val); mi_setv(val, (mi_ul) ABS(v), v >= 0 ? MI_POS : MI_NEG);