You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
4.2KB

  1. //
  2. // Created by red on 05/12/19.
  3. //
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include "intcode.h"
  8. ival out_val(long n) {
  9. ival v;
  10. v.type = IVAL_OUT;
  11. v.num = n;
  12. return v;
  13. }
  14. ival err_val(long n) {
  15. ival v;
  16. v.type = IVAL_ERR;
  17. v.err = n;
  18. return v;
  19. }
  20. ival end_val() {
  21. ival v;
  22. v.type = IVAL_END;
  23. return v;
  24. }
  25. ival cont_val() {
  26. ival v;
  27. v.type = IVAL_CONT;
  28. return v;
  29. }
  30. void ival_print(ival v) {
  31. switch (v.type) {
  32. case IVAL_ERR: {
  33. switch (v.err) {
  34. case IERR_OUT_OF_BOUNDS: printf("error: read/write out of bounds\n");
  35. break;
  36. case IERR_BAD_OP: printf("error: bad opcode\n");
  37. break;
  38. }
  39. }
  40. case IVAL_OUT: {
  41. printf("Output value: %ld\n", v.num);
  42. }
  43. }
  44. }
  45. int power (int base, int pow) {
  46. if (pow <= 0) return 1;
  47. else return base*power(base,pow-1);
  48. }
  49. void get_operands (intcode* m, long** operands) {
  50. long opcode = m->tape[m->index] / 100;
  51. for (size_t i = 0; i < 3; i++) {
  52. long addr_mode = opcode % 10;
  53. opcode = opcode / 10;
  54. long* v = 0;
  55. switch (addr_mode) {
  56. case 0: v = &m->tape[m->tape[m->index + i + 1]]; break;
  57. case 1: v = &m->tape[m->index + i + 1]; break;
  58. case 2: {
  59. long delta = m->tape[m->index + i + 1];
  60. v = &m->tape[m->relative_base + delta];
  61. }
  62. }
  63. operands[i] = v;
  64. }
  65. }
  66. ival op_add (intcode* m, long** operands) {
  67. *operands[2] = *operands[0] + *operands[1];
  68. m->index += 4;
  69. return cont_val();
  70. }
  71. ival op_mul (intcode* m, long** operands) {
  72. *operands[2] = *operands[0] * *operands[1];
  73. m->index += 4;
  74. return cont_val();
  75. }
  76. ival op_in (intcode* m, long** operands) {
  77. *operands[0] = m->input_tape[0];
  78. m->index += 2;
  79. m->input_tape = m->input_tape+1;
  80. return cont_val();
  81. }
  82. ival op_out (intcode* m, long** operands) {
  83. m->index += 2;
  84. long v = *operands[0];
  85. return out_val(v);
  86. }
  87. ival op_jnz (intcode* m, long** operands) {
  88. if (*operands[0] != 0) {
  89. m->index = (size_t) *operands[1];
  90. } else {
  91. m->index += 3;
  92. }
  93. return cont_val();
  94. }
  95. ival op_jez (intcode* m, long** operands) {
  96. if (*operands[0] == 0) {
  97. m->index = (size_t) *operands[1];
  98. } else {
  99. m->index += 3;
  100. }
  101. return cont_val();
  102. }
  103. ival op_lt (intcode* m, long** operands) {
  104. long result;
  105. if (*operands[0] < *operands[1]) {
  106. result = 1;
  107. } else result = 0;
  108. *operands[2] = result;
  109. m->index += 4;
  110. return cont_val();
  111. }
  112. ival op_eq (intcode* m, long** operands) {
  113. long result;
  114. if (*operands[0] == *operands[1]) {
  115. result = 1;
  116. } else result = 0;
  117. *operands[2] = result;
  118. m->index += 4;
  119. return cont_val();
  120. }
  121. ival op_rbs (intcode* m, long** operands) {
  122. m->relative_base += *operands[0];
  123. m->index += 2;
  124. return cont_val();
  125. }
  126. ival step (intcode* m) {
  127. long* operands[3];
  128. get_operands(m, operands);
  129. long opcode = m->tape[m->index];
  130. opcode = opcode % 100;
  131. switch (opcode) {
  132. case 99: return end_val();
  133. case 1: return op_add(m, operands);
  134. case 2: return op_mul(m, operands);
  135. case 3: return op_in(m, operands);
  136. case 4: return op_out(m, operands);
  137. case 5: return op_jnz(m, operands);
  138. case 6: return op_jez(m, operands);
  139. case 7: return op_lt(m, operands);
  140. case 8: return op_eq(m, operands);
  141. case 9: return op_rbs(m, operands);
  142. default: return err_val(IERR_BAD_OP);
  143. }
  144. }
  145. ival run (intcode* m) {
  146. for (;;) {
  147. //size_t i = m->index;
  148. //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]);
  149. ival v = step(m);
  150. switch (v.type) {
  151. case IVAL_ERR:
  152. case IVAL_END:
  153. case IVAL_OUT: return v;
  154. default: break;
  155. }
  156. }
  157. };
  158. intcode* read_file(char *filename, size_t buf_size) {
  159. long* tape = calloc(buf_size, sizeof(long));
  160. memset((void*) tape, 0, sizeof(long)*buf_size);
  161. FILE* file = fopen(filename, "r");
  162. size_t i;
  163. for (i = 0; i < buf_size; i++) {
  164. long a;
  165. long err = fscanf(file, "%ld,", &a);
  166. if (err == EOF) break;
  167. tape[i] = a;
  168. }
  169. static intcode v;
  170. v.tape = tape;
  171. v.index = 0;
  172. v.tape_l = i;
  173. v.relative_base = 0;
  174. return &v;
  175. }
  176. intcode *clone(intcode *m, size_t buf_size) {
  177. static intcode v;
  178. long* tape = calloc(buf_size, sizeof(long));
  179. memcpy((void*) tape, (void*) m->tape, sizeof(long)*m->tape_l);
  180. v.tape = tape;
  181. v.index = 0;
  182. v.tape_l = m->tape_l;
  183. v.relative_base = m->relative_base;
  184. return &v;
  185. }