main.c (4519B)
1#include "aoc.h" 2#include "allocator.h" 3#include "iccmp.h" 4#include "hmap.h" 5#include "maxint.h" 6#include "util.h" 7 8#include <assert.h> 9#include <stdbool.h> 10#include <stddef.h> 11#include <stdint.h> 12#include <stdlib.h> 13#include <stdio.h> 14 15const char *tiles = " +#=o"; 16 17struct vec2 { 18 int x, y; 19}; 20 21enum { 22 EMPTY, 23 WALL, 24 BLOCK, 25 PADDLE, 26 BALL 27}; 28 29uint32_t 30hmap_pos_hash(struct hmap_key key) 31{ 32 const struct vec2 *pos = key.p; 33 uint32_t hash; 34 35 hash = ((uint32_t) pos->x & 0xffffffff); 36 hash = (hash << 8) ^ ((uint32_t) pos->y & 0xffffffff); 37 38 return hash; 39} 40 41bool 42hmap_pos_keycmp(struct hmap_key k1, struct hmap_key k2) 43{ 44 const struct vec2 *v1 = k1.p, *v2 = k2.p; 45 46 return v1->x == v2->x && v1->y == v2->y; 47} 48 49void 50print_map(struct hmap *map) 51{ 52 struct hmap_iter iter; 53 const struct vec2 *ppos; 54 struct vec2 size, pos; 55 struct hmap_link *link; 56 char tile; 57 int x, y; 58 59 size.x = size.y = 1; 60 for (HMAP_ITER(map, iter)) { 61 ppos = iter.link->key.p; 62 size.x = MAX(size.x, ppos->x + 1); 63 size.y = MAX(size.y, ppos->y + 1); 64 } 65 66 for (y = 0; y < size.y; y++) { 67 for (x = 0; x < size.x; x++) { 68 pos.x = x; 69 pos.y = y; 70 link = hmap_get(map, (struct hmap_key) {.p = &pos}); 71 if (link) 72 tile = tiles[link->value.i]; 73 else 74 tile = tiles[EMPTY]; 75 aoc_debug("%c", tile); 76 } 77 aoc_debug("\n"); 78 } 79 80 aoc_debug("\n"); 81} 82 83void 84part1(void) 85{ 86 struct hmap_link **link; 87 struct hmap_iter iter; 88 struct hmap map; 89 struct icc icc; 90 struct vec2 pos; 91 int outind, outvec[3]; 92 int rc, count; 93 void *key; 94 95 hmap_init(&map, 100, hmap_pos_hash, hmap_pos_keycmp, 96 &stdlib_strict_heap_allocator); 97 98 icc_init(&icc); 99 icc_parse_inst(&icc, aoc.input, aoc.input_size); 100 101 outind = 0; 102 while (icc.state != ICC_HALT) { 103 icc_step_inst(&icc); 104 switch (icc.state) { 105 case ICC_OUTPUT: 106 outvec[outind] = (int) mi_cast_ul(&icc.out); 107 outind = (outind + 1) % 3; 108 if (!outind) { 109 pos.x = outvec[0]; 110 pos.y = outvec[1]; 111 link = hmap_link_pos(&map, 112 (struct hmap_key) {.p = &pos}); 113 if (*link) { 114 (*link)->value.i = outvec[2]; 115 } else { 116 key = memdup(&pos, sizeof(pos)); 117 *link = hmap_link_alloc(&map, 118 (struct hmap_key) {.p = key}, 119 (struct hmap_val) {.i = outvec[2]}, 120 &rc); 121 assert(*link); 122 } 123 } 124 break; 125 } 126 } 127 128 count = 0; 129 for (HMAP_ITER(&map, iter)) { 130 if (iter.link->value.i == BLOCK) 131 count += 1; 132 } 133 134 aoc.answer = aprintf("%i", count); 135 aoc.solution = "329"; 136 137 for (HMAP_ITER(&map, iter)) 138 free(iter.link->key._p); 139 hmap_deinit(&map); 140 icc_deinit(&icc); 141} 142 143void 144part2(void) 145{ 146 struct hmap_link **link; 147 struct hmap_iter iter; 148 struct hmap map; 149 struct maxint addr = MI_INIT; 150 struct maxint val = MI_INIT; 151 mi_ul addr_ul, val_ul; 152 struct icc icc; 153 struct vec2 pos, ball, paddle; 154 int outind, outvec[3]; 155 int rc, score, dir; 156 void *key; 157 158 hmap_init(&map, 100, hmap_pos_hash, hmap_pos_keycmp, 159 &stdlib_strict_heap_allocator); 160 161 icc_init(&icc); 162 icc_parse_inst(&icc, aoc.input, aoc.input_size); 163 icc_write(&icc, mi_imm(&addr, &addr_ul, 0, MI_POS), 164 mi_imm(&val, &val_ul, 2, MI_POS)); 165 166 score = 0; 167 outind = 0; 168 while (icc.state != ICC_HALT) { 169 icc_step_inst(&icc); 170 switch (icc.state) { 171 case ICC_INPUT: 172 if (paddle.x < ball.x) { 173 mi_setv(&icc.in, 1, MI_POS); 174 dir = 1; 175 } else if (paddle.x > ball.x) { 176 mi_setv(&icc.in, 1, MI_NEG); 177 dir = -1; 178 } else { 179 mi_setv(&icc.in, 0, MI_POS); 180 dir = 0; 181 } 182 if (aoc.debug) { 183 aoc_debug("Score: %i, Ball: %i %i, Paddle: %i %i, Dir: %i\n", 184 score, ball.x, ball.y, paddle.x, paddle.y, dir); 185 print_map(&map); 186 } 187 break; 188 case ICC_OUTPUT: 189 outvec[outind] = (int) mi_cast_ul(&icc.out) 190 * (icc.out.sign == MI_POS ? 1 : -1); 191 outind = (outind + 1) % 3; 192 if (!outind) { 193 pos.x = outvec[0]; 194 pos.y = outvec[1]; 195 if (pos.x == -1 && pos.y == 0) { 196 score = outvec[2]; 197 } else { 198 link = hmap_link_pos(&map, 199 (struct hmap_key) {.p = &pos}); 200 if (*link) { 201 (*link)->value.i = outvec[2]; 202 } else { 203 key = memdup(&pos, sizeof(pos)); 204 *link = hmap_link_alloc(&map, 205 (struct hmap_key) {.p = key}, 206 (struct hmap_val) {.i = outvec[2]}, 207 &rc); 208 assert(*link); 209 } 210 if (outvec[2] == BALL) { 211 ball.x = pos.x; 212 ball.y = pos.y; 213 } else if (outvec[2] == PADDLE) { 214 paddle.x = pos.x; 215 paddle.y = pos.y; 216 } 217 } 218 } 219 break; 220 } 221 } 222 223 aoc.answer = aprintf("%i", score); 224 aoc.solution = "15973"; 225 226 for (HMAP_ITER(&map, iter)) 227 free(iter.link->key._p); 228 hmap_deinit(&map); 229 icc_deinit(&icc); 230}