advent2023

Advent of Code 2023 solutions
git clone git://bsandro.tech/advent2023
Log | Files | Refs | LICENSE

puzzle.c (3200B)


      1 #define _DEFAULT_SOURCE
      2 
      3 #include <limits.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <errno.h>
      7 #include <string.h>
      8 #include <strings.h>
      9 #include <assert.h>
     10 #include <stdbool.h>
     11 
     12 #define STR_LEN 2048
     13 
     14 bool is_digit(char b) {
     15 	return b>='0' && b<='9';
     16 }
     17 
     18 typedef enum LinePart {
     19 	LINE_PART_NONE,
     20 	LINE_PART_CARD,
     21 	LINE_PART_WINS,
     22 	LINE_PART_NUMS
     23 } LinePart;
     24 
     25 typedef struct Card {
     26 	int id;
     27 	int count;
     28 	int wins;
     29 	struct Card *next;
     30 } Card;
     31 
     32 Card * make_card() {
     33 	Card *c = malloc(sizeof(Card));
     34 	memset(c, 0, sizeof(Card));
     35 	return c;
     36 }
     37 
     38 void print_cards(Card *first) {
     39 	Card *c = first;
     40 	while (c!=NULL) {
     41 		printf("%d: %d\n", c->id, c->wins);
     42 		c = c->next;
     43 	}
     44 }
     45 
     46 typedef struct Number {
     47 	int value;
     48 	struct Number *next;
     49 } Number;
     50 
     51 Number * make_number(int val) {
     52 	Number *num = malloc(sizeof(Number));
     53 	memset(num, 0, sizeof(Number));
     54 	num->value = val;
     55 	return num;
     56 }
     57 
     58 void print_numbers(Number *first) {
     59 	Number *n = first;
     60 	while (n!=NULL) {
     61 		printf("%d -> ", n->value);
     62 		n = n->next;
     63 	}
     64 	printf("\n");
     65 }
     66 
     67 void puzzle(const char *filename, long long *result1, long long *result2) {
     68 	FILE *infile = fopen(filename, "r");
     69 	if (infile == NULL) {
     70 		fprintf(stderr, "fopen() error: %s\n", strerror(errno));
     71 		return;
     72 	}
     73 
     74 	char buf[STR_LEN] = {0};
     75 	unsigned int line_num = 0;
     76 
     77 	*result1 = 0;
     78 	*result2 = 0;
     79 
     80 	Card *cards = NULL;
     81 	Card *card_last = NULL;
     82 
     83 	while (fgets(buf, STR_LEN, infile) != NULL) {
     84 		Number *wins = NULL;
     85 		Number *wins_last = NULL;
     86 		Number *nums = NULL;
     87 		Number *nums_last = NULL;
     88 		Card *card = make_card();
     89 		int len = strlen(buf);
     90 		int i = 0;
     91 		LinePart part = LINE_PART_CARD;
     92 		int num = 0;
     93 		while (i<len) {
     94 			if (part==LINE_PART_CARD && buf[i]==':') {
     95 				part = LINE_PART_WINS;
     96 				card->id = num;
     97 				card->count = 1;
     98 				if (cards==NULL) cards = card;
     99 				if (card_last!=NULL) card_last->next = card;
    100 				card_last = card;
    101 				num = 0;
    102 			} else if (part==LINE_PART_WINS && buf[i]=='|') {
    103 				part = LINE_PART_NUMS;
    104 			} else if (is_digit(buf[i])) {
    105 				num = num*10 + buf[i] - '0';
    106 			} else if (part!=LINE_PART_CARD && (buf[i]==' '||buf[i]==10) && num!=0) {
    107 				if (part==LINE_PART_WINS) {
    108 					Number *n = make_number(num);
    109 					if (wins==NULL) wins=n;
    110 					if (wins_last!=NULL) wins_last->next = n;
    111 					wins_last = n;
    112 				} else if (part==LINE_PART_NUMS) {
    113 					Number *n = make_number(num);
    114 					if (nums==NULL) nums=n;
    115 					if (nums_last!=NULL) nums_last->next = n;
    116 					nums_last = n;
    117 				}
    118 				num=0;
    119 			}
    120 			++i;
    121 		}
    122 
    123 		int score = 0;
    124 		for (Number *n = nums; n!=NULL; n=n->next) {
    125 			for (Number *w = wins; w!=NULL; w=w->next) {
    126 				if (n->value==w->value) {
    127 					card->wins++;
    128 					if (score==0) score=1;
    129 					else score*=2;
    130 				}
    131 			}
    132 		}
    133 		*result1 += score;
    134 
    135 		++line_num;
    136 		bzero(buf, STR_LEN);
    137 	}
    138 
    139 	int cnt = card_last->id;
    140 	int copies[cnt];
    141 	memset(&copies, 0, sizeof(int)*cnt);
    142 	for (int i=0; i<cnt; ++i) {
    143 		copies[i] = 1;
    144 	}
    145 
    146 	Card *card = cards;
    147 	while (card!=NULL) {
    148 		int cid = card->id-1;
    149 		for (int j=0; j<copies[cid]; ++j) {
    150 			for (int i=1; i<=card->wins; ++i) {
    151 				copies[cid+i]++;
    152 			}
    153 		}
    154 		card = card->next;
    155 	}
    156 	for (int i=0; i<cnt; ++i) {
    157 		*result2 += copies[i];
    158 	}
    159 
    160 	// mutiny! ignoring feof/ferror.
    161 	fclose(infile);
    162 }