|  | @@ -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);
 | 
	
		
			
				|  |  | +}
 |