days 1 and 2

This commit is contained in:
yequari 2023-12-03 08:34:59 -07:00
commit 99a2a4f996
8 changed files with 572 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
bin
input

8
day1/Makefile Normal file
View File

@ -0,0 +1,8 @@
part1: part1.c
gcc -Wall -g -o bin/part1 part1.c
part2: part2.c
gcc -Wall -g -o bin/part2 part2.c
.PHONY: clean
clean:
rm part1 part2

78
day1/part1.c Normal file
View File

@ -0,0 +1,78 @@
#include <ctype.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';
}
}
void extract_digits(char* str, char *first, char *last)
{
char *p,*q,*r;
p = str;
while (*p != '\0' && !isdigit(*p))
p++; // find first digit
*first = *last = *p;
q = p;
while (*q != '\0') // find digits until end of string
{
q++;
if (isdigit(*q))
{
*last = *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%s", value, buffer);
sum += value;
}
printf("%ld", sum);
return EXIT_SUCCESS;
}

136
day1/part2.c Normal file
View File

@ -0,0 +1,136 @@
#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;
}

8
day2/Makefile Normal file
View File

@ -0,0 +1,8 @@
part1: part1.c
gcc -Wall -g -o bin/part1 part1.c
part2: part2.c
gcc -Wall -g -o bin/part2 part2.c
.PHONY: clean
clean:
rm part1 part2

215
day2/part1.c Normal file
View File

@ -0,0 +1,215 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <regex.h>
#include <string.h>
typedef struct elfgame {
long number;
struct elfgame_play *plays;
struct elfgame *next;
} elfgame;
typedef struct elfgame_play {
long red, blue, green;
struct elfgame_play *next;
} elfgame_play;
elfgame *first_game;
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';
}
}
long get_gamenum(char* line)
{
regex_t regex;
char pattern[] = "Game ([0-9]+):.*";
regmatch_t pmatch[2];
if (regcomp(&regex, pattern, REG_EXTENDED))
{
fprintf(stderr, "error compiling regex");
return -1;
}
int rc = regexec(&regex, line, 2, pmatch, 0);
if (rc)
{
char buf[2048];
regerror(rc, &regex, buf, 2048);
fprintf(stderr, "error execing regex");
return -1;
}
return strtoul(line + pmatch[1].rm_so, NULL, 10);
}
elfgame_play *parse_play(char *line, int offset)
{
regex_t regex;
regmatch_t pmatch[3];
char pattern[] = "([0-9]+)[[:space:]](red|green|blue);?";
char *s = line;
elfgame_play *p = malloc(sizeof(elfgame_play));
if (p == NULL)
{
fprintf(stderr, "OOM");
return NULL;
}
p->red = p->blue = p->green = 0;
if (regcomp(&regex, pattern, REG_EXTENDED))
{
fprintf(stderr, "error compiling regex");
return NULL;
}
for (int i = 0; ; i++)
{
if (regexec(&regex, s, 3, pmatch, 0))
break;
if (s >= line + offset)
break;
long count = strtoul(s + pmatch[1].rm_so, NULL, 10);
if (strncmp(s + pmatch[2].rm_so, "red", 3) == 0)
{
p->red += count;
}
if (strncmp(s + pmatch[2].rm_so, "blue", 4) == 0)
{
p->blue += count;
}
if (strncmp(s + pmatch[2].rm_so, "green", 5) == 0)
{
p->green += count;
}
s += pmatch[0].rm_eo;
}
regfree(&regex);
return p;
}
elfgame_play *parse_plays(char* line, int offset)
{
regex_t regex;
regmatch_t pmatch[3];
char pattern[] = "([0-9]+)[[:space:]](red|blue|green)";
char *s = line;
elfgame_play *first = malloc(sizeof(elfgame_play));
if (first == NULL)
{
fprintf(stderr, "OOM");
return NULL;
}
elfgame_play *cur = first;
if (regcomp(&regex, pattern, REG_EXTENDED))
{
fprintf(stderr, "error compiling regex");
return NULL;
}
for (int i = 0; ; i++)
{
if (regexec(&regex, s, 3, pmatch, 0))
break;
if (s > line + offset)
break;
elfgame_play *p = malloc(sizeof(elfgame_play));
if (p == NULL)
{
fprintf(stderr, "OOM");
return NULL;
}
p->red = p->blue = p->green = 0;
long count = strtoul(s + pmatch[1].rm_so, NULL, 10);
if (strncmp(s + pmatch[2].rm_so, "red", 3) == 0)
{
p->red += count;
}
if (strncmp(s + pmatch[2].rm_so, "blue", 4) == 0)
{
p->blue += count;
}
if (strncmp(s + pmatch[2].rm_so, "green", 5) == 0)
{
p->green += count;
}
cur->next = p;
cur = cur->next;
s += pmatch[0].rm_eo;
}
return first;
}
elfgame *parse_game(char* line)
{
regex_t regex;
regmatch_t pmatch[4];
char pattern[] = "(([0-9]+)[[:space:]](red|blue|green),?[[:space:]]?)+;?";
if (regcomp(&regex, pattern, REG_EXTENDED))
{
fprintf(stderr, "error compiling regex");
return NULL;
}
char *s = line;
elfgame *g = malloc(sizeof(elfgame));
if (g == NULL)
{
return NULL;
}
g->number = get_gamenum(line);
elfgame_play *dummy = malloc(sizeof(elfgame_play));
if (dummy == NULL)
{
return NULL;
}
dummy->red = dummy->green = dummy->blue = 0;
elfgame_play *cur = dummy;
g->plays = dummy;
for (int i = 0; ; i++)
{
if(regexec(&regex, s, 4, pmatch, 0))
break;
cur->next = parse_play(line, pmatch[0].rm_eo);
cur = cur->next;
s += pmatch[0].rm_eo;
}
regfree(&regex);
return g;
}
int main(int argc, char *argv[])
{
char buffer[2048];
FILE* input = fopen("input", "r");
if (input == NULL)
{
fprintf(stderr, "error opening file");
return EXIT_FAILURE;
}
long sum = 0;
first_game = malloc(sizeof(elfgame));
if (first_game == NULL)
{
fprintf(stderr, "OOM");
return EXIT_FAILURE;
}
elfgame *cur = first_game;
while(true)
{
read_line(buffer, input);
if (feof(input))
break;
elfgame *g = parse_game(buffer);
cur->next = g;
cur = cur->next;
}
printf("%ld", sum);
return EXIT_SUCCESS;
}

63
day2/part1.py Normal file
View File

@ -0,0 +1,63 @@
import re
class Game:
def __init__(self, id, r=0, b=0, g=0):
self.id = id
self.red = r
self.blue = b
self.green = g
def __str__(self):
return f'game: {self.id}, max_red={self.red}, max_blue={self.blue}, max_green={self.green}'
game_pattern = re.compile(r'Game ([0-9]+):\s(.*)')
play_pattern = re.compile(r'([0-9]+)\s(red|green|blue)')
total_red = 12
total_blue = 14
total_green = 13
def parse_game(line):
m = game_pattern.search(line)
plays = m.groups()[1].split('; ')
game = Game(int(m.groups()[0]))
for play in plays:
counts = play.split(', ')
for c in counts:
r = b = g = 0
pm = play_pattern.search(c)
if pm.groups()[1] == 'red':
r = int(pm.groups()[0])
if pm.groups()[1] == 'blue':
b = int(pm.groups()[0])
if pm.groups()[1] == 'green':
g = int(pm.groups()[0])
game.red = max(game.red, r)
game.blue = max(game.blue, b)
game.green = max(game.green, g)
return game
def main():
games = []
with open('input', 'r') as f:
while True:
line = f.readline()
if not line:
break
games.append(parse_game(line))
sum = 0
for g in games:
if g.red > total_red or g.blue > total_blue or g.green > total_green:
continue
sum += g.id
print(sum)
if __name__ == '__main__':
main()

62
day2/part2.py Normal file
View File

@ -0,0 +1,62 @@
import re
class Game:
def __init__(self, id, r=0, b=0, g=0):
self.id = id
self.red = r
self.blue = b
self.green = g
def __str__(self):
return f'game: {self.id}, max_red={self.red}, max_blue={self.blue}, max_green={self.green}'
game_pattern = re.compile(r'Game ([0-9]+):\s(.*)')
play_pattern = re.compile(r'([0-9]+)\s(red|green|blue)')
total_red = 12
total_blue = 14
total_green = 13
def parse_game(line):
m = game_pattern.search(line)
plays = m.groups()[1].split('; ')
game = Game(int(m.groups()[0]))
for play in plays:
counts = play.split(', ')
for c in counts:
r = b = g = 0
pm = play_pattern.search(c)
if pm.groups()[1] == 'red':
r = int(pm.groups()[0])
if pm.groups()[1] == 'blue':
b = int(pm.groups()[0])
if pm.groups()[1] == 'green':
g = int(pm.groups()[0])
game.red = max(game.red, r)
game.blue = max(game.blue, b)
game.green = max(game.green, g)
return game
def main():
games = []
with open('input', 'r') as f:
while True:
line = f.readline()
if not line:
break
games.append(parse_game(line))
sum = 0
for g in games:
power = g.red * g.blue * g.green
sum += power
print(sum)
if __name__ == '__main__':
main()