16
This commit is contained in:
parent
c21ff6800f
commit
6301b1f90c
22
16/CMakeLists.txt
Normal file
22
16/CMakeLists.txt
Normal file
@ -0,0 +1,22 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
enable_language(CXX)
|
||||
|
||||
project(AoC16)
|
||||
|
||||
if(APPLE)
|
||||
include_directories(/usr/local/include)
|
||||
link_directories(/usr/local/lib)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_executable(${CMAKE_PROJECT_NAME} WIN32)
|
||||
else()
|
||||
add_executable(${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
target_sources(${CMAKE_PROJECT_NAME}
|
||||
PRIVATE main.cpp
|
||||
)
|
1
16/input
Normal file
1
16/input
Normal file
@ -0,0 +1 @@
|
||||
40541D900AEDC01A88002191FE2F45D1006A2FC2388D278D4653E3910020F2E2F3E24C007ECD7ABA6A200E6E8017F92C934CFA0E5290B569CE0F4BA5180213D963C00DC40010A87905A0900021B0D624C34600906725FFCF597491C6008C01B0004223342488A200F4378C9198401B87311A0C0803E600FC4887F14CC01C8AF16A2010021D1260DC7530042C012957193779F96AD9B36100907A00980021513E3943600043225C1A8EB2C3040043CC3B1802B400D3CA4B8D3292E37C30600B325A541D979606E384B524C06008E802515A638A73A226009CDA5D8026200D473851150401E8BF16E2ACDFB7DCD4F5C02897A5288D299D89CA6AA672AD5118804F592FC5BE8037000042217C64876000874728550D4C0149F29D00524ACCD2566795A0D880432BEAC79995C86483A6F3B9F6833397DEA03E401004F28CD894B9C48A34BC371CF7AA840155E002012E21260923DC4C248035299ECEB0AC4DFC0179B864865CF8802F9A005E264C25372ABAC8DEA706009F005C32B7FCF1BF91CADFF3C6FE4B3FB073005A6F93B633B12E0054A124BEE9C570004B245126F6E11E5C0199BDEDCE589275C10027E97BE7EF330F126DF3817354FFC82671BB5402510C803788DFA009CAFB14ECDFE57D8A766F0001A74F924AC99678864725F253FD134400F9B5D3004A46489A00A4BEAD8F7F1F7497C39A0020F357618C71648032BB004E4BBC4292EF1167274F1AA0078902262B0D4718229C8608A5226528F86008CFA6E802F275E2248C65F3610066274CEA9A86794E58AA5E5BDE73F34945E2008D27D2278EE30C489B3D20336D00C2F002DF480AC820287D8096F700288082C001DE1400C50035005AA2013E5400B10028C009600A74001EF2004F8400C92B172801F0F4C0139B8E19A8017D96A510A7E698800EAC9294A6E985783A400AE4A2945E9170
|
311
16/main.cpp
Normal file
311
16/main.cpp
Normal file
@ -0,0 +1,311 @@
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
class Packet {
|
||||
public:
|
||||
Packet(int version, int type) : _version(version), _type(type) {}
|
||||
|
||||
void setValue(uint64_t value) {
|
||||
_has_value = true;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
void addSubPacket(Packet p) {
|
||||
_subs.push_back(std::move(p));
|
||||
}
|
||||
|
||||
int getVersion() const {
|
||||
return _version;
|
||||
}
|
||||
|
||||
int getType() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
uint64_t getValue() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
bool hasSubs() const {
|
||||
return _subs.size() != 0;
|
||||
}
|
||||
|
||||
const std::vector<Packet> &getSubs() const {
|
||||
return _subs;
|
||||
}
|
||||
|
||||
std::vector<Packet> &getSubs() {
|
||||
return _subs;
|
||||
}
|
||||
|
||||
bool hasValue() const {
|
||||
return _has_value;
|
||||
}
|
||||
|
||||
private:
|
||||
int _version;
|
||||
int _type;
|
||||
uint64_t _value{};
|
||||
bool _has_value = false;
|
||||
std::vector<Packet> _subs{};
|
||||
};
|
||||
|
||||
uint8_t getBitsFromChar(const char &c) {
|
||||
switch (c) {
|
||||
case 'A':
|
||||
return 0b1010;
|
||||
case 'B':
|
||||
return 0b1011;
|
||||
case 'C':
|
||||
return 0b1100;
|
||||
case 'D':
|
||||
return 0b1101;
|
||||
case 'E':
|
||||
return 0b1110;
|
||||
case 'F':
|
||||
return 0b1111;
|
||||
default:
|
||||
return c - '0';
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> getBits(const std::string &file_name) {
|
||||
std::vector<uint8_t> bits;
|
||||
|
||||
std::ifstream file(file_name);
|
||||
std::string str;
|
||||
std::getline(file, str);
|
||||
if (str.length() % 2 == 1) {
|
||||
bits.resize(str.length() / 2 + 1);
|
||||
} else {
|
||||
bits.resize(str.length() / 2);
|
||||
}
|
||||
for (size_t i = 0; i < str.length() / 2; i++) {
|
||||
bits[i] |= getBitsFromChar(str[i * 2]);
|
||||
bits[i] <<= 4;
|
||||
bits[i] |= getBitsFromChar(str[i * 2 + 1]);
|
||||
}
|
||||
if (str.length() % 2 == 1) {
|
||||
bits.back() |= getBitsFromChar(str.back());
|
||||
bits.back() <<= 4;
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint8_t getBit(const std::vector<uint8_t> &bits, uint64_t bitpos) {
|
||||
auto ind = bitpos / 8;
|
||||
auto bit = bitpos % 8;
|
||||
uint8_t comparator = 0;
|
||||
switch (bit) {
|
||||
case 0:
|
||||
comparator = 0b10000000;
|
||||
break;
|
||||
case 1:
|
||||
comparator = 0b01000000;
|
||||
break;
|
||||
case 2:
|
||||
comparator = 0b00100000;
|
||||
break;
|
||||
case 3:
|
||||
comparator = 0b00010000;
|
||||
break;
|
||||
case 4:
|
||||
comparator = 0b00001000;
|
||||
break;
|
||||
case 5:
|
||||
comparator = 0b00000100;
|
||||
break;
|
||||
case 6:
|
||||
comparator = 0b00000010;
|
||||
break;
|
||||
case 7:
|
||||
comparator = 0b00000001;
|
||||
break;
|
||||
}
|
||||
return bits[ind] & comparator ? 1 : 0;
|
||||
}
|
||||
|
||||
std::pair<uint64_t, uint64_t> getPacketValue(const std::vector<uint8_t> &bits,
|
||||
uint64_t size, uint64_t bitpos) {
|
||||
uint64_t result = 0;
|
||||
auto length = bitpos + size;
|
||||
while (bitpos < length) {
|
||||
uint8_t group = 0;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
group <<= 1;
|
||||
group |= getBit(bits, bitpos);
|
||||
bitpos++;
|
||||
}
|
||||
result <<= 4;
|
||||
result |= group & 0b00001111;
|
||||
if (!(group & 0b00010000)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return { bitpos, result };
|
||||
}
|
||||
|
||||
std::pair<uint64_t, Packet> bitsToPacket(const std::vector<uint8_t> &bits,
|
||||
uint64_t start, uint64_t size) {
|
||||
int version = 0;
|
||||
version |= getBit(bits, start);
|
||||
version <<= 1;
|
||||
version |= getBit(bits, start + 1);
|
||||
version <<= 1;
|
||||
version |= getBit(bits, start + 2);
|
||||
int type = 0;
|
||||
type |= getBit(bits, start + 3);
|
||||
type <<= 1;
|
||||
type |= getBit(bits, start + 4);
|
||||
type <<= 1;
|
||||
type |= getBit(bits, start + 5);
|
||||
|
||||
auto length = start + size;
|
||||
|
||||
uint64_t end = 0;
|
||||
Packet result(version, type);
|
||||
switch (type) {
|
||||
case 4: {
|
||||
auto res = getPacketValue(bits, size - 6, start + 6);
|
||||
result.setValue(res.second);
|
||||
end = res.first;
|
||||
} break;
|
||||
default:
|
||||
if (getBit(bits, start + 6)) {
|
||||
uint16_t count = 0;
|
||||
for (int i = 0; i < 11; i++) {
|
||||
count <<= 1;
|
||||
count |= getBit(bits, start + 7 + i);
|
||||
}
|
||||
|
||||
auto new_start = start + 7 + 11;
|
||||
for (int i = 0; i < count; i++) {
|
||||
auto res = bitsToPacket(bits, new_start, length - new_start);
|
||||
new_start = res.first;
|
||||
result.addSubPacket(std::move(res.second));
|
||||
}
|
||||
end = new_start;
|
||||
} else {
|
||||
uint16_t size = 0;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
size <<= 1;
|
||||
size |= getBit(bits, start + 7 + i);
|
||||
}
|
||||
|
||||
auto new_start = start + 7 + 15;
|
||||
auto sub_end = start + 7 + 15 + size;
|
||||
while (new_start < sub_end) {
|
||||
auto res = bitsToPacket(bits, new_start, size);
|
||||
size -= res.first - new_start;
|
||||
new_start = res.first;
|
||||
result.addSubPacket(std::move(res.second));
|
||||
}
|
||||
end = new_start;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return { end, result };
|
||||
}
|
||||
|
||||
uint64_t versionSum(const Packet &packet) {
|
||||
uint64_t sum = packet.getVersion();
|
||||
if (packet.hasSubs()) {
|
||||
for (auto &sub : packet.getSubs()) {
|
||||
sum += versionSum(sub);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
uint64_t part1(const Packet &packet) {
|
||||
return versionSum(packet);
|
||||
}
|
||||
|
||||
uint64_t calculatePacket(Packet &packet) {
|
||||
if (packet.hasValue()) {
|
||||
return packet.getValue();
|
||||
}
|
||||
uint64_t result = 0;
|
||||
switch (packet.getType()) {
|
||||
case 0:
|
||||
result = 0;
|
||||
for (auto &sub : packet.getSubs()) {
|
||||
result += calculatePacket(sub);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
result = 1;
|
||||
for (auto &sub : packet.getSubs()) {
|
||||
result *= calculatePacket(sub);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
result = -1;
|
||||
for (auto &sub : packet.getSubs()) {
|
||||
auto calc = calculatePacket(sub);
|
||||
if (calc < result) {
|
||||
result = calc;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
result = 0;
|
||||
for (auto &sub : packet.getSubs()) {
|
||||
auto calc = calculatePacket(sub);
|
||||
if (calc > result) {
|
||||
result = calc;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
result = packet.getValue();
|
||||
break;
|
||||
case 5:
|
||||
result = calculatePacket(packet.getSubs()[0]) >
|
||||
calculatePacket(packet.getSubs()[1])
|
||||
? 1
|
||||
: 0;
|
||||
break;
|
||||
case 6:
|
||||
result = calculatePacket(packet.getSubs()[0]) <
|
||||
calculatePacket(packet.getSubs()[1])
|
||||
? 1
|
||||
: 0;
|
||||
break;
|
||||
case 7:
|
||||
result = calculatePacket(packet.getSubs()[0]) ==
|
||||
calculatePacket(packet.getSubs()[1])
|
||||
? 1
|
||||
: 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
packet.setValue(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t part2(Packet &packet) {
|
||||
return calculatePacket(packet);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "You must provide input file!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
auto bits = getBits(argv[1]);
|
||||
auto packet = bitsToPacket(bits, 0, bits.size() * 8).second;
|
||||
std::cout << "Sum of all packet's versions is \033[91;1m" << part1(packet)
|
||||
<< "\033[0m." << std::endl;
|
||||
std::cout << "The resulting value of the outermost packet is \033[91;1m"
|
||||
<< part2(packet) << "\033[0m." << std::endl;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user