mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 12:50:32 +01:00
Implement 2025 day 5 in C
This commit is contained in:
1
2025/day05/.gitignore
vendored
Normal file
1
2025/day05/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
solve
|
||||||
6
2025/day05/Makefile
Normal file
6
2025/day05/Makefile
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
CFLAGS=-Wall -Wextra -O2 -g
|
||||||
|
|
||||||
|
all: solve
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) solve
|
||||||
12
2025/day05/README.md
Normal file
12
2025/day05/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Day 05: C
|
||||||
|
|
||||||
|
C is weird. It's a very simple language but it's made complicated by the fact that you have to do
|
||||||
|
everything yourself. Relatively straightforward solution.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ make
|
||||||
|
cc -Wall -Wextra -O2 -g solve.c -o solve
|
||||||
|
$ ./solve sample.txt
|
||||||
|
Part1: 3
|
||||||
|
Part2: 14
|
||||||
|
```
|
||||||
11
2025/day05/sample.txt
Normal file
11
2025/day05/sample.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
3-5
|
||||||
|
10-14
|
||||||
|
16-20
|
||||||
|
12-18
|
||||||
|
|
||||||
|
1
|
||||||
|
5
|
||||||
|
8
|
||||||
|
11
|
||||||
|
17
|
||||||
|
32
|
||||||
160
2025/day05/solve.c
Normal file
160
2025/day05/solve.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX(a,b) \
|
||||||
|
({ __typeof__ (a) _a = (a); \
|
||||||
|
__typeof__ (b) _b = (b); \
|
||||||
|
_a > _b ? _a : _b; })
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t start;
|
||||||
|
uint64_t end;
|
||||||
|
} range_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t length;
|
||||||
|
size_t capacity;
|
||||||
|
range_t* buffer;
|
||||||
|
} ranges_t;
|
||||||
|
|
||||||
|
static int cmp_range(void const* va, void const* vb) {
|
||||||
|
range_t const* a = va;
|
||||||
|
range_t const* b = vb;
|
||||||
|
|
||||||
|
if (a->start == b->start) {
|
||||||
|
return (a->end > b->end) - (a->end < b->end);
|
||||||
|
} else {
|
||||||
|
return (a->start > b->start) - (a->start < b-> start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simplify_ranges(ranges_t* ranges) {
|
||||||
|
// First, sort ranges ascending by start (then end)
|
||||||
|
qsort(ranges->buffer, ranges->length, sizeof(range_t), cmp_range);
|
||||||
|
|
||||||
|
const size_t length = ranges->length;
|
||||||
|
range_t* write_ptr = &ranges->buffer[0];
|
||||||
|
|
||||||
|
// Important, skip the first iteration, it can never be merged
|
||||||
|
for (size_t i = 1; i < length; ++i) {
|
||||||
|
if (ranges->buffer[i].start <= write_ptr->end) {
|
||||||
|
// Merge the two ranges
|
||||||
|
write_ptr->end = MAX(write_ptr->end, ranges->buffer[i].end);
|
||||||
|
ranges->length--;
|
||||||
|
} else {
|
||||||
|
write_ptr++;
|
||||||
|
if (write_ptr != &ranges->buffer[i]) {
|
||||||
|
memcpy(write_ptr, &ranges->buffer[i], sizeof(range_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (size_t i = 0; i < ranges->length; ++i) {
|
||||||
|
// printf("%" PRIu64 "-%" PRIu64 "\n", ranges->buffer[i].start, ranges->buffer[i].end);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// printf("Original length: %u, new length: %u\n", (unsigned int) length, (unsigned int) ranges->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_fresh(const uint64_t ingredient, ranges_t const * const ranges) {
|
||||||
|
size_t min = 0;
|
||||||
|
size_t size = ranges->length;
|
||||||
|
range_t const* buffer = ranges->buffer;
|
||||||
|
|
||||||
|
while (size > 1) {
|
||||||
|
size_t half = size / 2;
|
||||||
|
size_t mid = min + half;
|
||||||
|
|
||||||
|
if (buffer[mid].start <= ingredient) {
|
||||||
|
min = mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
size -= half;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer[min].start <= ingredient && buffer[min].end >= ingredient;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(const int argc, char const** argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("Usage: %s <input>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ranges_t ranges = {
|
||||||
|
.length = 0,
|
||||||
|
.capacity = 2,
|
||||||
|
.buffer = malloc(2 * sizeof(range_t)),
|
||||||
|
};
|
||||||
|
|
||||||
|
FILE* input = fopen(argv[1], "r");
|
||||||
|
if (input == NULL) {
|
||||||
|
perror("failed to open file");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ingredient;
|
||||||
|
bool seen_first = false;
|
||||||
|
|
||||||
|
while (!seen_first) {
|
||||||
|
uint64_t start;
|
||||||
|
uint64_t end;
|
||||||
|
|
||||||
|
switch (fscanf(input, "%" PRIu64 "-%" PRIu64, &start, &end)) {
|
||||||
|
case 1:
|
||||||
|
seen_first = true;
|
||||||
|
ingredient = start;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (ranges.capacity == ranges.length) {
|
||||||
|
size_t new_capacity = ranges.capacity * 2;
|
||||||
|
range_t* buffer = realloc(ranges.buffer, new_capacity * sizeof(range_t));
|
||||||
|
if (buffer == NULL) {
|
||||||
|
printf("Failed to resize ranges buffer\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ranges.capacity = new_capacity;
|
||||||
|
ranges.buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ranges.buffer[ranges.length].start = start;
|
||||||
|
ranges.buffer[ranges.length].end = end;
|
||||||
|
ranges.length++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unexpected end of file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simplify_ranges(&ranges);
|
||||||
|
|
||||||
|
int total_fresh = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (is_fresh(ingredient, &ranges)) {
|
||||||
|
total_fresh++;
|
||||||
|
}
|
||||||
|
} while (fscanf(input, "%" PRIu64 "\n", &ingredient) == 1);
|
||||||
|
|
||||||
|
printf("Part1: %u\n", total_fresh);
|
||||||
|
|
||||||
|
uint64_t combined_fresh = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ranges.length; ++i) {
|
||||||
|
combined_fresh += ranges.buffer[i].end - ranges.buffer[i].start + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Part2: %" PRIu64 "\n", combined_fresh);
|
||||||
|
|
||||||
|
fclose(input);
|
||||||
|
free(ranges.buffer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user