This commit is contained in:
Eric Mertens 2022-11-07 17:19:17 -08:00
parent 1b5607c8fe
commit 5de6db8780
7 changed files with 141 additions and 46 deletions

View File

@ -23,6 +23,9 @@ target_link_libraries(day01 aocpp)
add_executable(day02 day02.cpp) add_executable(day02 day02.cpp)
target_link_libraries(day02 aocpp intcode) target_link_libraries(day02 aocpp intcode)
add_executable(day03 day03.cpp)
target_link_libraries(day03 aocpp)
add_executable(day05 day05.cpp) add_executable(day05 day05.cpp)
target_link_libraries(day05 aocpp intcode) target_link_libraries(day05 aocpp intcode)

93
day03.cpp Normal file
View File

@ -0,0 +1,93 @@
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
#include <map>
#include <tuple>
#include <string>
#include <aocpp/Coord.hpp>
#include <aocpp/Startup.hpp>
using namespace aocpp;
namespace {
auto BuildLine(std::string instructions) -> std::vector<Coord>
{
Coord here {};
std::vector<Coord> 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<Coord, Entry> & m,
bool Entry::* which,
std::vector<Coord> 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<Coord, Entry> counts;
Record(counts, &Entry::w0, wire0);
Record(counts, &Entry::w1, wire1);
std::int64_t part1 = std::numeric_limits<std::int64_t>::max();
std::int64_t part2 = std::numeric_limits<std::int64_t>::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;
}

View File

@ -1,3 +1,4 @@
#include <array>
#include <cstddef> #include <cstddef>
#include <deque> #include <deque>
#include <iostream> #include <iostream>
@ -15,16 +16,14 @@ namespace {
struct Payload { ValueType x, y; }; struct Payload { ValueType x, y; };
struct Packet { ValueType destination; Payload payload; }; struct Packet { ValueType destination; Payload payload; };
using Ethernet = std::deque<Packet>; using Ethernet = std::deque<Packet>;
using Machines = std::array<Machine, 50>;
auto BuildNetwork(Machine m) -> std::vector<Machine> { auto BuildNetwork(Machine m) -> Machines {
std::vector<Machine> machines; Machines machines;
machines.reserve(50);
auto& i = std::get<Input>(Step(m)).input; auto& i = std::get<Input>(Step(m)).input;
for (i = 0; i < 50; i++) { for (i = 0; i < machines.size(); i++) {
machines.push_back(m); machines[i] = m;
} }
return machines; return machines;
} }
@ -56,7 +55,7 @@ auto Interact(Ethernet & ethernet, Machine & m, std::optional<Payload> p) -> voi
} // namespace } // namespace
auto main(int argc, char** argv) -> int { auto main(int const argc, char** const argv) -> int {
auto fin = aocpp::Startup(argc, argv); auto fin = aocpp::Startup(argc, argv);
auto machines = BuildNetwork(Machine{ParseStream(fin)}); auto machines = BuildNetwork(Machine{ParseStream(fin)});
auto ethernet = Ethernet{}; auto ethernet = Ethernet{};
@ -67,7 +66,7 @@ auto main(int argc, char** argv) -> int {
for(;;) { for(;;) {
if (!ethernet.empty()) { if (!ethernet.empty()) {
auto packet = ethernet.front(); auto const packet = ethernet.front();
ethernet.pop_front(); ethernet.pop_front();
if (packet.destination == 255) { if (packet.destination == 255) {
nat = packet.payload; nat = packet.payload;

View File

@ -2,10 +2,10 @@
namespace intcode { namespace intcode {
BadInstruction::BadInstruction(char const* what) BadInstruction::BadInstruction(char const* const what)
: std::runtime_error{what} {} : std::runtime_error{what} {}
auto StepInput(Machine & m, ValueType input) -> void { auto StepInput(Machine & m, ValueType const input) -> void {
std::get<Input>(Step(m)).input = input; std::get<Input>(Step(m)).input = input;
} }
@ -15,67 +15,58 @@ auto StepOutput(Machine & m) -> ValueType {
auto Step(Machine & m) -> std::variant<Input, Output, Halt> { auto Step(Machine & m) -> std::variant<Input, Output, Halt> {
for (;;) { for (;;) {
auto instruction = m.Next(); auto next = m.Next();
auto modes = instruction / 10; auto const instruction = next % 100; next /= 100;
auto arg = [&]() -> ValueType & { auto const arg = [&]() -> ValueType & {
auto &v = m.Next(); auto &v = m.Next();
switch ((modes /= 10) % 10) { auto const mode = next % 10; next /= 10;
case 0: switch (mode) {
return m.At(v); case 0: return m.At(v);
case 1: case 1: return v;
return v; case 2: return m.Rel(v);
case 2: default: throw BadInstruction{"invalid addressing mode"};
return m.Rel(v);
default:
throw BadInstruction{"invalid addressing mode"};
} }
}; };
switch (instruction % 100) { switch (instruction) {
case 1: { case 1:
arg() = arg() + arg(); arg() = arg() + arg();
break; break;
}
case 2: { case 2:
arg() = arg() * arg(); arg() = arg() * arg();
break; break;
}
case 3: { case 3:
return Input{arg()}; return Input{arg()};
}
case 4: { case 4:
return Output{arg()}; return Output{arg()};
}
case 5: { case 5: {
auto a = arg(); auto const a = arg();
auto b = arg(); auto const b = arg();
if (a) { m.Goto(b); } if (a) { m.Goto(b); }
break; break;
} }
case 6: { case 6: {
auto a = arg(); auto const a = arg();
auto b = arg(); auto const b = arg();
if (!a) { m.Goto(b); } if (!a) { m.Goto(b); }
break; break;
} }
case 7: { case 7: {
auto a = arg(); auto const a = arg();
auto b = arg(); arg() = a < arg();
arg() = a < b; // order matters
break; break;
} }
case 8: { case 8:
arg() = arg() == arg(); arg() = arg() == arg();
break; break;
}
case 9: case 9:
m.Rebase(arg()); m.Rebase(arg());
@ -85,6 +76,7 @@ auto Step(Machine & m) -> std::variant<Input, Output, Halt> {
return Halt{}; return Halt{};
default: default:
std::cout << instruction << std::endl;
throw BadInstruction{"invalid opcode"}; throw BadInstruction{"invalid opcode"};
} }
} }

View File

@ -5,17 +5,17 @@ namespace intcode {
Machine::Machine() : rom_{}, ram_{}, pc_{0}, base_{0} {} Machine::Machine() : rom_{}, ram_{}, pc_{0}, base_{0} {}
Machine::Machine(std::vector<ValueType> program) Machine::Machine(std::vector<ValueType> 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]; 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); return At(base_ + i);
} }
auto Machine::Rebase(std::size_t offset) -> void { auto Machine::Rebase(std::size_t const offset) -> void {
base_ += offset; base_ += offset;
} }
@ -23,7 +23,7 @@ auto Machine::Next() -> ValueType & {
return At(pc_++); return At(pc_++);
} }
auto Machine::Goto(std::size_t address) -> void { auto Machine::Goto(std::size_t const address) -> void {
pc_ = address; pc_ = address;
} }

View File

@ -40,6 +40,8 @@ auto CW(Coord) -> Coord;
/// Rotate counter-clockwise /// Rotate counter-clockwise
auto CCW(Coord) -> Coord; auto CCW(Coord) -> Coord;
auto Norm1(Coord) -> std::int64_t;
/// Add two coordinates pairwise /// Add two coordinates pairwise
auto operator+(Coord, Coord) -> Coord; auto operator+(Coord, Coord) -> Coord;

View File

@ -1,5 +1,7 @@
#include <aocpp/Coord.hpp> #include <aocpp/Coord.hpp>
#include <cstdlib>
namespace aocpp { namespace aocpp {
auto Draw(std::ostream & out, std::map<Coord, std::int64_t> image) -> void { auto Draw(std::ostream & out, std::map<Coord, std::int64_t> image) -> void {
@ -65,6 +67,10 @@ auto CCW(Coord c) -> Coord {
return c; 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 { auto operator+(Coord a, Coord b) -> Coord {
return {a.x + b.x, a.y + b.y}; return {a.x + b.x, a.y + b.y};
} }