|
@@ -0,0 +1,186 @@
|
|
|
+#define _GNU_SOURCE
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+int arraySize = 0;
|
|
|
+
|
|
|
+struct instruction {
|
|
|
+ char name[4];
|
|
|
+ int value;
|
|
|
+};
|
|
|
+
|
|
|
+void zeroArray(int *array) {
|
|
|
+ for (int i = 0; i < arraySize; i++)
|
|
|
+ array[i] = 0;
|
|
|
+}
|
|
|
+
|
|
|
+struct instruction **readInput(char *path) {
|
|
|
+ struct instruction **instructions = NULL;
|
|
|
+ FILE *fp = fopen(path, "r");
|
|
|
+ if (!fp) {
|
|
|
+ puts("Can't read");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ int index = 0;
|
|
|
+ while (1) {
|
|
|
+ struct instruction *p = malloc(sizeof(struct instruction));
|
|
|
+ if (!p) return NULL;
|
|
|
+
|
|
|
+ if (1 > fscanf(fp, "%s %d\n", p->name, &(p->value)))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+
|
|
|
+ arraySize++;
|
|
|
+ struct instruction **newInstructions = realloc(instructions, sizeof(struct instruction*)*arraySize);
|
|
|
+ if (!newInstructions) return NULL;
|
|
|
+ instructions = newInstructions;
|
|
|
+ instructions[index] = p;
|
|
|
+ index++;
|
|
|
+
|
|
|
+ if (feof(fp)) break;
|
|
|
+ }
|
|
|
+
|
|
|
+ fclose(fp);
|
|
|
+ return instructions;
|
|
|
+}
|
|
|
+
|
|
|
+int processInstructions(struct instruction **instructions, int *executed) {
|
|
|
+ int acc = 0;
|
|
|
+ int index = 0;
|
|
|
+ while(1) {
|
|
|
+ if (index < 0 || index >= arraySize) break;
|
|
|
+ if (executed[index]) break;
|
|
|
+
|
|
|
+ struct instruction *currentInstruction = instructions[index];
|
|
|
+ if (0 == (strcmp("nop", currentInstruction->name))) {
|
|
|
+ executed[index] = 1;
|
|
|
+ index++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (0 == (strcmp("acc", currentInstruction->name))) {
|
|
|
+ acc += currentInstruction->value;
|
|
|
+ executed[index] = 1;
|
|
|
+ index++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (0 == (strcmp("jmp", currentInstruction->name))) {
|
|
|
+ executed[index] = 1;
|
|
|
+ index += currentInstruction->value;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return acc;
|
|
|
+}
|
|
|
+
|
|
|
+int checkArray(struct instruction **instructions, int *executed, int index) {
|
|
|
+ int executedCheck[arraySize];
|
|
|
+ zeroArray(executedCheck);
|
|
|
+
|
|
|
+ while(1) {
|
|
|
+ if (index < 0 || index >= arraySize) break;
|
|
|
+ if (executed[index] || executedCheck[index]) break;
|
|
|
+
|
|
|
+ struct instruction *currentInstruction = instructions[index];
|
|
|
+ if (0 == (strcmp("nop", currentInstruction->name))) {
|
|
|
+ executedCheck[index] = 1;
|
|
|
+ index++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (0 == (strcmp("acc", currentInstruction->name))) {
|
|
|
+ executedCheck[index] = 1;
|
|
|
+ index++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (0 == (strcmp("jmp", currentInstruction->name))) {
|
|
|
+ executedCheck[index] = 1;
|
|
|
+ index += currentInstruction->value;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return index == arraySize;
|
|
|
+}
|
|
|
+
|
|
|
+int fixTheLoop(struct instruction **instructions, int *executed) {
|
|
|
+ int acc = 0;
|
|
|
+ int index = 0;
|
|
|
+ int changed = 0;
|
|
|
+ while(1) {
|
|
|
+ if (index < 0 || index >= arraySize) break;
|
|
|
+ if (executed[index]) break;
|
|
|
+
|
|
|
+ struct instruction *currentInstruction = instructions[index];
|
|
|
+ if (0 == (strcmp("nop", currentInstruction->name))) {
|
|
|
+ executed[index] = 1;
|
|
|
+
|
|
|
+ if (!changed && checkArray(instructions, executed, index+currentInstruction->value)) {
|
|
|
+ changed = 1;
|
|
|
+ index += currentInstruction->value;
|
|
|
+ }
|
|
|
+ else index++;
|
|
|
+
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (0 == (strcmp("acc", currentInstruction->name))) {
|
|
|
+ acc += currentInstruction->value;
|
|
|
+ executed[index] = 1;
|
|
|
+ index++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (0 == (strcmp("jmp", currentInstruction->name))) {
|
|
|
+ executed[index] = 1;
|
|
|
+
|
|
|
+ if (!changed && checkArray(instructions, executed, index+1)) {
|
|
|
+ changed = 1;
|
|
|
+ index++;
|
|
|
+ }
|
|
|
+
|
|
|
+ else index += currentInstruction->value;
|
|
|
+
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (changed) return acc;
|
|
|
+ return 1000000000;
|
|
|
+}
|
|
|
+
|
|
|
+void freeInstructions(struct instruction **instructions) {
|
|
|
+ for (int i = 0; i < arraySize; i++)
|
|
|
+ free(instructions[i]);
|
|
|
+
|
|
|
+ free(instructions);
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, char **argv)
|
|
|
+{
|
|
|
+ if (argc < 2) {
|
|
|
+ puts("You need to specify path to file!");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ struct instruction **instructions = readInput(argv[1]);
|
|
|
+ if (!instructions) {
|
|
|
+ puts("Can't read array!");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ int executed[arraySize];
|
|
|
+ zeroArray(executed);
|
|
|
+
|
|
|
+ printf("Part1: %d\n", processInstructions(instructions, executed));
|
|
|
+
|
|
|
+ zeroArray(executed);
|
|
|
+ printf("Part2: %d\n", fixTheLoop(instructions, executed));
|
|
|
+
|
|
|
+ freeInstructions(instructions);
|
|
|
+}
|