day 25 optimize and improve heuristics
[aoc_eblake.git] / 2019 / day5.c
blobc508e27558fad0186711878c2264e936c5f6b654
1 #define _GNU_SOURCE 1
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6 #include <stdbool.h>
7 #include <math.h>
9 #define LIMIT 2000
10 static int a[LIMIT];
11 static int len;
12 static int pc;
14 static int do_debug = -1;
15 static void
16 debug(const char *fmt, ...) {
17 va_list ap;
18 if (do_debug < 0)
19 do_debug = !!getenv("DEBUG");
20 if (do_debug > 0) {
21 va_start(ap, fmt);
22 vfprintf(stderr, fmt, ap);
23 va_end(ap);
27 static void
28 dump(void) {
29 if (!do_debug)
30 return;
31 for (int i = 0; i < len; i++)
32 debug("%d,", a[i]);
33 debug("\n");
36 static void __attribute__((noreturn))
37 crash(const char *msg) {
38 printf("invalid program, pc=%d: %s\n", pc, msg);
39 exit(1);
42 static int
43 get(int param) {
44 int op = a[pc];
45 int scale = pow(10, param + 1);
46 int mode = (op / scale) % 10;
47 int value;
49 debug("get mode=%d\n", mode);
50 if (pc + param > len)
51 crash("program too short for opcode");
52 value = a[pc + param];
53 switch (mode) {
54 case 0:
55 if (value > len || value < 0)
56 crash("in position mode, param beyond end of program");
57 return a[value];
58 case 1:
59 return value;
60 default:
61 crash("unexpected mode");
65 static void
66 put(int param, int value) {
67 int op = a[pc];
68 int scale = pow(10, param + 1);
69 int mode = (op / scale) % 10;
70 int offset;
72 debug("put mode=%d\n", mode);
73 if (pc + param > len)
74 crash("program too short for opcode");
75 offset = a[pc + param];
76 switch (mode) {
77 case 0:
78 if (offset > len)
79 crash("in position mode, param beyond end of program");
80 a[offset] = value;
81 return;
82 default:
83 crash("unexpected mode");
87 int
88 main(int argc, char **argv) {
89 int i, count = 0, jump;
90 bool done = false;
91 int reads = 0, input = 1;
93 if (argc > 1)
94 if (!(stdin = freopen(argv[1], "r", stdin))) {
95 perror("failure");
96 exit(2);
99 while (scanf("%d%*[,\n]", &i) == 1) {
100 a[len++] = i;
101 if (len > LIMIT - 3) {
102 printf("recompile with larger LIMIT\n");
103 exit(2);
106 printf("Read %u slots\n", len);
107 dump();
109 if (argc > 2)
110 input = atoi(argv[2]);
112 while (!done) {
113 count++;
114 debug("executing %d,%d,%d,%d\n", a[pc], a[pc+1], a[pc+2], a[pc+3]);
115 if (pc > len || pc < 0)
116 crash("program ran out of bounds");
117 switch (a[pc] % 100) {
118 case 1:
119 put(3, get(1) + get(2));
120 jump = 4;
121 break;
122 case 2:
123 put(3, get(1) * get(2));
124 jump = 4;
125 break;
126 case 3:
127 if (++reads != 1)
128 crash("too many reads");
129 put(1, input);
130 jump = 2;
131 break;
132 case 4:
133 printf("%d\n", get(1));
134 jump = 2;
135 break;
136 case 5:
137 if (get(1)) {
138 pc = get(2);
139 jump = 0;
140 } else
141 jump = 3;
142 break;
143 case 6:
144 if (!get(1)) {
145 pc = get(2);
146 jump = 0;
147 } else
148 jump = 3;
149 break;
150 case 7:
151 put(3, get(1) < get(2));
152 jump = 4;
153 break;
154 case 8:
155 put(3, get(1) == get(2));
156 jump = 4;
157 break;
158 case 99:
159 debug("halting\n");
160 done = true;
161 jump = 1;
162 break;
163 default:
164 crash("unexpected opcode");
166 pc += jump;
167 dump();
169 printf("after %d opcodes, slot 0 holds %d\n", count, a[0]);
170 dump();
171 return 0;