|
|
@@ -49,57 +49,122 @@ void ival_print(ival v) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int power (int base, int pow) { |
|
|
|
if (pow <= 0) return 1; |
|
|
|
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; |
|
|
|
opcode = opcode / 10; |
|
|
|
int v = 0; |
|
|
|
if (addr_mode == 0) { |
|
|
|
v = m->tape[m->tape[m->index+i+1]]; |
|
|
|
} |
|
|
|
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]; |
|
|
|
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]; |
|
|
|
m->index += 4; |
|
|
|
free((void*) operands); |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_in (intcode* m) { |
|
|
|
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(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_out (intcode* m) { |
|
|
|
int* operands = get_operands(m, 1); |
|
|
|
m->index += 2; |
|
|
|
int v = operands[0]; |
|
|
|
free((void*) operands); |
|
|
|
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]; |
|
|
|
} else { |
|
|
|
m->index += 3; |
|
|
|
} |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_jez (intcode* m) { |
|
|
|
int* operands = get_operands(m, 2); |
|
|
|
if (operands[0] == 0) { |
|
|
|
m->index = (size_t) operands[1]; |
|
|
|
} else { |
|
|
|
m->index += 3; |
|
|
|
} |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_lt (intcode* m) { |
|
|
|
int* operands = get_operands(m,2); |
|
|
|
int result; |
|
|
|
if (operands[0] < operands[1]) { |
|
|
|
result = 1; |
|
|
|
} else result = 0; |
|
|
|
m->tape[m->tape[m->index+3]] = result; |
|
|
|
m->index += 4; |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
ival op_eq (intcode* m) { |
|
|
|
int* operands = get_operands(m,2); |
|
|
|
int result; |
|
|
|
if (operands[0] == operands[1]) { |
|
|
|
result = 1; |
|
|
|
} else result = 0; |
|
|
|
m->tape[m->tape[m->index+3]] = result; |
|
|
|
m->index += 4; |
|
|
|
return cont_val(); |
|
|
|
} |
|
|
|
|
|
|
|
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(); |
|
|
|
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); |
|
|
|
default: return err_val(IERR_BAD_OP); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
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]); |
|
|
|
//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: |