diff options
Diffstat (limited to '2018')
-rw-r--r-- | 2018/day16.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/2018/day16.c b/2018/day16.c new file mode 100644 index 0000000..a1a72c4 --- /dev/null +++ b/2018/day16.c @@ -0,0 +1,132 @@ +#include <stdio.h> +#include <stdlib.h> + +typedef unsigned uint; +typedef unsigned short Set; + +struct CPU { + uint r[4]; +}; + +static int cpuEq(struct CPU a, struct CPU b) { + return a.r[0] == b.r[0] + && a.r[1] == b.r[1] + && a.r[2] == b.r[2] + && a.r[3] == b.r[3]; +} + +typedef struct CPU Op(struct CPU, uint, uint, uint); + +static struct CPU addr(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] + cpu.r[b]; return cpu; +} +static struct CPU addi(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] + b; return cpu; +} +static struct CPU mulr(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] * cpu.r[b]; return cpu; +} +static struct CPU muli(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] * b; return cpu; +} +static struct CPU banr(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] & cpu.r[b]; return cpu; +} +static struct CPU bani(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] & b; return cpu; +} +static struct CPU borr(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] | cpu.r[b]; return cpu; +} +static struct CPU bori(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] | b; return cpu; +} +static struct CPU setr(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a]; return cpu; +} +static struct CPU seti(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = a; return cpu; +} +static struct CPU gtir(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = a > cpu.r[b]; return cpu; +} +static struct CPU gtri(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] > b; return cpu; +} +static struct CPU gtrr(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] > cpu.r[b]; return cpu; +} +static struct CPU eqir(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = a == cpu.r[b]; return cpu; +} +static struct CPU eqri(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] == b; return cpu; +} +static struct CPU eqrr(struct CPU cpu, uint a, uint b, uint c) { + cpu.r[c] = cpu.r[a] == cpu.r[b]; return cpu; +} + +static const struct { + const char *name; + Op *fn; +} Ops[16] = { + { "addr", addr }, + { "addi", addi }, + { "mulr", mulr }, + { "muli", muli }, + { "banr", banr }, + { "bani", bani }, + { "borr", borr }, + { "bori", bori }, + { "setr", setr }, + { "seti", seti }, + { "gtir", gtir }, + { "gtri", gtri }, + { "gtrr", gtrr }, + { "eqir", eqir }, + { "eqri", eqri }, + { "eqrr", eqrr }, +}; + +static uint card(Set set) { + uint pop = 0; + while (set) { + if (set & 1) pop++; + set >>= 1; + } + return pop; +} + +int main(void) { + Set opcodes[16]; + for (uint i = 0; i < 16; ++i) { + opcodes[i] = 0xFFFF; + } + + uint samples = 0; + for (;;) { + struct CPU before, after; + uint code, a, b, c; + int match = scanf( + "Before: [%u, %u, %u, %u]\n" + "%u %u %u %u\n" + "After: [%u, %u, %u, %u]\n", + &before.r[0], &before.r[1], &before.r[2], &before.r[3], + &code, &a, &b, &c, + &after.r[0], &after.r[1], &after.r[2], &after.r[3] + ); + if (match < 12) break; + + uint count = 0; + for (uint i = 0; i < 16; ++i) { + struct CPU result = Ops[i].fn(before, a, b, c); + if (cpuEq(result, after)) { + count++; + } else { + opcodes[code] &= ~(1 << i); + } + } + if (count >= 3) samples++; + } + printf("%u\n", samples); +} |