-
-
Save erikaderstedt/c4d3b4ac86f5a8b75959052154aefc91 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#define IMMEDIATE (1) | |
#define POSITIONAL (0) | |
#define RELATIVE (2) | |
#define ARG0_ADDR (p[i+1] + ((modes[0] == RELATIVE) ? relative_base : 0)) | |
#define ARG1_ADDR (p[i+2] + ((modes[1] == RELATIVE) ? relative_base : 0)) | |
#define ARG2_ADDR (p[i+3] + ((modes[2] == RELATIVE) ? relative_base : 0)) | |
#define ARG0 ((modes[0]==IMMEDIATE) ? p[i+1] : p[ARG0_ADDR]) | |
#define ARG1 ((modes[1]==IMMEDIATE) ? p[i+2] : p[ARG1_ADDR]) | |
int64_t run_program_and_wait(int64_t *p, | |
int64_t *instr, | |
int64_t length, | |
const int64_t *__restrict input, | |
size_t num_inputs, | |
bool *waiting_for_input, | |
int64_t *output_buf) { | |
int64_t i = *instr, output = 0; | |
size_t used_inputs = 0; | |
int64_t relative_base = 0; | |
*waiting_for_input = false; | |
while (p[i] != 99) { | |
int64_t modes[4] = { 100,1000,10000,10000}; | |
int64_t instruction = p[i] % 100; | |
for (size_t j = 0; j < 4; j++) modes[j] = (p[i] / modes[j]) % 10; | |
switch (instruction) { | |
case 1: p[ARG2_ADDR] = ARG0 + ARG1; i += 4; break; | |
case 2: p[ARG2_ADDR] = ARG0 * ARG1; i += 4; break; | |
case 7: p[ARG2_ADDR] = (ARG0 < ARG1) ? 1 : 0; i += 4; break; | |
case 8: p[ARG2_ADDR] = (ARG0 == ARG1) ? 1 : 0; i += 4; break; | |
case 4: output_buf[output++] = ARG0; i += 2; break; | |
case 5: i = (ARG0 != 0) ? ARG1 : (i+3); break; | |
case 6: i = (ARG0 == 0) ? ARG1 : (i+3); break; | |
case 9: relative_base += ARG0; i += 2; break; | |
case 3: | |
if (used_inputs == num_inputs) { | |
// Pause, wait for more inputs | |
*waiting_for_input = true; | |
*instr = i; | |
return output; | |
} | |
p[ARG0_ADDR] = input[used_inputs++]; | |
i += 2; break; | |
default: fprintf(stderr, "Invalid opcode %lld.\n", p[i]); exit(1); | |
} | |
} | |
return output; | |
} | |
int main(int argc, char **argv) { | |
int64_t a[1000024], output[10000]; | |
size_t length = 0; | |
FILE *fp = fopen(argv[1], "r"); | |
while(fscanf(fp, "%lld,", a + length++) > 0); | |
fclose(fp); | |
length--; | |
bool wait; | |
int64_t ip = 0; | |
int64_t input = 2; | |
int64_t m = run_program_and_wait(a, &ip, length, &input, 1, &wait, output); // Input phase | |
for (int64_t x = 0; x < m-1; x++) { | |
printf("%lld,", output[x]); | |
} | |
if (m > 0) printf("%lld", output[m-1]); | |
printf("\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment