|
|
@@ -0,0 +1,130 @@ |
|
|
|
// |
|
|
|
// Created by red on 05/12/19. |
|
|
|
// |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <string.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include "intcode.h" |
|
|
|
|
|
|
|
ival out_val(int n) { |
|
|
|
ival v; |
|
|
|
v.type = IVAL_OUT; |
|
|
|
v.num = n; |
|
|
|
return v; |
|
|
|
} |
|
|
|
|
|
|
|
ival err_val(int n) { |
|
|
|
ival v; |
|
|
|
v.type = IVAL_ERR; |
|
|
|
v.err = n; |
|
|
|
return v; |
|
|
|
} |
|
|
|
|
|
|
|
ival end_val() { |
|
|
|
ival v; |
|
|
|
v.type = IVAL_END; |
|
|
|
return v; |
|
|
|
} |
|
|
|
|
|
|
|
ival cont_val() { |
|
|
|
ival v; |
|
|
|
v.type = IVAL_CONT; |
|
|
|
return v; |
|
|
|
} |
|
|
|
|
|
|
|
void ival_print(ival v) { |
|
|
|
switch (v.type) { |
|
|
|
case IVAL_ERR: { |
|
|
|
switch (v.err) { |
|
|
|
case IERR_OUT_OF_BOUNDS: printf("error: read/write out of bounds\n"); |
|
|
|
break; |
|
|
|
case IERR_BAD_OP: printf("error: bad opcode\n"); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case IVAL_OUT: { |
|
|
|
printf("Output value: %d\n", v.num); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ival step (intcode* m) { |
|
|
|
int opcode = m->tape[m->index]; |
|
|
|
int addr_mode[2]; |
|
|
|
addr_mode[0] = (opcode / 100) % 10; |
|
|
|
addr_mode[1] = (opcode / 1000) % 10; |
|
|
|
opcode = opcode % 100; |
|
|
|
switch (opcode) { |
|
|
|
case 99: return end_val(); |
|
|
|
case 4: { |
|
|
|
int v; |
|
|
|
if (addr_mode[0] == 0) { v = m->tape[m->tape[m->index+1]]; } |
|
|
|
else { v = m->tape[m->index+1]; } |
|
|
|
m->index += 2; |
|
|
|
return out_val(v); |
|
|
|
} |
|
|
|
case 3: { |
|
|
|
int i = m->tape[m->index+1]; |
|
|
|
m->index += 2; |
|
|
|
m->tape[i] = m->input_tape[0]; |
|
|
|
m->input_tape = m->input_tape+1; |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
default: { |
|
|
|
int a; |
|
|
|
int b; |
|
|
|
if (opcode != 1 && opcode != 2) return err_val(IERR_BAD_OP); |
|
|
|
if (addr_mode[0] == 0) { a = m->tape[m->tape[m->index+1]]; } |
|
|
|
else { a = m->tape[m->index+1]; } |
|
|
|
if (addr_mode[1] == 0) { b = m->tape[m->tape[m->index+2]]; } |
|
|
|
else { b = m->tape[m->index+2]; } |
|
|
|
switch (opcode) { |
|
|
|
case 1: { |
|
|
|
m->tape[m->tape[m->index+3]] = a+b; |
|
|
|
m->index += 4; |
|
|
|
break; |
|
|
|
} |
|
|
|
case 2: { |
|
|
|
m->tape[m->tape[m->index+3]] = a*b; |
|
|
|
m->index += 4; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ival run (intcode* m) { |
|
|
|
for (;;) { |
|
|
|
size_t i = m->index; |
|
|
|
printf("DEBUG: next 4 values: %d %d %d %d\n", m->tape[i], m->tape[i+1], m->tape[i+2], m->tape[i+3]); |
|
|
|
ival v = step(m); |
|
|
|
switch (v.type) { |
|
|
|
case IVAL_ERR: |
|
|
|
case IVAL_END: return v; |
|
|
|
case IVAL_OUT: ival_print(v); |
|
|
|
break; |
|
|
|
default: break; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
intcode *read_file(char *filename, size_t buf_size) { |
|
|
|
int* tape = calloc(buf_size, sizeof(int)); |
|
|
|
memset((void*) tape, 0, sizeof(int)*buf_size); |
|
|
|
FILE* file = fopen(filename, "r"); |
|
|
|
size_t i; |
|
|
|
for (i = 0; i < buf_size; i++) { |
|
|
|
int a; |
|
|
|
int err = fscanf(file, "%d,", &a); |
|
|
|
if (err == EOF) break; |
|
|
|
tape[i] = a; |
|
|
|
} |
|
|
|
static intcode v; |
|
|
|
v.tape = tape; |
|
|
|
v.index = 0; |
|
|
|
v.tape_l = i; |
|
|
|
return &v; |
|
|
|
} |