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