#include #include #include #define LINE_MAX_LENGTH 256 #define MAX_CONNECTED 16 #define MAX_MODULES 128 #define MAX_QUEUE 1024 typedef enum module_type { FLIPFLOP, CONJUNCTION, BROADCAST, } module_type_t; typedef struct module { module_type_t type; char name[16]; int name_length; int state; struct module *inputs[MAX_CONNECTED]; int input_memory[MAX_CONNECTED]; int input_num; struct module *outputs[MAX_CONNECTED]; int output_num; char output_names[MAX_CONNECTED][16]; int output_name_lengths[MAX_CONNECTED]; } module_t; typedef struct signal { int value; module_t *module; module_t *source; } signal_t; int main() { char *p, *buf, c, *q; buf = (char *)malloc(LINE_MAX_LENGTH); memset(buf, 0, LINE_MAX_LENGTH); p = buf; module_t *modules = (module_t*)malloc(MAX_MODULES * sizeof(module_t)); memset(modules, 0, MAX_MODULES * sizeof(module_t)); int modules_num = 0; while ((c = getchar()) != EOF) { *p++ = c; if (c == '\n') { p = buf; if (*p == '%' || *p == '&' || *p == '#') { switch (*p) { case '%': modules[modules_num].type = FLIPFLOP; break; case '&': modules[modules_num].type = CONJUNCTION; break; } p++; } else { modules[modules_num].type = BROADCAST; } q = p; while(*p != ' ') p++; strncpy(modules[modules_num].name, q, p - q); modules[modules_num].name_length = p - q; p++; while(*p != ' ') p++; p++; // Read outputs while(*p != '\0') { q = p; while (*p != '\n' && *p != ',') p++; strncpy(modules[modules_num].output_names[modules[modules_num].output_num], q, p - q); modules[modules_num].output_name_lengths[modules[modules_num].output_num] = p - q; modules[modules_num].output_num++; p+=2; } modules_num++; memset(buf, 0, LINE_MAX_LENGTH); p = buf; } } // Link up modules for (int i = 0; i < modules_num; i++) { // Link outputs int found = 0; for (int j = 0; j < modules[i].output_num; j++) { for (int k = 0; k < modules_num; k++) { if (!strcmp(modules[k].name, modules[i].output_names[j])) { modules[i].outputs[j] = &modules[k]; found++; break; } } } // Link inputs for (int j = 0; j < modules_num; j++) { for (int k = 0; k < modules[j].output_num; k++) { if (!strcmp(modules[i].name, modules[j].output_names[k])) { modules[i].inputs[modules[i].input_num] = &modules[j]; modules[i].input_num++; break; } } } } // Find start module_t *broadcast; for (int i = 0; i < modules_num; i++) { if (modules[i].type == BROADCAST) { broadcast = &modules[i]; break; } } signal_t signal_queue[MAX_QUEUE]; unsigned long low_pulses = 0, high_pulses = 0; int turned_on = 0; #ifdef PART2 for(unsigned long l = 0; !turned_on; l++) { #else for (unsigned long l = 0; l < 1000; l++) { #endif memset(signal_queue, 0, MAX_QUEUE * sizeof(signal_t)); int signal_queue_length = 1; signal_queue[0].value = 0; signal_queue[0].module = broadcast; signal_queue[0].source = NULL; while (signal_queue_length > 0) { // Pop first signal_t signal = signal_queue[0]; for (int i = 0; i < signal_queue_length - 1; i++) { memcpy(&signal_queue[i], &signal_queue[i+1], sizeof(signal_t)); } signal_queue_length--; int output; if (signal.value) { high_pulses++; } else { low_pulses++; } if (signal.module == NULL) { if (signal.value == 0) { printf("Machine turn on: %lu\n", l+1); turned_on = 1; break; } continue; } switch (signal.module->type) { case FLIPFLOP: if (signal.value == 0) { signal.module->state = !signal.module->state; output = signal.module->state; } else { output = -1; } break; case BROADCAST: output = signal.value; break; case CONJUNCTION: // Update input memory for (int i = 0; i < signal.module->input_num; i++) { if (signal.module->inputs[i] == signal.source) { signal.module->input_memory[i] = signal.value; } } int all_high = 1; for (int i = 0; i < signal.module->input_num; i++) { if (signal.module->input_memory[i] == 0) { all_high = 0; break; } } output = !all_high; break; } if (output != -1) { for (int i = 0; i < signal.module->output_num; i++) { signal_queue[signal_queue_length].value = output; signal_queue[signal_queue_length].module = signal.module->outputs[i]; signal_queue[signal_queue_length].source = signal.module; signal_queue_length++; } } } } printf("%lu\n", high_pulses * low_pulses); free(buf); free(modules); }