Day17
This commit is contained in:
BIN
day17/c/day17
Executable file
BIN
day17/c/day17
Executable file
Binary file not shown.
179
day17/c/day17.c
Normal file
179
day17/c/day17.c
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define CHARS_MAX 128
|
||||||
|
#define MAX_INSTRUCTIONS 128
|
||||||
|
|
||||||
|
#define BIT_JUMPED 0
|
||||||
|
|
||||||
|
enum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
REGISTERS_LEN
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ADV,
|
||||||
|
BXL,
|
||||||
|
BST,
|
||||||
|
JNZ,
|
||||||
|
BXC,
|
||||||
|
OUT,
|
||||||
|
BDV,
|
||||||
|
CDV
|
||||||
|
};
|
||||||
|
|
||||||
|
void execute(uint64_t registers[REGISTERS_LEN], uint8_t *instructions, uint32_t *pc, uint8_t *status, char *output_buffer, int *buf_len);
|
||||||
|
uint64_t combo(uint64_t registers[REGISTERS_LEN], uint8_t operand);
|
||||||
|
uint64_t revert(uint8_t *instructions_inverted, uint8_t *instructions, uint32_t instruction_count, uint64_t current_A, uint32_t i, int print_register);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *p, *buf, c;
|
||||||
|
|
||||||
|
buf = calloc(CHARS_MAX, sizeof(char));
|
||||||
|
p = buf;
|
||||||
|
|
||||||
|
uint64_t registers[3];
|
||||||
|
int reading_register = 0, operand = 0;
|
||||||
|
uint8_t *instructions = calloc(MAX_INSTRUCTIONS, sizeof(instructions[0]));
|
||||||
|
uint32_t instruction_count = 0;
|
||||||
|
|
||||||
|
while ((c = getchar()) != EOF) {
|
||||||
|
if (reading_register < 3) {
|
||||||
|
*p++ = c;
|
||||||
|
if (c != '\n') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
while(*p++ != ':');
|
||||||
|
p++;
|
||||||
|
sscanf(p, "%li", ®isters[reading_register++]);
|
||||||
|
|
||||||
|
memset(buf, 0, CHARS_MAX);
|
||||||
|
p = buf;
|
||||||
|
} else {
|
||||||
|
if (c < 48 || c > 57) continue;
|
||||||
|
uint8_t num = c - 48;
|
||||||
|
instructions[instruction_count++] = num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pc = 0;
|
||||||
|
uint8_t status = 0;
|
||||||
|
int buf_len = 0;
|
||||||
|
while (pc < instruction_count) {
|
||||||
|
execute(registers, instructions, &pc, &status, buf, &buf_len);
|
||||||
|
if (!(status & (1 << BIT_JUMPED))) {
|
||||||
|
pc += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[buf_len - 1] = '\0';
|
||||||
|
printf("%s\n", buf);
|
||||||
|
|
||||||
|
// Find print register
|
||||||
|
int print_register = A;
|
||||||
|
for (uint32_t i = 0; i < instruction_count; i+=2) {
|
||||||
|
if (instructions[i] == OUT) {
|
||||||
|
print_register = instructions[i+1] - 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert instruction list
|
||||||
|
uint8_t *instructions_inverted = calloc(instruction_count, sizeof(instructions[0]));
|
||||||
|
for (uint32_t i = 0; i < instruction_count; i++) {
|
||||||
|
instructions_inverted[i] = instructions[instruction_count - i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%lu\n", revert(instructions_inverted, instructions, instruction_count, 0, 0, print_register));
|
||||||
|
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
free(instructions);
|
||||||
|
free(instructions_inverted);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t revert(uint8_t *instructions_inverted, uint8_t *instructions, uint32_t instruction_count, uint64_t current_A, uint32_t i, int print_register) {
|
||||||
|
if (i == instruction_count) {
|
||||||
|
return current_A >> 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try each 3-bit LSB of A
|
||||||
|
for (uint32_t j = 0; j < 8; j++) {
|
||||||
|
uint64_t next_A = current_A + j;
|
||||||
|
uint64_t registers_copy[3] = {next_A, 0, 0};
|
||||||
|
uint32_t pc = 0;
|
||||||
|
uint8_t status = 0;
|
||||||
|
for (pc = 0; pc < instruction_count - 4; pc+=2) {
|
||||||
|
execute(registers_copy, instructions, &pc, &status, NULL, NULL);
|
||||||
|
}
|
||||||
|
// Check print register
|
||||||
|
uint64_t expected_output = instructions_inverted[i];
|
||||||
|
if (registers_copy[print_register] % 8 == expected_output) {
|
||||||
|
uint64_t a = revert(instructions_inverted, instructions, instruction_count, next_A << 3, i + 1, print_register);
|
||||||
|
if (a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(uint64_t registers[REGISTERS_LEN], uint8_t *instructions, uint32_t *pc, uint8_t *status, char *output_buffer, int *buf_len) {
|
||||||
|
uint8_t opcode = instructions[*pc];
|
||||||
|
uint8_t operand = instructions[(*pc) + 1];
|
||||||
|
uint8_t current_status = *status;
|
||||||
|
uint8_t next_status = 0;
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
case ADV:
|
||||||
|
registers[A] = registers[A] / (1 << combo(registers, operand));
|
||||||
|
break;
|
||||||
|
case BXL:
|
||||||
|
registers[B] = registers[B] ^ operand;
|
||||||
|
break;
|
||||||
|
case BST:
|
||||||
|
registers[B] = combo(registers, operand) % 8;
|
||||||
|
break;
|
||||||
|
case JNZ:
|
||||||
|
if (registers[A] != 0) {
|
||||||
|
*pc = operand;
|
||||||
|
next_status |= 1 << BIT_JUMPED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BXC:
|
||||||
|
registers[B] = registers[B] ^ registers[C];
|
||||||
|
break;
|
||||||
|
case OUT:
|
||||||
|
output_buffer[(*buf_len)++] = ((uint8_t)combo(registers, operand) & 7) + 48;
|
||||||
|
output_buffer[(*buf_len)++] = ',';
|
||||||
|
break;
|
||||||
|
case BDV:
|
||||||
|
registers[B] = registers[A] / combo(registers, operand);
|
||||||
|
break;
|
||||||
|
case CDV:
|
||||||
|
registers[C] = registers[A] / (1 << combo(registers, operand));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = next_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t combo(uint64_t registers[REGISTERS_LEN], uint8_t operand) {
|
||||||
|
if (operand < 4) {
|
||||||
|
return operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operand == 7) {
|
||||||
|
printf("INVALID PROGRAM\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return registers[operand - 4];
|
||||||
|
}
|
||||||
5
day17/input.txt
Normal file
5
day17/input.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Register A: 46187030
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 2,4,1,5,7,5,0,3,4,0,1,6,5,5,3,0
|
||||||
5
day17/sample.txt
Normal file
5
day17/sample.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Register A: 729
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 0,1,5,4,3,0
|
||||||
5
day17/sample2.txt
Normal file
5
day17/sample2.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Register A: 2024
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 0,3,5,4,3,0
|
||||||
Reference in New Issue
Block a user