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 %" PRId64
",%" PRId64
138 ",%" PRId64
",%" PRId64
"\n", s
->id
,
139 s
->steps
++, s
->pc
, s
->a
[s
->pc
], s
->a
[s
->pc
+1], s
->a
[s
->pc
+2],
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
);
165 printf("program id=%d overwriting output %" PRId64
" \n", s
->id
, s
->out
);
185 put(s
, 3, get(s
, 1) < get(s
, 2));
189 put(s
, 3, get(s
, 1) == get(s
, 2));
193 s
->base
+= get(s
, 1);
194 if (s
->base
< 0 || s
->base
> LIMIT
)
195 crash(s
, "relative base out of bounds");
199 debug_raw(2, "id=%d halting\n", s
->id
);
202 crash(s
, "unexpected opcode");
209 static struct state s
;
211 main(int argc
, char **argv
) {
216 if (!(stdin
= freopen(argv
[1], "r", stdin
))) {
221 while (scanf("%" SCNd64
"%*[,\n]", &orig
[len
]) == 1)
222 if (len
++ > LIMIT
- 3) {
223 printf("recompile with larger LIMIT\n");
226 printf("Read %u slots\n", len
);
228 for (i
= 1; i
<= 2; i
++) {
231 crash(&s
, "not enough input");
233 printf("part %d final output %" PRId64
"\n", i
, s
.out
);
235 printf("part %d no final output\n", i
);