day 2 golf to 389 effective bytes
[aoc_eblake.git] / 2016 / advent25.c
blob6ea45adadfd79c0be22abf5ee6c4b4cc39c77ffb
1 #define _GNU_SOURCE 1
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <stdbool.h>
7 #include <ctype.h>
9 int regs[4];
10 int cache[4];
11 char *program[50]; // sized based on pre-inspecting file
13 int
14 get (const char *value)
16 if (isalpha(*value))
17 return regs[*value - 'a'];
18 return atoi (value);
21 void
22 set (const char *reg, int value)
24 if (getenv ("DEBUG"))
25 printf (" setting %s to %d\n", reg, value);
26 regs[*reg - 'a'] = value;
29 int main(int argc, char **argv)
31 int instr = 0;
32 char buf[250]; // sized based on pre-inspecting file
33 int nread = fread (buf, 1, sizeof buf, stdin);
34 char *p = buf;
35 while (p < buf + nread) {
36 program[instr++] = p;
37 p = strchr (p, '\n');
38 *p++ = '\0';
40 printf ("program consists of %d instructions\n", instr);
41 int initial = -1;
42 retry:
43 regs[0] = ++initial;
44 memset (cache, 0, sizeof cache);
45 if (getenv ("DEBUG"))
46 printf ("attempting execution with a=%d\n", initial);
47 unsigned int pc = 0;
48 long long count = 0;
49 int expected = 0;
50 while (pc < instr && expected < 50) {
51 char arg1[10], arg2[10];
52 unsigned int line;
53 count++;
54 if (getenv ("DEBUG"))
55 printf ("count=%lld pc=%d a=%d b=%d c=%d d=%d, executing %s\n", count,
56 pc, regs[0], regs[1], regs[2], regs[3], program[pc]);
57 sscanf (program[pc], "%*s %9s %9s", arg1, arg2);
58 switch (program[pc][0]) {
59 case 'c': // cpy x y
60 if (isalpha (*arg2))
61 set (arg2, get (arg1));
62 break;
63 case 'i': // inc x
64 set (arg1, get (arg1) + 1);
65 break;
66 case 'd': // dec x
67 set (arg1, get (arg1) - 1);
68 break;
69 case 'j': // jnz x y
70 if (get (arg1))
71 pc += get (arg2) - 1;
72 break;
73 case 't': // tgl x
74 line = get (arg1) + pc;
75 if (line < instr) {
76 if (getenv ("DEBUG"))
77 printf (" rewriting instruction %d, was %s\n", line, program[line]);
78 switch (*program[line]) {
79 case 'i':
80 memcpy (program[line], "dec", 3);
81 break;
82 case 'd':
83 case 't':
84 memcpy (program[line], "inc", 3);
85 break;
86 case 'c':
87 memcpy (program[line], "jnz", 3);
88 break;
89 case 'j':
90 memcpy (program[line], "cpy", 3);
91 break;
92 default:
93 return 1;
96 break;
97 case 'o': // out x
98 line = get (arg1);
99 if (line != (expected & 1)) {
100 //if (getenv ("DEBUG"))
101 printf ("after %lld ops and %d out, got %d, with initial a=%d\n",
102 count, expected, line, initial);
103 goto retry;
105 if (initial == 175)
106 printf (" %d %d %d %d: %d\n", regs[0], regs[1], regs[2], regs[3], line);
107 if (!line) {
108 if (!memcmp (regs, cache, sizeof regs))
109 printf ("same state seen, looping sequence found?\n");
110 memcpy (cache, regs, sizeof regs);
112 expected++;
113 break;
114 default:
115 return 1;
117 pc++;
119 int potential = 0;
120 if (pc < instr) {
121 printf ("potential candidate for start %d, with %d out\n", initial,
122 expected);
123 if (potential++ < 10)
124 goto retry;
126 printf ("after %lld operations, final content of register a: %d\n",
127 count, regs[0]);
128 return 0;