main.c (5120B)
1#include "aoc.h" 2#include "iccmp.h" 3#include "list.h" 4#include "maxint.h" 5#include "util.h" 6 7#include <assert.h> 8#include <stdbool.h> 9#include <stdint.h> 10#include <stdlib.h> 11 12struct packet { 13 struct maxint x, y; 14 size_t src_ip, dst_ip; 15 16 struct list_link link; 17}; 18 19static struct packet nat_packet; 20static bool nat_avail = false; 21 22void 23feed_input(struct icc *icc, mi_ul imm) 24{ 25 while (icc->state != ICC_HALT) { 26 if (icc->state == ICC_INPUT) { 27 mi_setv(&icc->in, imm, MI_POS); 28 icc_step_inst(icc); 29 break; 30 } 31 icc_step_inst(icc); 32 } 33} 34 35void 36free_packet(void *p) 37{ 38 struct packet *packet; 39 40 packet = p; 41 mi_deinit(&packet->x); 42 mi_deinit(&packet->y); 43 free(packet); 44} 45 46bool 47recv_packet(struct list *queues, struct maxint *val, int state, size_t ip) 48{ 49 static struct packet *packet; 50 struct list_link *link; 51 char buf[64]; 52 53 aoc_debug("INPUT %i\n", ip); 54 if (list_empty(&queues[ip])) { 55 mi_setv(val, 1, MI_NEG); 56 return false; 57 } else { 58 switch(state) { 59 case 0: 60 link = list_front(&queues[ip]); 61 packet = LIST_UPCAST(link, struct packet, link); 62 aoc_debug("%i <- %i (", packet->src_ip, packet->dst_ip); 63 mi_dec(&packet->x, buf, sizeof(buf), 0); 64 aoc_debug("%s, ", buf); 65 mi_dec(&packet->y, buf, sizeof(buf), 0); 66 aoc_debug("%s)\n", buf); 67 mi_set(val, &packet->x); 68 break; 69 case 1: 70 mi_set(val, &packet->y); 71 list_link_pop(&packet->link); 72 free_packet(packet); 73 break; 74 } 75 return true; 76 } 77} 78 79void 80send_packet(struct list *queues, struct maxint *val, int state, size_t ip) 81{ 82 static struct packet *packet; 83 size_t dst; 84 char buf[64]; 85 86 aoc_debug("OUTPUT %i\n", ip); 87 switch (state) { 88 case 0: 89 dst = (size_t) mi_cast_ul(val); 90 if (dst == 255) { 91 packet = &nat_packet; 92 } else { 93 packet = malloc(sizeof(struct packet)); 94 mi_init(&packet->x); 95 mi_init(&packet->y); 96 } 97 packet->src_ip = ip; 98 packet->dst_ip = dst; 99 packet->link = LIST_LINK_INIT; 100 break; 101 case 1: 102 mi_set(&packet->x, val); 103 break; 104 case 2: 105 mi_set(&packet->y, val); 106 if (packet->dst_ip != 255) { 107 assert(packet->dst_ip < 50); 108 list_insert_back(&queues[packet->dst_ip], &packet->link); 109 } else { 110 nat_avail = true; 111 } 112 aoc_debug("%i <- %i (", packet->dst_ip, packet->src_ip); 113 mi_dec(&packet->x, buf, sizeof(buf), 0); 114 aoc_debug("%s, ", buf); 115 mi_dec(&packet->y, buf, sizeof(buf), 0); 116 aoc_debug("%s)\n", buf); 117 break; 118 } 119} 120 121bool 122nic_tick(struct icc *icc, struct list *queues, size_t ip) 123{ 124 int out_state, in_state; 125 bool idle, done; 126 127 done = false; 128 idle = true; 129 in_state = 0; 130 out_state = 0; 131 while (!done && icc->state != ICC_HALT) { 132 switch (icc->state) { 133 case ICC_INPUT: 134 idle &= !recv_packet(queues, &icc->in, in_state, ip); 135 in_state = (in_state + 1) % 2; 136 if (!in_state) done = true; 137 break; 138 case ICC_OUTPUT: 139 send_packet(queues, &icc->out, out_state, ip); 140 out_state = (out_state + 1) % 3; 141 idle = false; 142 break; 143 defualt: 144 assert(icc->state == ICC_RUN); 145 } 146 icc_step_inst(icc); 147 } 148 assert(in_state == 0 && out_state == 0); 149 150 return idle; 151} 152 153void 154part1(void) 155{ 156 struct list queues[50]; 157 struct icc icc[50]; 158 char buf[64]; 159 size_t i; 160 161 for (i = 0; i < 50; i++) { 162 list_init(&queues[i]); 163 icc_init(&icc[i]); 164 icc_parse_inst(&icc[i], aoc.input, aoc.input_size); 165 feed_input(&icc[i], (mi_ul) i); 166 } 167 168 mi_init(&nat_packet.x); 169 mi_setv(&nat_packet.x, 0, MI_POS); 170 mi_init(&nat_packet.y); 171 mi_setv(&nat_packet.y, 0, MI_POS); 172 173 while (!nat_avail) { 174 aoc_debug("-- TICK --\n"); 175 for (i = 0; i < 50; i++) 176 nic_tick(&icc[i], queues, i); 177 } 178 179 mi_dec(&nat_packet.y, buf, sizeof(buf), 0); 180 aoc.answer = aprintf("%s", buf); 181 aoc.solution = "20225"; 182 183 mi_deinit(&nat_packet.x); 184 mi_deinit(&nat_packet.y); 185 for (i = 0; i < 50; i++) { 186 list_free_items(&queues[i], free_packet, 187 LIST_OFFSET(struct packet, link)); 188 icc_deinit(&icc[i]); 189 } 190} 191 192void 193part2(void) 194{ 195 struct list queues[256]; 196 struct icc icc[50]; 197 struct packet *packet; 198 size_t answer; 199 size_t last; 200 bool idle; 201 size_t i; 202 203 for (i = 0; i < 50; i++) { 204 list_init(&queues[i]); 205 icc_init(&icc[i]); 206 icc_parse_inst(&icc[i], aoc.input, aoc.input_size); 207 feed_input(&icc[i], (mi_ul) i); 208 } 209 210 mi_init(&nat_packet.x); 211 mi_setv(&nat_packet.x, 0, MI_POS); 212 mi_init(&nat_packet.y); 213 mi_setv(&nat_packet.y, 0, MI_POS); 214 215 last = SIZE_MAX; 216 while (1) { 217 aoc_debug("-- TICK --\n"); 218 219 idle = true; 220 for (i = 0; i < 50; i++) 221 idle &= nic_tick(&icc[i], queues, i); 222 223 if (idle) { 224 assert(nat_avail); 225 packet = malloc(sizeof(struct packet)); 226 mi_init(&packet->x); 227 mi_set(&packet->x, &nat_packet.x); 228 mi_init(&packet->y); 229 mi_set(&packet->y, &nat_packet.y); 230 packet->dst_ip = nat_packet.dst_ip; 231 packet->src_ip = nat_packet.src_ip; 232 packet->link = LIST_LINK_INIT; 233 list_insert_back(&queues[0], &packet->link); 234 235 if (mi_cast_ul(&packet->y) == last) { 236 answer = last; 237 break; 238 } 239 last = mi_cast_ul(&packet->y); 240 241 } 242 } 243 244 aoc.answer = aprintf("%lu", answer); 245 aoc.solution = "14348"; 246 247 mi_deinit(&nat_packet.x); 248 mi_deinit(&nat_packet.y); 249 for (i = 0; i < 50; i++) { 250 list_free_items(&queues[i], free_packet, 251 LIST_OFFSET(struct packet, link)); 252 icc_deinit(&icc[i]); 253 } 254}