Created
December 17, 2021 00:24
-
-
Save weirddan455/1fffb4466090e7421c080788199cc783 to your computer and use it in GitHub Desktop.
Advent of Code Day 16
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <fcntl.h> | |
#include <unistd.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
uint64_t versionSum; | |
uint8_t *binary; | |
uint8_t getBit(size_t *position) | |
{ | |
uint8_t byte = binary[*position / 8]; | |
byte = byte >> (7 - (*position % 8)); | |
byte = byte & 1; | |
(*position)++; | |
return byte; | |
} | |
uint16_t readBits(size_t *position, int numBits) | |
{ | |
uint16_t value = 0; | |
for (int i = numBits - 1; i >= 0; i--) | |
{ | |
uint16_t bit = getBit(position); | |
bit = bit << i; | |
value = value | bit; | |
} | |
return value; | |
} | |
uint64_t parsePacket(size_t *position) | |
{ | |
uint16_t version = readBits(position, 3); | |
versionSum += version; | |
uint16_t type = readBits(position, 3); | |
switch(type) | |
{ | |
case 4: | |
{ | |
uint64_t value = 0; | |
size_t tempPos = *position; | |
uint8_t moreLiterals = getBit(&tempPos); | |
tempPos += 4; | |
int literals = 1; | |
while (moreLiterals) | |
{ | |
moreLiterals = getBit(&tempPos); | |
tempPos += 4; | |
literals++; | |
} | |
for (int i = literals - 1; i >= 0; i--) | |
{ | |
(*position)++; | |
uint64_t bits = readBits(position, 4); | |
bits = bits << (4 * i); | |
value = value | bits; | |
} | |
return value; | |
} | |
case 0: | |
{ | |
uint64_t value = 0; | |
uint8_t lengthType = getBit(position); | |
if (lengthType == 0) | |
{ | |
uint16_t length = readBits(position, 15); | |
size_t startingPosition = *position; | |
uint16_t bitsRead = 0; | |
while (bitsRead < length) | |
{ | |
value += parsePacket(position); | |
bitsRead = *position - startingPosition; | |
} | |
} | |
else | |
{ | |
uint16_t subpackets = readBits(position, 11); | |
for (uint16_t i = 0; i < subpackets; i++) | |
{ | |
value += parsePacket(position); | |
} | |
} | |
return value; | |
} | |
case 1: | |
{ | |
uint64_t value = 1; | |
uint8_t lengthType = getBit(position); | |
if (lengthType == 0) | |
{ | |
uint16_t length = readBits(position, 15); | |
size_t startingPosition = *position; | |
uint16_t bitsRead = 0; | |
while (bitsRead < length) | |
{ | |
value *= parsePacket(position); | |
bitsRead = *position - startingPosition; | |
} | |
} | |
else | |
{ | |
uint16_t subpackets = readBits(position, 11); | |
for (uint16_t i = 0; i < subpackets; i++) | |
{ | |
value *= parsePacket(position); | |
} | |
} | |
return value; | |
} | |
case 2: | |
{ | |
uint64_t value = UINT64_MAX; | |
uint8_t lengthType = getBit(position); | |
if (lengthType == 0) | |
{ | |
uint16_t length = readBits(position, 15); | |
size_t startingPosition = *position; | |
uint16_t bitsRead = 0; | |
while (bitsRead < length) | |
{ | |
uint64_t sv = parsePacket(position); | |
bitsRead = *position - startingPosition; | |
if (sv < value) | |
{ | |
value = sv; | |
} | |
} | |
} | |
else | |
{ | |
uint16_t subpackets = readBits(position, 11); | |
for (uint16_t i = 0; i < subpackets; i++) | |
{ | |
uint64_t sv = parsePacket(position); | |
if (sv < value) | |
{ | |
value = sv; | |
} | |
} | |
} | |
return value; | |
} | |
case 3: | |
{ | |
uint64_t value = 0; | |
uint8_t lengthType = getBit(position); | |
if (lengthType == 0) | |
{ | |
uint16_t length = readBits(position, 15); | |
size_t startingPosition = *position; | |
uint16_t bitsRead = 0; | |
while (bitsRead < length) | |
{ | |
uint64_t sv = parsePacket(position); | |
bitsRead = *position - startingPosition; | |
if (sv > value) | |
{ | |
value = sv; | |
} | |
} | |
} | |
else | |
{ | |
uint16_t subpackets = readBits(position, 11); | |
for (uint16_t i = 0; i < subpackets; i++) | |
{ | |
uint64_t sv = parsePacket(position); | |
if (sv > value) | |
{ | |
value = sv; | |
} | |
} | |
} | |
return value; | |
} | |
case 5: | |
{ | |
uint8_t lengthType = getBit(position); | |
if (lengthType == 0) | |
{ | |
*position += 15; | |
} | |
else | |
{ | |
*position += 11; | |
} | |
uint64_t sv = parsePacket(position); | |
uint64_t sv2 = parsePacket(position); | |
if (sv > sv2) | |
{ | |
return 1; | |
} | |
else | |
{ | |
return 0; | |
} | |
} | |
case 6: | |
{ | |
uint8_t lengthType = getBit(position); | |
if (lengthType == 0) | |
{ | |
*position += 15; | |
} | |
else | |
{ | |
*position += 11; | |
} | |
uint64_t sv = parsePacket(position); | |
uint64_t sv2 = parsePacket(position); | |
if (sv < sv2) | |
{ | |
return 1; | |
} | |
else | |
{ | |
return 0; | |
} | |
} | |
case 7: | |
{ | |
uint8_t lengthType = getBit(position); | |
if (lengthType == 0) | |
{ | |
*position += 15; | |
} | |
else | |
{ | |
*position += 11; | |
} | |
uint64_t sv = parsePacket(position); | |
uint64_t sv2 = parsePacket(position); | |
if (sv == sv2) | |
{ | |
return 1; | |
} | |
else | |
{ | |
return 0; | |
} | |
} | |
} | |
return 0; | |
} | |
int main() | |
{ | |
int fd = open("input", O_RDONLY); | |
if (fd == -1) | |
{ | |
perror("open"); | |
return 1; | |
} | |
struct stat fileInfo; | |
if (fstat(fd, &fileInfo) != 0) | |
{ | |
perror("fstat"); | |
close(fd); | |
return 1; | |
} | |
uint8_t *data = malloc(fileInfo.st_size); | |
if (data == NULL) | |
{ | |
puts("malloc failed"); | |
close(fd); | |
return 1; | |
} | |
ssize_t bytesRead = read(fd, data, fileInfo.st_size); | |
close(fd); | |
if (bytesRead == -1) | |
{ | |
perror("read"); | |
free(data); | |
return 1; | |
} | |
if (bytesRead != fileInfo.st_size) | |
{ | |
printf("Error: read %d bytes. %d expected.\n", bytesRead, fileInfo.st_size); | |
free(data); | |
return 1; | |
} | |
size_t hexSize = 0; | |
while (hexSize < bytesRead && data[hexSize] != '\n') | |
{ | |
hexSize++; | |
} | |
if (hexSize % 2 != 0) | |
{ | |
puts("Incorrect hex size (not divisible by 2)"); | |
free(data); | |
return 1; | |
} | |
size_t binarySize = hexSize / 2; | |
binary = malloc(binarySize); | |
if (binary == NULL) | |
{ | |
puts("malloc failed"); | |
free(data); | |
return 1; | |
} | |
size_t hexIndex = 0; | |
size_t binaryIndex = 0; | |
while (hexIndex < hexSize) | |
{ | |
uint8_t byte = 0; | |
for (int i = 0; i < 2; i++) | |
{ | |
uint8_t c = data[hexIndex++]; | |
if (c > 47 && c < 58) | |
{ | |
c -= 48; | |
} | |
else if (c > 64 && c < 71) | |
{ | |
c -= 55; | |
} | |
else | |
{ | |
puts("Invalid character found in input"); | |
free(data); | |
free(binary); | |
return 1; | |
} | |
if (i == 0) | |
{ | |
c = c << 4; | |
} | |
byte = byte | c; | |
} | |
binary[binaryIndex++] = byte; | |
} | |
free(data); | |
size_t position = 0; | |
uint64_t evaluation = parsePacket(&position); | |
free(binary); | |
printf("Version Sum: %lu\nEvaluation: %lu\n", versionSum, evaluation); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment