|
|
@@ -7,14 +7,14 @@ |
|
|
|
#include <stdlib.h> |
|
|
|
#include "intcode.h" |
|
|
|
|
|
|
|
ival out_val(int n) { |
|
|
|
ival out_val(long n) { |
|
|
|
ival v; |
|
|
|
v.type = IVAL_OUT; |
|
|
|
v.num = n; |
|
|
|
return v; |
|
|
|
} |
|
|
|
|
|
|
|
ival err_val(int n) { |
|
|
|
ival err_val(long n) { |
|
|
|
ival v; |
|
|
|
v.type = IVAL_ERR; |
|
|
|
v.err = n; |
|
|
@@ -44,7 +44,7 @@ void ival_print(ival v) { |
|
|
|
} |
|
|
|
} |
|
|
|
case IVAL_OUT: { |
|
|
|
printf("Output value: %d\n", v.num); |
|
|
|
printf("Output value: %ld\n", v.num); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@@ -54,113 +54,109 @@ int power (int base, int pow) { |
|
|
|
else return base*power(base,pow-1); |
|
|
|
} |
|
|
|
|
|
|
|
int* get_operands (intcode* m, size_t num_operands) { |
|
|
|
int* operands = calloc(num_operands, sizeof(int)); |
|
|
|
int opcode = m->tape[m->index] / 100; |
|
|
|
for (size_t i = 0; i < num_operands; i++) { |
|
|
|
int addr_mode = opcode % 10; |
|
|
|
void get_operands (intcode* m, long** operands) { |
|
|
|
long opcode = m->tape[m->index] / 100; |
|
|
|
for (size_t i = 0; i < 3; i++) { |
|
|
|
long addr_mode = opcode % 10; |
|
|
|
opcode = opcode / 10; |
|
|
|
int v = 0; |
|
|
|
if (addr_mode == 0) { |
|
|
|
v = m->tape[m->tape[m->index+i+1]]; |
|
|
|
long* v = 0; |
|
|
|
switch (addr_mode) { |
|
|
|
case 0: v = &m->tape[m->tape[m->index + i + 1]]; break; |
|
|
|
case 1: v = &m->tape[m->index + i + 1]; break; |
|
|
|
case 2: { |
|
|
|
long delta = m->tape[m->index + i + 1]; |
|
|
|
v = &m->tape[m->relative_base + delta]; |
|
|
|
} |
|
|
|
} |
|
|
|
else v = m->tape[m->index+i+1]; |
|
|
|
operands[i] = v; |
|
|
|
} |
|
|
|
return operands; |
|
|
|
} |
|
|
|
|
|
|
|
ival op_add (intcode* m) { |
|
|
|
int* operands = get_operands(m, 2); |
|
|
|
m->tape[m->tape[m->index+3]] = operands[0] + operands[1]; |
|
|
|
ival op_add (intcode* m, long** operands) { |
|
|
|
*operands[2] = *operands[0] + *operands[1]; |
|
|
|
m->index += 4; |
|
|
|
free((void*) operands); |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_mul (intcode* m) { |
|
|
|
int* operands = get_operands(m, 2); |
|
|
|
m->tape[m->tape[m->index+3]] = operands[0] * operands[1]; |
|
|
|
ival op_mul (intcode* m, long** operands) { |
|
|
|
*operands[2] = *operands[0] * *operands[1]; |
|
|
|
m->index += 4; |
|
|
|
free((void*) operands); |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_in (intcode* m) { |
|
|
|
int i = m->tape[m->index+1]; |
|
|
|
ival op_in (intcode* m, long** operands) { |
|
|
|
*operands[0] = m->input_tape[0]; |
|
|
|
m->index += 2; |
|
|
|
m->tape[i] = m->input_tape[0]; |
|
|
|
m->input_tape = m->input_tape+1; |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_out (intcode* m) { |
|
|
|
int* operands = get_operands(m, 1); |
|
|
|
ival op_out (intcode* m, long** operands) { |
|
|
|
m->index += 2; |
|
|
|
int v = operands[0]; |
|
|
|
free((void*) operands); |
|
|
|
long v = *operands[0]; |
|
|
|
return out_val(v); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_jnz (intcode* m) { |
|
|
|
int* operands = get_operands(m, 2); |
|
|
|
if (operands[0] != 0) { |
|
|
|
m->index = (size_t) operands[1]; |
|
|
|
ival op_jnz (intcode* m, long** operands) { |
|
|
|
if (*operands[0] != 0) { |
|
|
|
m->index = (size_t) *operands[1]; |
|
|
|
} else { |
|
|
|
m->index += 3; |
|
|
|
} |
|
|
|
free((void*) operands); |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_jez (intcode* m) { |
|
|
|
int* operands = get_operands(m, 2); |
|
|
|
if (operands[0] == 0) { |
|
|
|
m->index = (size_t) operands[1]; |
|
|
|
ival op_jez (intcode* m, long** operands) { |
|
|
|
if (*operands[0] == 0) { |
|
|
|
m->index = (size_t) *operands[1]; |
|
|
|
} else { |
|
|
|
m->index += 3; |
|
|
|
} |
|
|
|
free((void*) operands); |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_lt (intcode* m) { |
|
|
|
int* operands = get_operands(m,2); |
|
|
|
int result; |
|
|
|
if (operands[0] < operands[1]) { |
|
|
|
ival op_lt (intcode* m, long** operands) { |
|
|
|
long result; |
|
|
|
if (*operands[0] < *operands[1]) { |
|
|
|
result = 1; |
|
|
|
} else result = 0; |
|
|
|
m->tape[m->tape[m->index+3]] = result; |
|
|
|
*operands[2] = result; |
|
|
|
m->index += 4; |
|
|
|
free((void*) operands); |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_eq (intcode* m) { |
|
|
|
int* operands = get_operands(m,2); |
|
|
|
int result; |
|
|
|
if (operands[0] == operands[1]) { |
|
|
|
ival op_eq (intcode* m, long** operands) { |
|
|
|
long result; |
|
|
|
if (*operands[0] == *operands[1]) { |
|
|
|
result = 1; |
|
|
|
} else result = 0; |
|
|
|
m->tape[m->tape[m->index+3]] = result; |
|
|
|
*operands[2] = result; |
|
|
|
m->index += 4; |
|
|
|
free((void*) operands); |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_rbs (intcode* m, long** operands) { |
|
|
|
m->relative_base += *operands[0]; |
|
|
|
m->index += 2; |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival step (intcode* m) { |
|
|
|
int opcode = m->tape[m->index]; |
|
|
|
long* operands[3]; |
|
|
|
get_operands(m, operands); |
|
|
|
long opcode = m->tape[m->index]; |
|
|
|
opcode = opcode % 100; |
|
|
|
switch (opcode) { |
|
|
|
case 99: return end_val(); |
|
|
|
case 1: return op_add(m); |
|
|
|
case 2: return op_mul(m); |
|
|
|
case 3: return op_in(m); |
|
|
|
case 4: return op_out(m); |
|
|
|
case 5: return op_jnz(m); |
|
|
|
case 6: return op_jez(m); |
|
|
|
case 7: return op_lt(m); |
|
|
|
case 8: return op_eq(m); |
|
|
|
case 1: return op_add(m, operands); |
|
|
|
case 2: return op_mul(m, operands); |
|
|
|
case 3: return op_in(m, operands); |
|
|
|
case 4: return op_out(m, operands); |
|
|
|
case 5: return op_jnz(m, operands); |
|
|
|
case 6: return op_jez(m, operands); |
|
|
|
case 7: return op_lt(m, operands); |
|
|
|
case 8: return op_eq(m, operands); |
|
|
|
case 9: return op_rbs(m, operands); |
|
|
|
default: return err_val(IERR_BAD_OP); |
|
|
|
} |
|
|
|
} |
|
|
@@ -180,13 +176,13 @@ ival run (intcode* m) { |
|
|
|
}; |
|
|
|
|
|
|
|
intcode* read_file(char *filename, size_t buf_size) { |
|
|
|
int* tape = calloc(buf_size, sizeof(int)); |
|
|
|
memset((void*) tape, 0, sizeof(int)*buf_size); |
|
|
|
long* tape = calloc(buf_size, sizeof(long)); |
|
|
|
memset((void*) tape, 0, sizeof(long)*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); |
|
|
|
long a; |
|
|
|
long err = fscanf(file, "%ld,", &a); |
|
|
|
if (err == EOF) break; |
|
|
|
tape[i] = a; |
|
|
|
} |
|
|
@@ -194,15 +190,17 @@ intcode* read_file(char *filename, size_t buf_size) { |
|
|
|
v.tape = tape; |
|
|
|
v.index = 0; |
|
|
|
v.tape_l = i; |
|
|
|
v.relative_base = 0; |
|
|
|
return &v; |
|
|
|
} |
|
|
|
|
|
|
|
intcode *clone(intcode *m, size_t buf_size) { |
|
|
|
static intcode v; |
|
|
|
int* tape = calloc(buf_size, sizeof(int)); |
|
|
|
memcpy((void*) tape, (void*) m->tape, sizeof(int)*m->tape_l); |
|
|
|
long* tape = calloc(buf_size, sizeof(long)); |
|
|
|
memcpy((void*) tape, (void*) m->tape, sizeof(long)*m->tape_l); |
|
|
|
v.tape = tape; |
|
|
|
v.index = 0; |
|
|
|
v.tape_l = m->tape_l; |
|
|
|
v.relative_base = m->relative_base; |
|
|
|
return &v; |
|
|
|
} |