205 lines
6.1 KiB
C
205 lines
6.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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);
|
|
}
|