#include #include #include #include #include #include #include #include typedef enum { ASSIGN, AND, OR, LSHIFT, RSHIFT, NOT } Gate; typedef struct { char l_operand[3]; char r_operand[3]; Gate gate; bool assigned; uint16_t value; } Wire; /* hash: for single character strings, convert the character to its natural index. * for two character strings, treat the string as a base 26 number. * e.g., a -> 0, b -> 1, ..., z -> 25, aa -> 26, ..., etc. */ int32_t hash(char *str) { int32_t length = strlen(str); if (length == 1) { return str[0] - 'a'; } else if (length == 2) { return 26 * ((str[0] - 'a') + 1) + (str[1] - 'a'); } else { return -1; } } // is_int: return 1 if the string argument is an integer; 0 otherwise. int32_t is_int(char *str) { while (isspace((unsigned char)*str)) str++; if (*str == '\0') return 0; char *endptr; errno = 0; int64_t val = strtol(str, &endptr, 10); if (endptr == str || ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE)) { return 0; } while (isspace((unsigned char)*endptr)) endptr++; if (*endptr != '\0') return 0; return 1; } // get_value: recursively determine the value of the Wire given its name. int32_t get_value(Wire *wire, char *wire_name) { if (is_int(wire_name)) { return atoi(wire_name); } uint32_t index = hash(wire_name); if (wire[index].assigned == true) { return wire[index].value; } uint16_t l_operand, r_operand; if (wire[index].l_operand[0] != '\0') l_operand = get_value(wire, wire[index].l_operand); if (wire[index].r_operand[0] != '\0') r_operand = get_value(wire, wire[index].r_operand); switch(wire[index].gate) { case ASSIGN: wire[index].assigned = true; return wire[index].value = r_operand; break; case AND: wire[index].assigned = true; return wire[index].value = l_operand & r_operand; break; case OR: wire[index].assigned = true; return wire[index].value = l_operand | r_operand; break; case LSHIFT: wire[index].assigned = true; return wire[index].value = l_operand << r_operand; break; case RSHIFT: wire[index].assigned = true; return wire[index].value = l_operand >> r_operand; break; case NOT: wire[index].assigned = true; return wire[index].value = ~r_operand; break; } //bad gate perror("get_value: bad gate."); return -1; } // process: insert each wire definition (i.e., instruction) into the Wire array. void process(Wire *wire, char *left, char *right) { uint32_t index = hash(right); if (strstr(left, "AND") != NULL) { sscanf(left, "%s AND %s", wire[index].l_operand, wire[index].r_operand); wire[index].gate = AND; } else if (strstr(left, "OR") != NULL) { sscanf(left, "%s OR %s", wire[index].l_operand, wire[index].r_operand); wire[index].gate = OR; } else if(strstr(left, "LSHIFT") != NULL) { sscanf(left, "%s LSHIFT %s", wire[index].l_operand, wire[index].r_operand); wire[index].gate = LSHIFT; } else if (strstr(left, "RSHIFT") != NULL) { sscanf(left, "%s RSHIFT %s", wire[index].l_operand, wire[index].r_operand); wire[index].gate = RSHIFT; } else if (strstr(left, "NOT") != NULL) { sscanf(left, "NOT %s", wire[index].r_operand); wire[index].gate = NOT; } else if (!is_int(left)) { //test for definitions like "x -> y" strcpy(wire[index].r_operand, left); uint64_t len = strlen(wire[index].r_operand); //remove trailing whitespace for (uint64_t i = len - 1; i >= 0; i--) { if (isspace((unsigned char)wire[index].r_operand[i])) { wire[index].r_operand[i] = '\0'; } else { break; } } wire[index].gate = ASSIGN; } else { //if we end up here, the definition must be like "123 -> x" wire[index].value = atoi(left); wire[index].assigned = true; } } int main() { FILE *file = fopen("input2", "r"); if (file == NULL) { perror("main: error opening file."); return 1; } uint16_t index = 26*26; Wire wire[index]; char left[20]; //20 is suffcient to hold the longest possible definition. char right[3]; //3 is sufficient for any one or two character wire name. for (uint16_t i = 0; i < index; i++) { wire[i].l_operand[0] = '\0'; wire[i].r_operand[0] = '\0'; wire[i].gate = ASSIGN; wire[i].assigned = false; wire[i].value = 0; } while (fscanf(file, "%20[a-zA-Z0-9 ] -> %s\n", left, right) != EOF) { process(wire, left, right); } fclose(file); printf("a: %hu\n", get_value(wire, "a")); return 0; }