9 static int orig
[LIMIT
];
24 static int debug_level
= -1;
26 debug_raw(int level
, const char *fmt
, ...) {
29 debug_level
= atoi(getenv("DEBUG") ?: "0");
30 if (debug_level
>= level
) {
32 vfprintf(stderr
, fmt
, ap
);
36 #define debug(...) debug_raw(1, __VA_ARGS__)
39 dump(struct state
*s
) {
42 debug(" state of id=%d: pc=%d in=%s%d out=%s%d steps=%d\n", s
->id
, s
->pc
,
43 s
->has_in
? "" : "!", s
->in
, s
->has_out
? "" : "!", s
->out
, s
->steps
);
44 for (int i
= 0; i
< len
; i
++)
45 debug_raw(3, "%d,", s
->a
[i
]);
49 static void __attribute__((noreturn
))
50 crash(struct state
*s
, const char *msg
) {
51 printf("invalid program id=%d, pc=%d: %s\n", s
->id
, s
->pc
, msg
);
56 get(struct state
*s
, int param
) {
62 if (s
->pc
+ param
> len
)
63 crash(s
, "program too short for opcode");
64 value
= s
->a
[s
->pc
+ param
];
67 mode
= (op
/ scale
) % 10;
68 debug_raw(3, "get op=%d mode=%d value=%d\n", op
, mode
, value
);
71 if (value
> len
|| value
< 0)
72 crash(s
, "in position mode, param beyond end of program");
77 crash(s
, "unexpected mode");
82 put(struct state
*s
, int param
, int value
) {
88 if (s
->pc
+ param
> len
)
89 crash(s
, "program too short for opcode");
90 offset
= s
->a
[s
->pc
+ param
];
93 mode
= (op
/ scale
) % 10;
94 debug_raw(3, "put op=%d mode=%d value=%d offset=%d\n", op
, mode
, value
, offset
);
98 crash(s
, "in position mode, param beyond end of program");
102 crash(s
, "unexpected mode");
107 run(struct state
*s
) {
111 debug_raw(2, "executing id=%d step=%d pc=%d %d,%d,%d,%d\n", s
->id
,
112 s
->steps
++, s
->pc
, s
->a
[s
->pc
], s
->a
[s
->pc
+1], s
->a
[s
->pc
+2],
114 if (s
->pc
> len
|| s
->pc
< 0)
115 crash(s
, "program ran out of bounds");
116 switch (s
->a
[s
->pc
] % 100) {
118 put(s
, 3, get(s
, 1) + get(s
, 2));
122 put(s
, 3, get(s
, 1) * get(s
, 2));
127 debug_raw(2, "id=%d stalling for input\n", s
->id
);
136 printf("program id=%d overwriting output %d\n", s
->id
, s
->out
);
156 put(s
, 3, get(s
, 1) < get(s
, 2));
160 put(s
, 3, get(s
, 1) == get(s
, 2));
164 debug_raw(2, "id=%d halting\n", s
->id
);
167 crash(s
, "unexpected opcode");
178 bool done
= false, has_out
= true;
180 debug("computing %d,%d,%d,%d,%d...\n", p
[0], p
[1], p
[2], p
[3], p
[4]);
181 for (i
= 0; i
< 5; i
++) {
182 memset(&s
[i
], 0, sizeof amps
[i
]);
184 memcpy(amps
[i
].a
, orig
, len
* sizeof orig
[0]);
185 amps
[i
].has_in
= true;
187 if (run(&s
[i
]) != -1 || amps
[i
].has_in
)
188 crash(&s
[i
], "program finished too soon");
193 for (i
= 0; i
< 5; i
++) {
195 printf("program id=%d skipping input %d\n", amps
[i
].id
, amps
[i
].in
);
196 amps
[i
].has_in
= has_out
;
198 if (run(&s
[i
]) == -1)
200 else if (!amps
[i
].has_out
)
201 printf("program id=%d completed with stale output\n", amps
[i
].id
);
202 has_out
= amps
[i
].has_out
;
204 amps
[i
].has_out
= false;
208 debug("...%d\n", data
);
214 permute(int *p
, int size
, int n
)
221 permute(p
, size
- 1, n
);
222 for (i
= 0; i
< size
- 1; i
++) {
232 permute(p
, size
- 1, n
);
237 main(int argc
, char **argv
) {
239 int phase
[] = { 0, 1, 2, 3, 4 };
243 if (!(stdin
= freopen(argv
[1], "r", stdin
))) {
248 while (scanf("%d%*[,\n]", &i
) == 1) {
250 if (len
> LIMIT
- 3) {
251 printf("recompile with larger LIMIT\n");
255 printf("Read %u slots\n", len
);
256 memcpy(amps
[0].a
, orig
, len
* sizeof orig
[0]);
259 permute(phase
, 5, 5);
260 printf("part 1 best output %d\n", max
);
262 for (i
= 0; i
< 5; i
++)
265 permute(phase
, 5, 5);
266 printf("part 2 best output %d\n", max
);