137 lines
3.0 KiB
C
137 lines
3.0 KiB
C
|
#include <ctype.h>
|
||
|
#include <string.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdbool.h>
|
||
|
|
||
|
/*
|
||
|
* Each line of the input file contains a string with a mix of letters and digits
|
||
|
* Each line's "calibration value" is a single two digit number, made up of the first and last
|
||
|
* digit found in the string
|
||
|
* Print out the sum of all the calibration values.
|
||
|
*/
|
||
|
|
||
|
char buffer[2048];
|
||
|
|
||
|
void read_line(char* linebuf, FILE* file)
|
||
|
{
|
||
|
char* str = fgets(linebuf, 2048, file);
|
||
|
if (feof(file))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (str == NULL)
|
||
|
{
|
||
|
fprintf(stderr, "Fgets error");
|
||
|
linebuf[0] = '\0';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool parse_digit(const char* str, char* result, int* n)
|
||
|
{
|
||
|
char* nums[] = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
|
||
|
int numslen[] = {3, 3, 5, 4, 4, 3, 5, 5, 4};
|
||
|
char numschar[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||
|
for (int i = 0; i < 9; i++)
|
||
|
{
|
||
|
if(strncmp(str, nums[i], numslen[i]) == 0)
|
||
|
{
|
||
|
*result = numschar[i];
|
||
|
*n = numslen[i];
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void extract_digits(char* str, char *first, char *last)
|
||
|
{
|
||
|
char *p,*q;
|
||
|
p = str;
|
||
|
int n;
|
||
|
bool found = false;
|
||
|
while (*p != '\0' && !found)
|
||
|
{
|
||
|
switch(*p)
|
||
|
{
|
||
|
case 'o':
|
||
|
case 't':
|
||
|
case 'f':
|
||
|
case 's':
|
||
|
case 'e':
|
||
|
case 'n':
|
||
|
if(parse_digit(p, first, &n))
|
||
|
{
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
if (isdigit(*p))
|
||
|
{
|
||
|
*first = *p;
|
||
|
found = true;
|
||
|
}
|
||
|
else
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
q = p;
|
||
|
*last = *first;
|
||
|
while (*q != '\0') // find next digit
|
||
|
{
|
||
|
switch(*q)
|
||
|
{
|
||
|
case 'o':
|
||
|
case 't':
|
||
|
case 'f':
|
||
|
case 's':
|
||
|
case 'e':
|
||
|
case 'n':
|
||
|
if(parse_digit(q, last, &n))
|
||
|
{
|
||
|
q++;
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
if (isdigit(*q))
|
||
|
{
|
||
|
*last = *q;
|
||
|
}
|
||
|
q++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
long convert_chars(char first, char last)
|
||
|
{
|
||
|
char num[3] = { first, last, '\0' };
|
||
|
return strtoul(num, NULL, 10);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
FILE* input = fopen("input", "r");
|
||
|
if (input == NULL)
|
||
|
{
|
||
|
fprintf(stderr, "error opening file");
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
long sum = 0;
|
||
|
char first, last;
|
||
|
|
||
|
while(true)
|
||
|
{
|
||
|
read_line(buffer, input);
|
||
|
if (feof(input))
|
||
|
break;
|
||
|
extract_digits(buffer, &first, &last);
|
||
|
long value = convert_chars(first, last);
|
||
|
printf("%ld\t%c\t%c\t%s", value, first, last, buffer);
|
||
|
sum += value;
|
||
|
}
|
||
|
|
||
|
printf("%ld", sum);
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|