11 static int64_t orig
[LIMIT
];
25 static int debug_level
= -1;
27 debug_raw(int level
, const char *fmt
, ...) {
30 debug_level
= atoi(getenv("DEBUG") ?: "0");
31 if (debug_level
>= level
) {
33 vfprintf(stderr
, fmt
, ap
);
37 #define debug(...) debug_raw(1, __VA_ARGS__)
40 dump(struct state
*s
) {
43 debug(" state of id=%d: pc=%d base=%d in=%s%" PRId64
" out=%s%" PRId64
44 " steps=%d\n", s
->id
, s
->pc
, s
->base
,
45 s
->has_in
? "" : "!", s
->in
, s
->has_out
? "" : "!", s
->out
, s
->steps
);
46 for (int i
= 0; i
< len
; i
++)
47 debug_raw(3, "%" PRId64
",", s
->a
[i
]);
51 static void __attribute__((noreturn
))
52 crash(struct state
*s
, const char *msg
) {
53 printf("invalid program id=%d, pc=%d: %s\n", s
->id
, s
->pc
, msg
);
58 get(struct state
*s
, int param
) {
59 int64_t op
= s
->a
[s
->pc
];
64 if (op
> 99999 || op
< 0)
65 crash(s
, "unexpected opcode");
66 if (s
->pc
+ param
> LIMIT
)
67 crash(s
, "memory too short for opcode");
68 value
= s
->a
[s
->pc
+ param
];
71 mode
= (op
/ scale
) % 10;
72 debug_raw(3, "get op=%d mode=%d value=%d\n", op
, mode
, value
);
75 if (value
> LIMIT
|| value
< 0)
76 crash(s
, "in position mode, param beyond memory");
82 if (value
> LIMIT
|| value
< 0)
83 crash(s
, "in relative mode, param beyond memory");
86 crash(s
, "unexpected mode");
91 put(struct state
*s
, int param
, int64_t value
) {
92 int64_t op
= s
->a
[s
->pc
];
97 if (op
> 99999 || op
< 0)
98 crash(s
, "unexpected opcode");
99 if (s
->pc
+ param
> LIMIT
)
100 crash(s
, "memory too short for opcode");
101 offset
= s
->a
[s
->pc
+ param
];
104 mode
= (op
/ scale
) % 10;
105 debug_raw(3, "put op=%d mode=%d value=%d offset=%d\n", op
, mode
, value
, offset
);
108 if (offset
> LIMIT
|| offset
< 0)
109 crash(s
, "in position mode, param beyond memory");
110 s
->a
[offset
] = value
;
114 if (offset
> LIMIT
|| offset
< 0)
115 crash(s
, "in relative mode, param beyond memory");
116 s
->a
[offset
] = value
;
119 crash(s
, "unexpected mode");
124 init(struct state
*s
, int64_t in
) {
125 memset(s
, 0, sizeof *s
);
126 memcpy(s
->a
, orig
, len
* sizeof orig
[0]);
133 run(struct state
*s
) {
137 debug_raw(2, "executing id=%d step=%d pc=%d base=%" PRId64
" %" PRId64
138 ",%" PRId64
",%" PRId64
",%" PRId64
"\n", s
->id
,
139 s
->steps
++, s
->pc
, s
->base
, s
->a
[s
->pc
], s
->a
[s
->pc
+1],
140 s
->a
[s
->pc
+2], s
->a
[s
->pc
+3]);
141 if (!(s
->steps
% 10000))
142 debug(" steps=%d\n", s
->steps
);
143 if (s
->pc
> LIMIT
|| s
->pc
< 0)
144 crash(s
, "program ran out of bounds");
145 switch (s
->a
[s
->pc
] % 100) {
147 put(s
, 3, get(s
, 1) + get(s
, 2));
151 put(s
, 3, get(s
, 1) * get(s
, 2));
156 debug_raw(2, "id=%d stalling for input\n", s
->id
);
166 debug_raw(2, "id=%d stalling for output\n", s
->id
);
189 put(s
, 3, get(s
, 1) < get(s
, 2));
193 put(s
, 3, get(s
, 1) == get(s
, 2));
197 s
->base
+= get(s
, 1);
198 if (s
->base
< 0 || s
->base
> LIMIT
)
199 crash(s
, "relative base out of bounds");
203 debug_raw(2, "id=%d halting\n", s
->id
);
206 crash(s
, "unexpected opcode");
214 static uint8_t grid
[GRID
][GRID
];
215 enum dir
{ U
, R
, D
, L
};
217 static struct state s
;
220 display(int pairs
, int minx
, int maxx
, int miny
, int maxy
) {
222 fprintf(stderr
, " pair %d\n", pairs
);
223 for (j
= miny
- 3; j
< maxy
+ 3; j
++) {
224 for (i
= minx
- 3; i
< maxx
+ 3; i
++)
225 putc(" #-"[grid
[j
][i
]], stderr
);
231 main(int argc
, char **argv
) {
233 int pairs
= 0, count
= 0;
234 int x
, y
, minx
, maxx
, miny
, maxy
;
239 if (!(stdin
= freopen(argv
[1], "r", stdin
))) {
244 while (scanf("%" SCNd64
"%*[,\n]", &orig
[len
]) == 1)
245 if (len
++ > LIMIT
- 3) {
246 printf("recompile with larger LIMIT\n");
249 printf("Read %u slots\n", len
);
251 for (i
= 0; i
< 2; i
++) {
253 memset(grid
, 2, sizeof grid
);
261 display(pairs
, minx
, maxx
, miny
, maxy
);
264 crash(&s
, "no input prepped");
265 debug("pair %d, supplying %d\n", pairs
, s
.in
);
267 crash(&s
, "unexpected completion");
269 crash(&s
, "input not consumed");
271 crash(&s
, "missing expected output");
273 crash(&s
, "unexpected output");
274 debug("painting %d,%d as %d at pc=%d\n", x
, y
, s
.out
, s
.pc
);
282 crash(&s
, "missing expected output");
284 crash(&s
, "unexpected output");
291 case U
: y
--; if (y
< miny
) miny
= y
; break;
292 case R
: x
++; if (x
> maxx
) maxx
= x
; break;
293 case D
: y
++; if (y
> maxy
) maxy
= y
; break;
294 case L
: x
--; if (x
< minx
) minx
= x
; break;
296 debug("moving %d to %d,%d facing %c\n", s
.out
, x
, y
, "URDL"[dir
]);
297 if (minx
< 0 || maxx
>= GRID
|| miny
< 0 || maxy
>= GRID
)
298 crash(&s
, "recompile with larger grid");
301 s
.in
= grid
[y
][x
] == 1;
303 display(pairs
, minx
, maxx
, miny
, maxy
);
304 printf("%d-%d %d-%d\n", minx
, maxx
, miny
, maxy
);
305 printf("program completed: %d pairs parsed, %d painted\n", pairs
, count
);