From 2833c43111bc41bd1b01d2866bfca4b61684cb2b Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Fri, 17 Dec 2021 09:58:07 -0500 Subject: [PATCH] day16: finished part2 (C++) --- day16/part1.clj | 8 +-- day16/part2.cpp | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 6 deletions(-) create mode 100644 day16/part2.cpp diff --git a/day16/part1.clj b/day16/part1.clj index 50b7f1a..2358e59 100644 --- a/day16/part1.clj +++ b/day16/part1.clj @@ -40,14 +40,10 @@ (if (every? #(= \0 %) data) ['() vcnt] (do - (println "Version: " version) (if-let [value (take-literal-value data)] - (do - (println "Value:" (first value)) - [(second value) (+ vcnt version)]) + [(second value) (+ vcnt version)] (do (let [info (take-operator (drop 3 data))] - (println "Subpacket:") (if (= :bits (get info 2)) (loop [inpt [(subs (first info) 0 (get info 1)) (+ vcnt version)]] (if (empty? (first inpt)) @@ -67,5 +63,5 @@ (process-packet))] (if (not (empty? (first packet))) (recur (process-packet packet)) - (println packet))) + (println (second packet)))) diff --git a/day16/part2.cpp b/day16/part2.cpp new file mode 100644 index 0000000..5a02df9 --- /dev/null +++ b/day16/part2.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static const std::map 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 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 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 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}; + } +} +