diff --git a/CMakeLists.txt b/CMakeLists.txt index 093b595..1ca3748 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,9 @@ target_link_libraries(day01 aocpp) add_executable(day02 day02.cpp) target_link_libraries(day02 aocpp intcode) +add_executable(day03 day03.cpp) +target_link_libraries(day03 aocpp) + add_executable(day05 day05.cpp) target_link_libraries(day05 aocpp intcode) diff --git a/day03.cpp b/day03.cpp new file mode 100644 index 0000000..d6a5466 --- /dev/null +++ b/day03.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +using namespace aocpp; + +namespace { + +auto BuildLine(std::string instructions) -> std::vector +{ + Coord here {}; + std::vector wire; + + auto it = std::begin(instructions); + auto end = std::end(instructions); + while (it != end) { + auto start = it; + it = std::find(it, end, ','); + if (start == it) { throw std::runtime_error{"null command"}; } + + Coord (*step)(Coord); + switch (*start++) { + case 'U': step = Up; break; + case 'D': step = Down; break; + case 'L': step = Left; break; + case 'R': step = Right; break; + default: throw std::runtime_error{"bad command letter"}; + } + + auto n = std::stol(std::string{start, it}); + for (int i = 0; i < n; i++) { + here = step(here); + wire.push_back(here); + } + + // skip over comma + if (it != end) it++; + } + return wire; +} + +struct Entry { bool w0, w1; std::int64_t part2; }; + +auto Record ( + std::map & m, + bool Entry::* which, + std::vector const& wire +) -> void { + for (std::size_t i = 0; i < wire.size(); i++) { + auto & entry = m[wire[i]]; + if (!(entry.*which)) { + entry.*which = true; + entry.part2 += i+1; + } + } +} + +} // namespace + +auto main(int argc, char** argv) -> int { + auto fin = aocpp::Startup(argc, argv); + + std::string line; + std::getline(fin, line); + auto wire0 = BuildLine(line); + std::getline(fin, line); + auto wire1 = BuildLine(line); + + std::map counts; + Record(counts, &Entry::w0, wire0); + Record(counts, &Entry::w1, wire1); + + std::int64_t part1 = std::numeric_limits::max(); + std::int64_t part2 = std::numeric_limits::max(); + + for (auto & [k,v] : counts) { + if (v.w0 && v.w1) { + part1 = std::min(part1, Norm1(k)); + part2 = std::min(part2, v.part2); + } + } + + std::cout << "Part 1: " << part1 << std::endl; + std::cout << "Part 2: " << part2 << std::endl; +} diff --git a/day23.cpp b/day23.cpp index a952965..5e1481c 100644 --- a/day23.cpp +++ b/day23.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -15,16 +16,14 @@ namespace { struct Payload { ValueType x, y; }; struct Packet { ValueType destination; Payload payload; }; using Ethernet = std::deque; +using Machines = std::array; -auto BuildNetwork(Machine m) -> std::vector { - std::vector machines; - machines.reserve(50); - +auto BuildNetwork(Machine m) -> Machines { + Machines machines; auto& i = std::get(Step(m)).input; - for (i = 0; i < 50; i++) { - machines.push_back(m); + for (i = 0; i < machines.size(); i++) { + machines[i] = m; } - return machines; } @@ -56,7 +55,7 @@ auto Interact(Ethernet & ethernet, Machine & m, std::optional p) -> voi } // namespace -auto main(int argc, char** argv) -> int { +auto main(int const argc, char** const argv) -> int { auto fin = aocpp::Startup(argc, argv); auto machines = BuildNetwork(Machine{ParseStream(fin)}); auto ethernet = Ethernet{}; @@ -67,7 +66,7 @@ auto main(int argc, char** argv) -> int { for(;;) { if (!ethernet.empty()) { - auto packet = ethernet.front(); + auto const packet = ethernet.front(); ethernet.pop_front(); if (packet.destination == 255) { nat = packet.payload; diff --git a/intcode/src/Interpreter.cpp b/intcode/src/Interpreter.cpp index 85ce251..7002b3b 100644 --- a/intcode/src/Interpreter.cpp +++ b/intcode/src/Interpreter.cpp @@ -2,10 +2,10 @@ namespace intcode { -BadInstruction::BadInstruction(char const* what) +BadInstruction::BadInstruction(char const* const what) : std::runtime_error{what} {} -auto StepInput(Machine & m, ValueType input) -> void { +auto StepInput(Machine & m, ValueType const input) -> void { std::get(Step(m)).input = input; } @@ -15,67 +15,58 @@ auto StepOutput(Machine & m) -> ValueType { auto Step(Machine & m) -> std::variant { for (;;) { - auto instruction = m.Next(); - auto modes = instruction / 10; + auto next = m.Next(); + auto const instruction = next % 100; next /= 100; - auto arg = [&]() -> ValueType & { + auto const arg = [&]() -> ValueType & { auto &v = m.Next(); - switch ((modes /= 10) % 10) { - case 0: - return m.At(v); - case 1: - return v; - case 2: - return m.Rel(v); - default: - throw BadInstruction{"invalid addressing mode"}; + auto const mode = next % 10; next /= 10; + switch (mode) { + case 0: return m.At(v); + case 1: return v; + case 2: return m.Rel(v); + default: throw BadInstruction{"invalid addressing mode"}; } }; - switch (instruction % 100) { - case 1: { + switch (instruction) { + case 1: arg() = arg() + arg(); break; - } - case 2: { + case 2: arg() = arg() * arg(); break; - } - case 3: { + case 3: return Input{arg()}; - } - case 4: { + case 4: return Output{arg()}; - } case 5: { - auto a = arg(); - auto b = arg(); + auto const a = arg(); + auto const b = arg(); if (a) { m.Goto(b); } break; } case 6: { - auto a = arg(); - auto b = arg(); + auto const a = arg(); + auto const b = arg(); if (!a) { m.Goto(b); } break; } case 7: { - auto a = arg(); - auto b = arg(); - arg() = a < b; // order matters + auto const a = arg(); + arg() = a < arg(); break; } - case 8: { + case 8: arg() = arg() == arg(); break; - } case 9: m.Rebase(arg()); @@ -85,6 +76,7 @@ auto Step(Machine & m) -> std::variant { return Halt{}; default: + std::cout << instruction << std::endl; throw BadInstruction{"invalid opcode"}; } } diff --git a/intcode/src/Machine.cpp b/intcode/src/Machine.cpp index 9e2f56f..33cc276 100644 --- a/intcode/src/Machine.cpp +++ b/intcode/src/Machine.cpp @@ -5,17 +5,17 @@ namespace intcode { Machine::Machine() : rom_{}, ram_{}, pc_{0}, base_{0} {} Machine::Machine(std::vector program) - : rom_{program}, ram_{}, pc_{0}, base_{0} {} + : rom_{std::move(program)}, ram_{}, pc_{0}, base_{0} {} -auto Machine::At(std::size_t i) -> ValueType & { +auto Machine::At(std::size_t const i) -> ValueType & { return i < rom_.size() ? rom_[i] : ram_[i]; } -auto Machine::Rel(std::size_t i) -> ValueType & { +auto Machine::Rel(std::size_t const i) -> ValueType & { return At(base_ + i); } -auto Machine::Rebase(std::size_t offset) -> void { +auto Machine::Rebase(std::size_t const offset) -> void { base_ += offset; } @@ -23,7 +23,7 @@ auto Machine::Next() -> ValueType & { return At(pc_++); } -auto Machine::Goto(std::size_t address) -> void { +auto Machine::Goto(std::size_t const address) -> void { pc_ = address; } diff --git a/lib/include/aocpp/Coord.hpp b/lib/include/aocpp/Coord.hpp index 0eb4bf4..e9c8ab5 100644 --- a/lib/include/aocpp/Coord.hpp +++ b/lib/include/aocpp/Coord.hpp @@ -40,6 +40,8 @@ auto CW(Coord) -> Coord; /// Rotate counter-clockwise auto CCW(Coord) -> Coord; +auto Norm1(Coord) -> std::int64_t; + /// Add two coordinates pairwise auto operator+(Coord, Coord) -> Coord; diff --git a/lib/src/Coord.cpp b/lib/src/Coord.cpp index 992a248..e749f08 100644 --- a/lib/src/Coord.cpp +++ b/lib/src/Coord.cpp @@ -1,5 +1,7 @@ #include +#include + namespace aocpp { auto Draw(std::ostream & out, std::map image) -> void { @@ -65,6 +67,10 @@ auto CCW(Coord c) -> Coord { return c; } +auto Norm1(Coord c) -> std::int64_t { + return std::abs(c.x) + std::abs(c.y); +} + auto operator+(Coord a, Coord b) -> Coord { return {a.x + b.x, a.y + b.y}; }