day16: finished part2 (C++)

master
Clyne 3 years ago
parent 5cc9e45db5
commit 2833c43111

@ -40,14 +40,10 @@
(if (every? #(= \0 %) data) (if (every? #(= \0 %) data)
['() vcnt] ['() vcnt]
(do (do
(println "Version: " version)
(if-let [value (take-literal-value data)] (if-let [value (take-literal-value data)]
(do [(second value) (+ vcnt version)]
(println "Value:" (first value))
[(second value) (+ vcnt version)])
(do (do
(let [info (take-operator (drop 3 data))] (let [info (take-operator (drop 3 data))]
(println "Subpacket:")
(if (= :bits (get info 2)) (if (= :bits (get info 2))
(loop [inpt [(subs (first info) 0 (get info 1)) (+ vcnt version)]] (loop [inpt [(subs (first info) 0 (get info 1)) (+ vcnt version)]]
(if (empty? (first inpt)) (if (empty? (first inpt))
@ -67,5 +63,5 @@
(process-packet))] (process-packet))]
(if (not (empty? (first packet))) (if (not (empty? (first packet)))
(recur (process-packet packet)) (recur (process-packet packet))
(println packet))) (println (second packet))))

@ -0,0 +1,131 @@
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <list>
#include <map>
#include <string>
#include <string_view>
#include <tuple>
static const std::map<char, const char *> hexToBin = {
{'0', "0000"}, {'1', "0001"}, {'2', "0010"}, {'3', "0011"},
{'4', "0100"}, {'5', "0101"}, {'6', "0110"}, {'7', "0111"},
{'8', "1000"}, {'9', "1001"}, {'A', "1010"}, {'B', "1011"},
{'C', "1100"}, {'D', "1101"}, {'E', "1110"}, {'F', "1111"}
};
static std::pair<uint64_t, std::string_view> solve(std::string_view packet);
int main(int argc, const char *argv[])
{
if (argc != 2)
return -1;
std::string packetBin;
std::string packetHex (argv[1]);
for (char c : packetHex)
packetBin += hexToBin.at(c);
std::cout << solve(packetBin).first << std::endl;
return 0;
}
uint64_t binStrToInt(std::string_view bin)
{
uint64_t n = 0;
for (char c : bin) {
n = n * 2ull;
if (c == '1')
++n;
}
return n;
}
bool isEmptyPacket(std::string_view packet)
{
return packet.empty() ||
std::all_of(packet.cbegin(), packet.cend(),
[](char c) { return c == '0'; });
}
std::pair<uint64_t, std::string_view> solve(std::string_view packet)
{
// Remove version
packet = packet.substr(3);
// Pull type ID
const auto typeId = packet.substr(0, 3);
packet = packet.substr(3);
if (typeId == "100") {
std::string numberStr;
while (1) {
const auto chunk = packet.substr(0, 5);
packet = packet.substr(5);
numberStr += chunk.substr(1);
if (chunk.front() == '0')
break;
}
return {binStrToInt(numberStr), isEmptyPacket(packet) ? "" : packet};
} else {
const bool isLengthBits = packet.front() == '0';
packet = packet.substr(1);
const auto lengthStr = packet.substr(0, isLengthBits ? 15 : 11);
const auto length = binStrToInt(lengthStr);
packet = packet.substr(isLengthBits ? 15 : 11);
std::list<uint64_t> args;
if (isLengthBits) {
auto rem = packet.substr(0, length);
while (1) {
const auto ret = solve(rem);
args.emplace_front(ret.first);
if (ret.second.empty() || isEmptyPacket(ret.second))
break;
rem = ret.second;
}
packet = packet.substr(length);
} else {
for (uint64_t i = 0; i < length; ++i) {
const auto ret = solve(packet);
args.emplace_front(ret.first);
packet = ret.second;
if (isEmptyPacket(packet))
break;
}
}
uint64_t result;
if (typeId == "000") {
result = 0;
for (auto a : args)
result += a;
} else if (typeId == "001") {
result = 1;
for (auto a : args)
result *= a;
} else if (typeId == "010") {
result = *std::min_element(args.cbegin(), args.cend());
} else if (typeId == "011") {
result = *std::max_element(args.cbegin(), args.cend());
} else if (typeId == "101") {
const auto a1 = args.back();
args.pop_back();
result = args.back() < a1;
} else if (typeId == "110") {
const auto a1 = args.back();
args.pop_back();
result = args.back() > a1;
} else if (typeId == "111") {
const auto a1 = args.back();
args.pop_back();
result = args.back() == a1;
}
return {result, isEmptyPacket(packet) ? "" : packet};
}
}
Loading…
Cancel
Save