Skip to content

Instantly share code, notes, and snippets.

@weirddan455
Created December 17, 2021 00:24
Show Gist options
  • Save weirddan455/1fffb4466090e7421c080788199cc783 to your computer and use it in GitHub Desktop.
Save weirddan455/1fffb4466090e7421c080788199cc783 to your computer and use it in GitHub Desktop.
Advent of Code Day 16
#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