Committing days 1-4
This commit is contained in:
158
03/03-part2.c
Normal file
158
03/03-part2.c
Normal file
@@ -0,0 +1,158 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define STRBUF_SIZE 200
|
||||
#define DEFAULT_FILE "input.txt"
|
||||
#define ISDIGIT(X) (X >= '0' && X <= '9')
|
||||
|
||||
// Parses a found number.
|
||||
// The provided location can be any digit of the
|
||||
// number; this function will automatically
|
||||
// seek the first digit before processing.
|
||||
// Erases numbers as they are processed.
|
||||
uint16_t parse_num_at(char *str, uint8_t idx)
|
||||
{
|
||||
|
||||
// Check input
|
||||
if (str[idx] < '0' || str[idx] > '9') return 0;
|
||||
|
||||
// Find first digit of number
|
||||
while (ISDIGIT(str[idx]) && idx) idx--;
|
||||
if (!ISDIGIT(str[idx])) idx++;
|
||||
|
||||
uint16_t num = 0;
|
||||
|
||||
// Add up all digits
|
||||
while (ISDIGIT(str[idx]))
|
||||
{
|
||||
num = (num * 10) + (str[idx] - '0');
|
||||
// Erase the number to make sure we don't count it twice
|
||||
str[idx] = '.';
|
||||
idx++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
// If the character is a * with two adjacent numbers,
|
||||
// returns the gear ratio. Returns zero if the symbol
|
||||
// is not a gear.
|
||||
uint64_t get_gear_ratio( uint8_t idx,
|
||||
char *above,
|
||||
char *current,
|
||||
char *below)
|
||||
{
|
||||
char *above_copy = malloc(sizeof(char) * STRBUF_SIZE);
|
||||
char *current_copy = malloc(sizeof(char) * STRBUF_SIZE);
|
||||
char *below_copy = malloc(sizeof(char) * STRBUF_SIZE);
|
||||
|
||||
memcpy(above_copy, above, STRBUF_SIZE);
|
||||
memcpy(current_copy, current, STRBUF_SIZE);
|
||||
memcpy(below_copy, below, STRBUF_SIZE);
|
||||
|
||||
uint16_t nums[8] = {0};
|
||||
|
||||
if (idx) nums[0] = parse_num_at(above_copy, idx - 1);
|
||||
nums[1] = parse_num_at(above_copy, idx);
|
||||
nums[2] = parse_num_at(above_copy, idx + 1);
|
||||
|
||||
nums[3] = parse_num_at(current_copy, idx + 1);
|
||||
nums[4] = parse_num_at(current_copy, idx - 1);
|
||||
|
||||
if (idx) nums[5] = parse_num_at(below_copy, idx - 1);
|
||||
nums[6] = parse_num_at(below_copy, idx);
|
||||
nums[7] = parse_num_at(below_copy, idx + 1);
|
||||
|
||||
free(above_copy);
|
||||
free(current_copy);
|
||||
free(below_copy);
|
||||
|
||||
uint8_t i = 0;
|
||||
uint16_t num1 = 0;
|
||||
uint16_t num2 = 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
// More than 2 adjacent numbers
|
||||
if (nums[i] && num1 && num2) return 0;
|
||||
|
||||
// The second number
|
||||
if (nums[i] && num1) num2 = nums[i];
|
||||
|
||||
// The first number
|
||||
else if (nums[i]) num1 = nums[i];
|
||||
}
|
||||
|
||||
return num1 * num2;
|
||||
}
|
||||
|
||||
// Search through a line of *current for symbols.
|
||||
uint64_t parse_line(char *above, char *current, char *below)
|
||||
{
|
||||
uint64_t sum = 0;
|
||||
uint8_t idx;
|
||||
char c;
|
||||
|
||||
for (idx = 0; current[idx] != 0; idx++)
|
||||
{
|
||||
c = current[idx];
|
||||
if (c == '*')
|
||||
{
|
||||
// We've found a symbol,
|
||||
// add up all numbers around it
|
||||
sum += get_gear_ratio(idx, above, current, below);
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Get filename as an argument, defaults to "input.txt"
|
||||
char *path = (argc > 1) ? argv[1] : DEFAULT_FILE;
|
||||
|
||||
if (!path)
|
||||
{
|
||||
printf("Requires input file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE *file = fopen(path, "r");
|
||||
|
||||
if (!file)
|
||||
{
|
||||
printf("Could not find file.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *above = malloc(sizeof(char) * STRBUF_SIZE);
|
||||
char *current = malloc(sizeof(char) * STRBUF_SIZE);
|
||||
char *below = malloc(sizeof(char) * STRBUF_SIZE);
|
||||
|
||||
memset(above, '.', STRBUF_SIZE);
|
||||
fgets(current, STRBUF_SIZE, file);
|
||||
|
||||
uint64_t sum = 0;
|
||||
|
||||
while (fgets(below, 200, file))
|
||||
{
|
||||
sum += parse_line(above, current, below);
|
||||
|
||||
free(above);
|
||||
above = current;
|
||||
current = below;
|
||||
below = malloc(sizeof(char) * STRBUF_SIZE);
|
||||
memset(below, '.', STRBUF_SIZE);
|
||||
}
|
||||
|
||||
// Process the last line of the file
|
||||
sum += parse_line(above, current, below);
|
||||
|
||||
printf("Sum: %lud\n", sum);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user