#include "aoc.h" #include "allocator.h" #include "iccmp.h" #include "hmap.h" #include "maxint.h" #include "util.h" #include #include #include #include #include #include const char *tiles = " +#=o"; struct vec2 { int x, y; }; enum { EMPTY, WALL, BLOCK, PADDLE, BALL }; uint32_t hmap_pos_hash(struct hmap_key key) { const struct vec2 *pos = key.p; uint32_t hash; hash = ((uint32_t) pos->x & 0xffffffff); hash = (hash << 8) ^ ((uint32_t) pos->y & 0xffffffff); return hash; } bool hmap_pos_keycmp(struct hmap_key k1, struct hmap_key k2) { const struct vec2 *v1 = k1.p, *v2 = k2.p; return v1->x == v2->x && v1->y == v2->y; } void print_map(struct hmap *map) { struct hmap_iter iter; const struct vec2 *ppos; struct vec2 size, pos; struct hmap_link *link; char tile; int x, y; size.x = size.y = 1; for (HMAP_ITER(map, iter)) { ppos = iter.link->key.p; size.x = MAX(size.x, ppos->x + 1); size.y = MAX(size.y, ppos->y + 1); } for (y = 0; y < size.y; y++) { for (x = 0; x < size.x; x++) { pos.x = x; pos.y = y; link = hmap_get(map, (struct hmap_key) {.p = &pos}); if (link) tile = tiles[link->value.i]; else tile = tiles[EMPTY]; aoc_debug("%c", tile); } aoc_debug("\n"); } aoc_debug("\n"); } void part1(void) { struct hmap_link **link; struct hmap_iter iter; struct hmap map; struct icc icc; struct vec2 pos; int outind, outvec[3]; int rc, count; void *key; hmap_init(&map, 100, hmap_pos_hash, hmap_pos_keycmp, &stdlib_strict_heap_allocator); icc_init(&icc); icc_parse_inst(&icc, aoc.input, aoc.input_size); outind = 0; while (icc.state != ICC_HALT) { icc_step_inst(&icc); switch (icc.state) { case ICC_OUTPUT: outvec[outind] = (int) mi_cast_ul(&icc.out); outind = (outind + 1) % 3; if (!outind) { pos.x = outvec[0]; pos.y = outvec[1]; link = hmap_link_pos(&map, (struct hmap_key) {.p = &pos}); if (*link) { (*link)->value.i = outvec[2]; } else { key = memdup(&pos, sizeof(pos)); *link = hmap_link_alloc(&map, (struct hmap_key) {.p = key}, (struct hmap_val) {.i = outvec[2]}, &rc); assert(*link); } } break; } } count = 0; for (HMAP_ITER(&map, iter)) { if (iter.link->value.i == BLOCK) count += 1; } aoc.answer = aprintf("%i", count); aoc.solution = "329"; for (HMAP_ITER(&map, iter)) free(iter.link->key._p); hmap_deinit(&map); icc_deinit(&icc); } void part2(void) { struct hmap_link **link; struct hmap_iter iter; struct hmap map; struct maxint addr = MI_INIT; struct maxint val = MI_INIT; mi_ul addr_ul, val_ul; struct icc icc; struct vec2 pos, ball, paddle; int outind, outvec[3]; int rc, score, dir; void *key; hmap_init(&map, 100, hmap_pos_hash, hmap_pos_keycmp, &stdlib_strict_heap_allocator); icc_init(&icc); icc_parse_inst(&icc, aoc.input, aoc.input_size); icc_write(&icc, mi_imm(&addr, &addr_ul, 0, MI_POS), mi_imm(&val, &val_ul, 2, MI_POS)); score = 0; outind = 0; while (icc.state != ICC_HALT) { icc_step_inst(&icc); switch (icc.state) { case ICC_INPUT: if (paddle.x < ball.x) { mi_setv(&icc.in, 1, MI_POS); dir = 1; } else if (paddle.x > ball.x) { mi_setv(&icc.in, 1, MI_NEG); dir = -1; } else { mi_setv(&icc.in, 0, MI_POS); dir = 0; } if (aoc.debug) { aoc_debug("Score: %i, Ball: %i %i, Paddle: %i %i, Dir: %i\n", score, ball.x, ball.y, paddle.x, paddle.y, dir); print_map(&map); } break; case ICC_OUTPUT: outvec[outind] = (int) mi_cast_ul(&icc.out) * (icc.out.sign == MI_POS ? 1 : -1); outind = (outind + 1) % 3; if (!outind) { pos.x = outvec[0]; pos.y = outvec[1]; if (pos.x == -1 && pos.y == 0) { score = outvec[2]; } else { link = hmap_link_pos(&map, (struct hmap_key) {.p = &pos}); if (*link) { (*link)->value.i = outvec[2]; } else { key = memdup(&pos, sizeof(pos)); *link = hmap_link_alloc(&map, (struct hmap_key) {.p = key}, (struct hmap_val) {.i = outvec[2]}, &rc); assert(*link); } if (outvec[2] == BALL) { ball.x = pos.x; ball.y = pos.y; } else if (outvec[2] == PADDLE) { paddle.x = pos.x; paddle.y = pos.y; } } } break; } } aoc.answer = aprintf("%i", score); aoc.solution = "15973"; for (HMAP_ITER(&map, iter)) free(iter.link->key._p); hmap_deinit(&map); icc_deinit(&icc); }