commit 9b245784798f928a344ae72ca76b7b26f5474600
parent d4c5a6f75ea3a06a0c5f819dd8ccfdec689128cd
Author: bsandro <[email protected]>
Date: Fri, 17 Dec 2021 02:58:32 +0200
Day 16, puzzle 1
Diffstat:
11 files changed, 254 insertions(+), 0 deletions(-)
diff --git a/day16/Makefile b/day16/Makefile
@@ -0,0 +1,25 @@
+NAME=$(shell basename ${PWD})
+SRC=$(wildcard *.c ../common/*.c)
+DEPS:=$(wildcard *.h ../common/*.h)
+OBJ:=$(SRC:.c=.o)
+CFLAGS=-O0 -g -std=c99 -Werror -Wall -Wextra -I. -I../common
+LDFLAGS=-lc
+
+all: $(NAME)
+
+.PHONY: clean run
+
+clean:
+ rm -f $(OBJ) $(NAME)
+
+%.o : %.c $(DEPS)
+ @$(CC) $(CFLAGS) -c $< -o $@
+
+$(NAME): $(OBJ)
+ @$(CC) $(OBJ) -o $@ $(LDFLAGS)
+
+run: $(NAME)
+ @./$(NAME) input.txt
+
+test: $(NAME)
+ @./$(NAME) test4.txt
diff --git a/day16/input.txt b/day16/input.txt
@@ -0,0 +1 @@
+420D610055D273AF1630010092019207300B278BE5932551E703E608400C335003900AF0402905009923003880856201E95C00B60198D400B50034400E20101DC00E10024C00F1003C400B000212697140249D049F0F8952A8C6009780272D5D074B5741F3F37730056C0149658965E9AED7CA8401A5CC45BB801F0999FFFEEE0D67050C010C0036278A62D4D737F359993398027800BECFD8467E3109945C1008210C9C442690A6F719C48A351006E9359C1C5003E739087E80F27EC29A0030322BD2553983D272C67508E5C0804639D4BD004C401B8B918E3600021D1061D47A30053801C89EF2C4CCFF39204C53C212DABED04C015983A9766200ACE7F95C80D802B2F3499E5A700267838803029FC56203A009CE134C773A2D3005A77F4EDC6B401600043A35C56840200F4668A71580043D92D5A02535BAF7F9A89CF97C9F59A4F02C400C249A8CF1A49331004CDA00ACA46517E8732E8D2DB90F3005E92362194EF5E630CA5E5EEAD1803E200CC228E70700010A89D0BE3A08033146164177005A5AEEB1DA463BDC667600189C9F53A6FF6D6677954B27745CA00BCAE53A6EEDC60074C920001B93CFB05140289E8FA4812E071EE447218CBE1AA149008DBA00A497F9486262325FE521898BC9669B382015365715953C5FC01AA8002111721D4221007E13C448BA600B4F77F694CE6C01393519CE474D46009D802C00085C578A71E4001098F518639CC301802B400E7CDDF4B525C8E9CA2188032600E44B8F1094C0198CB16A29180351EA1DC3091F47A5CA0054C4234BDBC2F338A77B84F201232C01700042A0DC7A8A0200CC578B10A65A000601048B24B25C56995A30056C013927D927C91AB43005D127FDC610EF55273F76C96641002A4F0F8C01CCC579A8D68E52587F982996F537D600
diff --git a/day16/main.c b/day16/main.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+
+void puzzle(const char *filename, long long *res1, long long *res2);
+
+int main(int argc, char *argv[]) {
+ printf("Advent of Code: day 16\n");
+ double time_start = clock();
+
+ if (argc <= 1) {
+ printf("Usage: %s inputfile.txt\n", argv[0]);
+ return -1;
+ }
+
+ const char *filename = argv[1];
+ long long counter1 = -1;
+ long long counter2 = -1;
+
+ puzzle(filename, &counter1, &counter2);
+
+ printf("Puzzle #1: %lld\n", counter1);
+ printf("Puzzle #2: %lld\n", counter2);
+
+ double elapsed = clock() - time_start;
+ printf("Elapsed: %f\n", elapsed / CLOCKS_PER_SEC);
+
+ return 0;
+}
diff --git a/day16/puzzle.c b/day16/puzzle.c
@@ -0,0 +1,192 @@
+#define _DEFAULT_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+
+#define BUF_SIZE 16
+
+struct packet_t {
+ uint8_t version;
+ uint8_t type;
+ uint32_t value;
+ uint16_t packets_size;
+ struct packet_t **packets;
+};
+
+uint8_t hex2int(const int symbol);
+char * int2bin(const uint8_t digit);
+uint16_t str2int(char *str, size_t size);
+uint32_t get_value(char *str, size_t *offset);
+struct packet_t * get_packet(char *str, size_t *offset);
+uint32_t calc_packet_sum(struct packet_t *packet);
+void delete_packet(struct packet_t *packet);
+
+void puzzle(const char *filename, long long *result1, long long *result2) {
+ FILE *infile = fopen(filename, "r");
+ if (infile == NULL) {
+ fprintf(stderr, "fopen() error: %s\n", strerror(errno));
+ return;
+ }
+
+ *result1 = 0;
+ *result2 = 0;
+
+ int symbol = 0;
+ char *binary = NULL;
+ size_t binary_size = 1;
+
+ binary = malloc(binary_size);
+ assert(binary != NULL);
+ binary[0] = '\0';
+
+ while ((symbol = fgetc(infile)) != EOF) {
+ if (symbol == '\n') break;
+ uint8_t digit = hex2int(symbol);
+ binary_size += 4;
+ binary = realloc(binary, binary_size);
+ strlcat(binary, int2bin(digit), binary_size);
+ }
+
+ size_t offset = 0;
+ struct packet_t *packet = get_packet(binary, &offset);
+ assert(packet != NULL);
+ //printf("final offset: %zu\n", offset);
+ *result1 = calc_packet_sum(packet);
+
+ delete_packet(packet);
+ free(binary);
+ // mutiny! ignoring feof/ferror.
+ fclose(infile);
+}
+
+uint32_t calc_packet_sum(struct packet_t *packet) {
+ uint32_t sum = packet->version;
+ if (packet->type != 4) {
+ for (uint16_t i = 0; i < packet->packets_size; ++i) {
+ sum += calc_packet_sum(packet->packets[i]);
+ }
+ }
+ return sum;
+}
+
+void delete_packet(struct packet_t *packet) {
+ if (packet->type != 4) {
+ for (uint16_t i = 0; i < packet->packets_size; ++i) {
+ delete_packet(packet->packets[i]);
+ }
+ }
+ free(packet);
+}
+
+uint8_t hex2int(const int symbol) {
+ if (symbol >= '0' && symbol <= '9') {
+ return symbol - '0';
+ } else if (symbol >= 'A' && symbol <= 'F') {
+ return symbol - 'A' + 10;
+ }
+ return 0;
+}
+
+char * int2bin(const uint8_t digit) {
+ static char bin[5];
+ int cnt = 0;
+ // only "lower" 4 bits
+ for (int i = 8; i > 0; i >>= 1) {
+ bin[cnt++] = ((digit & i) == i) ? '1' : '0';
+ }
+ bin[4] = '\0';
+ return bin;
+}
+
+uint16_t str2int(char *str, size_t size) {
+ assert(size < BUF_SIZE);
+
+ static char data[BUF_SIZE] = {0};
+ strlcpy(data, str, size+1);
+
+ return strtoull(data, NULL, 2);
+}
+
+struct packet_t * get_packet(char *str, size_t *offset) {
+ struct packet_t *packet = malloc(sizeof(struct packet_t));
+ bzero(packet, sizeof(struct packet_t));
+
+ //printf("%s\n", str);
+ size_t total_offset = 0;
+
+ packet->version = str2int(str+total_offset, 3);
+ total_offset += 3;
+ packet->type = str2int(str+total_offset, 3);
+ total_offset += 3;
+
+ //printf("type: %u\n", packet->type);
+ //printf("version: %u\n", packet->version);
+
+ if (packet->type == 4) { // literal values type
+ size_t local_offset = 0;
+ packet->value = get_value(str+total_offset, &local_offset);
+ //printf("value: %u\n", packet->value);
+ total_offset += local_offset;
+
+ } else { // operator packet
+ uint16_t len_type = str2int(str+total_offset, 1);
+ total_offset += 1;
+ uint16_t len = 0;
+
+ if (len_type == 0) { // next 15 bits are length in bits
+ len = str2int(str+total_offset, 15);
+ //printf("length nested packets: %u bits\n", len);
+ total_offset += 15;
+
+ size_t sum_offset = 0;
+ packet->packets_size = 0;
+ while (sum_offset < len) {
+ packet->packets_size++;
+ size_t local_offset = 0;
+ struct packet_t *p = get_packet(str+total_offset, &local_offset);
+ assert(p != NULL);
+ sum_offset += local_offset;
+ total_offset += local_offset;
+ packet->packets = realloc(packet->packets, packet->packets_size * sizeof(void *));
+ packet->packets[packet->packets_size - 1] = p;
+ }
+ *offset = sum_offset;
+ } else { // next 11 bits are number of packets
+ len = str2int(str+total_offset, 11);
+ total_offset += 11;
+ //printf("number of nested packets: %u\n", len);
+ packet->packets_size = len;
+ packet->packets = calloc(len, sizeof(void *));
+ for (uint16_t i = 0; i < len; ++i) {
+ size_t local_offset = 0;
+ struct packet_t *p = get_packet(str+total_offset, &local_offset);
+ assert(p != NULL);
+ total_offset += local_offset;
+ packet->packets[i] = p;
+ }
+ }
+ }
+
+ *offset = total_offset;
+
+ return packet;
+}
+
+uint32_t get_value(char *str, size_t *offset) {
+ uint32_t value = 0;
+ size_t local_offset = 0;
+ uint16_t flag = 1;
+ while (flag == 1) {
+ flag = str2int(str+local_offset, 1);
+ local_offset += 1;
+ uint16_t val = str2int(str+local_offset, 4);
+ value = (value << 4) + val;
+ local_offset += 4;
+ }
+ *offset = local_offset;
+ return value;
+}
diff --git a/day16/test1.txt b/day16/test1.txt
@@ -0,0 +1 @@
+D2FE28
diff --git a/day16/test2.txt b/day16/test2.txt
@@ -0,0 +1 @@
+38006F45291200
diff --git a/day16/test3.txt b/day16/test3.txt
@@ -0,0 +1 @@
+EE00D40C823060
diff --git a/day16/test4.txt b/day16/test4.txt
@@ -0,0 +1 @@
+8A004A801A8002F478
diff --git a/day16/test5.txt b/day16/test5.txt
@@ -0,0 +1 @@
+620080001611562C8802118E34
diff --git a/day16/test6.txt b/day16/test6.txt
@@ -0,0 +1 @@
+C0015000016115A2E0802F182340
diff --git a/day16/test7.txt b/day16/test7.txt
@@ -0,0 +1 @@
+A0016C880162017C3686B18A3D4780