Files
AdventOfCode2023/01/01-part2.c
2023-12-04 19:40:03 -05:00

133 lines
3.6 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
// How much memory to allocate for each line
#define MAX_LINE_LEN 200
#define DEFAULT_FILE "input.txt"
// Returns 0 if a string is not a number (e.g. 'two')
// Otherwise, returns the equivilant ascii character digit.
// Only works for single digits.
// Only accepts lower case.
char parse_num(char *str)
{
const char *num_strings[10] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
// The lengths of the strings above,
const uint8_t num_string_lens[10] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4 };
bool possible_nums[10] = { [0 ... 9] = true };
uint8_t num_idx = 0;
uint8_t char_incriment = 0;
char current;
bool result_still_possible = false;
for (char_incriment = 0; char_incriment < 6; char_incriment++)
{
// Grab out next character in the string
current = *(str + char_incriment);
for (num_idx = 0; num_idx < 10; num_idx++)
{
if (!possible_nums[num_idx]) continue;
// If we have passed the end of our number string and every character has matched,
// then we return our valid character.
if (char_incriment == num_string_lens[num_idx] && possible_nums[num_idx]) return (num_idx + '0');
// If the character is not the letter it should be, disqualify this number.
// e.g. if num_idx == 1 and char_incriment == 2, current should equal 'e'
// because 'e' is the 3rd number in the word 'one.'
if (current != num_strings[num_idx][char_incriment]) possible_nums[num_idx] = false;
else result_still_possible = true;
}
if (!result_still_possible) return 0;
}
return 0;
}
// Returns a string of the next line.
// Remember to free() this after you're finished.
// Limited by MAX_LINE_LEN (I'm lazy.)
char *next_line(FILE *file)
{
char *strbuf = malloc(sizeof(char) * MAX_LINE_LEN);
uint8_t idx = 0;
char current = 0;
while (current != '\n' && current != EOF)
{
current = fgetc(file);
strbuf[idx] = current;
idx++;
}
return strbuf;
}
int main(int argc, char **argv) {
// Get filename as an argument
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;
}
int8_t firstdigit = -1;
int8_t lastdigit = -1;
int8_t parsed_num = -1;
uint32_t sum = 0;
char current = 0;
char *strbuf = next_line(file);
uint8_t strbuf_idx = 0;
while (current != EOF)
{
parsed_num = parse_num(strbuf + strbuf_idx);
current = strbuf[strbuf_idx++];
if (current == '\n')
{
if (lastdigit == -1) lastdigit = firstdigit;
sum += (firstdigit * 10) + lastdigit;
firstdigit = -1;
lastdigit = -1;
strbuf_idx = 0;
free(strbuf);
strbuf = next_line(file);
continue;
}
if (parsed_num != 0) current = parsed_num;
if (current < '0' || current > '9') continue;
if (firstdigit == -1)
{
firstdigit = current - '0';
}
else
{
lastdigit = current - '0';
}
}
printf("Sum: %d\n", sum);
return 0;
}