Skip to content

Instantly share code, notes, and snippets.

@willkill07
Created December 4, 2024 17:21
Show Gist options
  • Save willkill07/ea3234c33edda64258727e0dd9a705f0 to your computer and use it in GitHub Desktop.
Save willkill07/ea3234c33edda64258727e0dd9a705f0 to your computer and use it in GitHub Desktop.
Advent of Code 2024 Day 3 in C (custom parser)
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
enum state_type {
Skip, SawM, SawU, SAW_L, SawD, SawO, SawN, SawT,
SawComma, SawQuote,
SawDigitA, SawDigitB,
SawParenMul, SawParenDo, SawParenDont
};
int main(int argc, char* argv[]) {
if (argc == 1) {
exit(1);
}
int fd = open(argv[1], O_RDONLY);
if (fd == -1) {
exit(1);
}
struct stat s;
if (fstat(fd, &s) == -1) {
exit(1);
}
char const* addr = (char const*)mmap(nullptr, (size_t)s.st_size, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0);
if (addr == nullptr) {
exit(1);
}
char const* end = addr + s.st_size;
int a = 0, b = 0, part1 = 0, part2 = 0, valid = 1;
enum state_type state = Skip;
for (char const* c = addr; c != end; ++c) {
switch(*c) {
case 'm': state = SawM; continue;
case 'u': if (state == SawM) state = SawU; continue;
case 'l': if (state == SawU) state = SAW_L; continue;
case 'd': state = SawD; continue;
case 'o': if (state == SawD) state = SawO; continue;
case 'n': if (state == SawO) state = SawN; continue;
case '\'': if (state == SawN) state = SawQuote; continue;
case 't': if (state == SawQuote) state = SawT; continue;
case ',': if (state == SawDigitA) state = SawComma; continue;
case '(':
switch (state) {
case SAW_L: state = SawParenMul; a = 0; b = 0; continue;
case SawO: state = SawParenDo; continue;
case SawT: state = SawParenDont; continue;
default: break;
}
break;
case ')':
switch (state) {
case SawDigitB: part1 += a * b; if (valid) part2 += a * b; break;
case SawParenDo: valid = true; break;
case SawParenDont: valid = false; break;
default: break;
}
break;
default:
if ('0' <= *c && *c <= '9') {
switch (state) {
case SawParenMul: state = SawDigitA; [[fallthrough]];
case SawDigitA: a = a * 10 + (*c - '0'); continue;
case SawComma: state = SawDigitB; [[fallthrough]];
case SawDigitB: b = b * 10 + (*c - '0'); continue;
default: break;
}
}
}
state = Skip;
}
munmap((void*)addr, (size_t)s.st_size);
close(fd);
char buffer[256];
write(0, buffer, (size_t)snprintf(buffer, 255, "%d %d\n", part1, part2));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment