12 static int debug_level
= -1;
16 debug_level
= atoi(getenv("DEBUG") ?: "0");
19 static void __attribute__((format(printf
, 2, 3)))
20 debug_raw(int level
, const char *fmt
, ...) {
22 if (debug_level
>= level
) {
24 vfprintf(stderr
, fmt
, ap
);
28 #define debug(...) debug_raw(1, __VA_ARGS__)
30 static int __attribute__((noreturn
)) __attribute__((format(printf
, 1, 2)))
31 die(const char *fmt
, ...)
42 static int64_t orig
[LIMIT
];
56 static struct state s
;
59 dump(struct state
*s
) {
62 debug(" state of id=%d: pc=%d base=%d in=%s%" PRId64
" out=%s%" PRId64
63 " steps=%d\n", s
->id
, s
->pc
, s
->base
,
64 s
->has_in
? "" : "!", s
->in
, s
->has_out
? "" : "!", s
->out
, s
->steps
);
65 for (int i
= 0; i
< len
; i
++)
66 debug_raw(3, "%" PRId64
",", s
->a
[i
]);
70 static void __attribute__((noreturn
))
71 crash(struct state
*s
, const char *msg
) {
72 printf("invalid program id=%d, pc=%d: %s\n", s
->id
, s
->pc
, msg
);
77 get(struct state
*s
, int param
) {
78 int64_t op
= s
->a
[s
->pc
];
83 if (op
> 99999 || op
< 0)
84 crash(s
, "unexpected opcode");
85 if (s
->pc
+ param
> LIMIT
)
86 crash(s
, "memory too short for opcode");
87 value
= s
->a
[s
->pc
+ param
];
90 mode
= (op
/ scale
) % 10;
91 debug_raw(3, "get op=%" PRId64
" mode=%d value=%" PRId64
"\n",
95 if (value
> LIMIT
|| value
< 0)
96 crash(s
, "in position mode, param beyond memory");
102 if (value
> LIMIT
|| value
< 0)
103 crash(s
, "in relative mode, param beyond memory");
106 crash(s
, "unexpected mode");
111 put(struct state
*s
, int param
, int64_t value
) {
112 int64_t op
= s
->a
[s
->pc
];
117 if (op
> 99999 || op
< 0)
118 crash(s
, "unexpected opcode");
119 if (s
->pc
+ param
> LIMIT
)
120 crash(s
, "memory too short for opcode");
121 offset
= s
->a
[s
->pc
+ param
];
124 mode
= (op
/ scale
) % 10;
125 debug_raw(3, "put op=%" PRId64
" mode=%d value=%" PRId64
" offset=%" PRId64
126 "\n", op
, mode
, value
, offset
);
129 if (offset
> LIMIT
|| offset
< 0)
130 crash(s
, "in position mode, param beyond memory");
131 s
->a
[offset
] = value
;
135 if (offset
> LIMIT
|| offset
< 0)
136 crash(s
, "in relative mode, param beyond memory");
137 s
->a
[offset
] = value
;
140 crash(s
, "unexpected mode");
145 init(struct state
*s
, int64_t in
) {
146 memset(s
, 0, sizeof *s
);
147 memcpy(s
->a
, orig
, len
* sizeof orig
[0]);
153 /* Returns -1 for stalled on input, 0 for done, 1 for stalled on output */
155 run(struct state
*s
) {
159 debug_raw(2, "executing id=%d step=%d pc=%d base=%d %" PRId64
160 ",%" PRId64
",%" PRId64
",%" PRId64
"\n", s
->id
,
161 s
->steps
++, s
->pc
, s
->base
, s
->a
[s
->pc
], s
->a
[s
->pc
+1],
162 s
->a
[s
->pc
+2], s
->a
[s
->pc
+3]);
163 if (!(s
->steps
% 10000))
164 debug(" steps=%d\n", s
->steps
);
165 if (s
->pc
> LIMIT
|| s
->pc
< 0)
166 crash(s
, "program ran out of bounds");
167 switch (s
->a
[s
->pc
] % 100) {
169 put(s
, 3, get(s
, 1) + get(s
, 2));
173 put(s
, 3, get(s
, 1) * get(s
, 2));
178 debug_raw(2, "id=%d stalling for input\n", s
->id
);
188 debug_raw(2, "id=%d stalling for output\n", s
->id
);
211 put(s
, 3, get(s
, 1) < get(s
, 2));
215 put(s
, 3, get(s
, 1) == get(s
, 2));
219 s
->base
+= get(s
, 1);
220 if (s
->base
< 0 || s
->base
> LIMIT
)
221 crash(s
, "relative base out of bounds");
225 debug_raw(2, "id=%d halting\n", s
->id
);
228 crash(s
, "unexpected opcode");
239 die("expecting program to consume input");
243 die("expecting program to complete");
245 die("expecting program to produce output");
246 debug("try(%d,%d)=%" PRId64
"\n", x
, y
, s
.out
);
251 main(int argc
, char **argv
) {
259 if (argc
> 1 && strcmp("-", argv
[1]))
260 if (!(stdin
= freopen(argv
[1], "r", stdin
))) {
266 limit
= atoi(argv
[2]);
268 while (scanf("%" SCNd64
"%*[,\n]", &orig
[len
]) == 1)
269 if (len
++ > LIMIT
- 3)
270 die("recompile with larger LIMIT");
271 printf("Read %u slots\n", len
);
275 die("expecting origin to hit");
284 } while (!try(x
, y
));
290 debug("after row %d, count is %d\n", y
, count
);
291 while (++y
!= limit
) {
292 while (lx
< limit
&& !try(lx
, y
))
294 while (rx
< limit
&& try(rx
, y
))
297 debug("after row %d, count is %d\n", y
, count
);
299 printf("%d points in grid size %d\n", count
, limit
);
304 if (try(lx
+ size
- 1, y
- size
+ 1))
308 printf("%dx%d box at offset %d\n", size
, size
, 10000 * lx
+ y
- size
+ 1);