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)
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)

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 <deque>
#include <iostream>
@ -15,16 +16,14 @@ namespace {
struct Payload { ValueType x, y; };
struct Packet { ValueType destination; Payload payload; };
using Ethernet = std::deque<Packet>;
using Machines = std::array<Machine, 50>;
auto BuildNetwork(Machine m) -> std::vector<Machine> {
std::vector<Machine> machines;
machines.reserve(50);
auto BuildNetwork(Machine m) -> Machines {
Machines machines;
auto& i = std::get<Input>(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<Payload> 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;

View File

@ -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<Input>(Step(m)).input = input;
}
@ -15,67 +15,58 @@ auto StepOutput(Machine & m) -> ValueType {
auto Step(Machine & m) -> std::variant<Input, Output, Halt> {
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<Input, Output, Halt> {
return Halt{};
default:
std::cout << instruction << std::endl;
throw BadInstruction{"invalid opcode"};
}
}

View File

@ -5,17 +5,17 @@ namespace intcode {
Machine::Machine() : rom_{}, ram_{}, pc_{0}, base_{0} {}
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];
}
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;
}

View File

@ -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;

View File

@ -1,5 +1,7 @@
#include <aocpp/Coord.hpp>
#include <cstdlib>
namespace aocpp {
auto Draw(std::ostream & out, std::map<Coord, std::int64_t> 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};
}