185 lines
3.8 KiB
C
185 lines
3.8 KiB
C
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define DEFAULT_FILE "input.txt"
|
|
#define STRBUF_LEN 300
|
|
#define ISDIGIT(X) (X >= '0' && X <= '9')
|
|
#define NUM_ARR_LEN 300
|
|
#define NUM_DIFFS 300
|
|
|
|
#define REVERSE_ARR 1
|
|
|
|
|
|
bool all_zeroes(int *num_arr, int len)
|
|
{
|
|
int i = 0;
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
if (num_arr[i]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int parse_num(char *str)
|
|
{
|
|
bool isnegative = false;
|
|
if (*str == '-')
|
|
{
|
|
isnegative = true;
|
|
str++;
|
|
}
|
|
uint64_t num = 0;
|
|
while (ISDIGIT(*str))
|
|
{
|
|
num = (num * 10) + (*str - '0');
|
|
str++;
|
|
}
|
|
return isnegative ? -num : num;
|
|
}
|
|
|
|
void reverse_arr(int *num_arr, int len)
|
|
{
|
|
int i = 0;
|
|
int temp;
|
|
for (i = 0; i < (len / 2); i++)
|
|
{
|
|
temp = num_arr[i];
|
|
num_arr[i] = num_arr[len - i - 1];
|
|
num_arr[len - i - 1] = temp;
|
|
}
|
|
}
|
|
|
|
int parse_nums(char *str, int *num_arr)
|
|
{
|
|
int i = 0;
|
|
|
|
while (*str != '\n')
|
|
{
|
|
if (*str == ' ') str++;
|
|
num_arr[i] = parse_num(str);
|
|
i++;
|
|
while (ISDIGIT(*str) || *str == '-') str++;
|
|
}
|
|
|
|
|
|
#if (REVERSE_ARR)
|
|
int k = 0;
|
|
int temp;
|
|
for (k = 0; k < (i / 2); k++)
|
|
{
|
|
temp = num_arr[k];
|
|
num_arr[k] = num_arr[i - k - 1];
|
|
num_arr[i - k - 1] = temp;
|
|
}
|
|
#endif
|
|
|
|
return i;
|
|
}
|
|
|
|
void print_arr(int *num_arr, int len)
|
|
{
|
|
int i = 0;
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
printf("%d ", num_arr[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
void calc_diff(int num_arr_len, int num_arr[num_arr_len], int diff_arr[num_arr_len - 1])
|
|
{
|
|
int i = 0;
|
|
for (i = 0; i < (num_arr_len - 1); i++)
|
|
{
|
|
diff_arr[i] = num_arr[i + 1] - num_arr[i];
|
|
}
|
|
}
|
|
|
|
int calc_all_diffs(int diffs_arr[NUM_DIFFS][NUM_ARR_LEN], int lens_arr[NUM_DIFFS])
|
|
{
|
|
int k = 0;
|
|
while (!all_zeroes(diffs_arr[k], lens_arr[k]))
|
|
{
|
|
calc_diff(lens_arr[k], diffs_arr[k], diffs_arr[k + 1]);
|
|
lens_arr[k + 1] = lens_arr[k] - 1;
|
|
k++;
|
|
}
|
|
|
|
memset(diffs_arr[k], 0, sizeof(int) * NUM_ARR_LEN);
|
|
|
|
return k;
|
|
}
|
|
|
|
#define PREDICT_NEXT(num_arr, num_arr_len, diffs) (num_arr[num_arr_len - 1] + diffs[num_arr_len - 1])
|
|
|
|
int predict_next_val(int diffs_arr[NUM_DIFFS][NUM_ARR_LEN], int *lens_arr, int depth)
|
|
{
|
|
while (depth)
|
|
{
|
|
depth--;
|
|
int len = lens_arr[depth];
|
|
|
|
int *current_arr = diffs_arr[depth];
|
|
int *diff = diffs_arr[depth + 1];
|
|
|
|
int current_arr_last_val = current_arr[len - 1];
|
|
int diff_last_val = diff[len - 1];
|
|
|
|
int next = current_arr_last_val + diff_last_val;
|
|
diffs_arr[depth][len] = next;
|
|
print_arr(diffs_arr[depth], lens_arr[depth] + 1);
|
|
}
|
|
return diffs_arr[0][lens_arr[0]];
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
// Get filename as an argument, if there is one
|
|
char *path = (argc > 1) ? argv[1] : DEFAULT_FILE;
|
|
|
|
if (!path)
|
|
{
|
|
printf("Requires input file.\n");
|
|
return 1;
|
|
}
|
|
|
|
FILE *file = fopen(path, "r");
|
|
char strbuf[STRBUF_LEN] = {0};
|
|
|
|
if (!file)
|
|
{
|
|
printf("Could not find file.");
|
|
return 1;
|
|
}
|
|
|
|
// Begin challenge
|
|
|
|
// diffs_arr[0] is a single line of the puzzle input
|
|
// diffs_arr[0][0] is the first int of the first line
|
|
int diffs_arr[NUM_DIFFS][NUM_ARR_LEN];
|
|
|
|
// Length of each diff arr
|
|
int lens_arr[NUM_DIFFS] = {0};
|
|
|
|
int i = 0;
|
|
uint64_t sum = 0;
|
|
|
|
while (fgets(strbuf, STRBUF_LEN, file))
|
|
{
|
|
if (strbuf[0] == '\n') break;
|
|
lens_arr[0] = parse_nums(strbuf, diffs_arr[0]);
|
|
|
|
int depth = calc_all_diffs(diffs_arr, lens_arr);
|
|
|
|
int next_val = predict_next_val(diffs_arr, lens_arr, depth);
|
|
|
|
sum += next_val;
|
|
}
|
|
|
|
printf("Sum: %lu\n", sum);
|
|
|
|
return 0;
|
|
} |