#include #include #include #include #define BUFFER_SIZE 64 #define MAX_MONKEYS 4096 enum monkeyType { CONSTANT, ARITHMETIC }; enum operand { ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION }; typedef struct monkey { char name[4]; char leftOperandName[4]; char rightOperandName[4]; enum monkeyType type; struct monkey *leftOperand; struct monkey *rightOperand; enum operand op; long long number; int hasValue; } MONKEY; long long getNumber(MONKEY); int main() { char buf[BUFFER_SIZE], *p, c; memset(buf, 0, BUFFER_SIZE); p = buf; MONKEY monkeys[MAX_MONKEYS], root; memset(monkeys, 0, MAX_MONKEYS * sizeof(MONKEY)); int monkey_count = 0; char op; while ((c = getchar()) != EOF) { *p++ = c; if (c == '\n') { if (sscanf(buf, "%c%c%c%c: %c%c%c%c %c %c%c%c%c", &monkeys[monkey_count].name[0], &monkeys[monkey_count].name[1], &monkeys[monkey_count].name[2], &monkeys[monkey_count].name[3], &monkeys[monkey_count].leftOperandName[0], &monkeys[monkey_count].leftOperandName[1], &monkeys[monkey_count].leftOperandName[2], &monkeys[monkey_count].leftOperandName[3], &op, &monkeys[monkey_count].rightOperandName[0], &monkeys[monkey_count].rightOperandName[1], &monkeys[monkey_count].rightOperandName[2], &monkeys[monkey_count].rightOperandName[3]) == 13) { switch (op) { case '+': monkeys[monkey_count].op = ADDITION; break; case '-': monkeys[monkey_count].op = SUBTRACTION; break; case '*': monkeys[monkey_count].op = MULTIPLICATION; break; case '/': monkeys[monkey_count].op = DIVISION; break; } monkeys[monkey_count].type = ARITHMETIC; } else { sscanf(buf, "%c%c%c%c: %lli", &monkeys[monkey_count].name[0], &monkeys[monkey_count].name[1], &monkeys[monkey_count].name[2], &monkeys[monkey_count].name[3], &monkeys[monkey_count].number); monkeys[monkey_count].type = CONSTANT; monkeys[monkey_count].hasValue = 1; } monkey_count++; memset(buf, 0, BUFFER_SIZE); p = buf; } } // Change names to pointers in monkeys for (int i = 0; i < monkey_count; i++) { if (monkeys[i].type == ARITHMETIC) { for (int j = 0; j < monkey_count; j++) { if (monkeys[i].leftOperandName[0] == monkeys[j].name[0] && monkeys[i].leftOperandName[1] == monkeys[j].name[1] && monkeys[i].leftOperandName[2] == monkeys[j].name[2] && monkeys[i].leftOperandName[3] == monkeys[j].name[3]) { monkeys[i].leftOperand = &monkeys[j]; } if (monkeys[i].rightOperandName[0] == monkeys[j].name[0] && monkeys[i].rightOperandName[1] == monkeys[j].name[1] && monkeys[i].rightOperandName[2] == monkeys[j].name[2] && monkeys[i].rightOperandName[3] == monkeys[j].name[3]) { monkeys[i].rightOperand = &monkeys[j]; } } } } // Get the shouted number // // Find 'root' for (int i = 0; i < monkey_count; i++) { if (monkeys[i].name[0] == 'r' && monkeys[i].name[1] == 'o' && monkeys[i].name[2] == 'o' && monkeys[i].name[3] == 't') {\ root = monkeys[i]; } } printf("%lli\n", getNumber(root)); // Good old bruteforce for part 2 // Find human MONKEY *human; for (int i = 0; i < monkey_count; i++) { if (monkeys[i].name[0] == 'h' && monkeys[i].name[1] == 'u' && monkeys[i].name[2] == 'm' && monkeys[i].name[3] == 'n') {\ human = &monkeys[i]; } } long long myNumber = 3759566892641; human->hasValue = 1; human->type = CONSTANT; human->number = myNumber; int found = 0; printf("%lli, %lli\n", getNumber(*root.leftOperand), getNumber(*root.rightOperand)); printf("%lli\n", myNumber); // do { // // Reset all arithmetic monkeys // for (int i = 0; i < monkey_count; i++) { // if (monkeys[i].type == ARITHMETIC) { // monkeys[i].hasValue = 0; // } // } // human->number = myNumber++; // long long left = getNumber(*root.leftOperand); // // Reset all arithmetic monkeys // for (int i = 0; i < monkey_count; i++) { // if (monkeys[i].type == ARITHMETIC) { // monkeys[i].hasValue = 0; // } // } // long long right = getNumber(*root.rightOperand); // // found = left == right; // } while (!found); // // printf("%lli\n", myNumber-1); } long long getNumber(MONKEY monkey) { // If previuosly calculated or constant if (monkey.hasValue == 1) { return monkey.number; } long long result = 0; switch (monkey.op) { case ADDITION: result = getNumber(*monkey.leftOperand) + getNumber(*monkey.rightOperand); break; case SUBTRACTION: result = getNumber(*monkey.leftOperand) - getNumber(*monkey.rightOperand); break; case MULTIPLICATION: result = getNumber(*monkey.leftOperand) * getNumber(*monkey.rightOperand); break; case DIVISION: result = getNumber(*monkey.leftOperand) / getNumber(*monkey.rightOperand); break; } monkey.hasValue = 1; monkey.number = result; return result; }