generalize to a repo for all years
This commit is contained in:
26
2019/01.cpp
Normal file
26
2019/01.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto& in = aocpp::Startup(argc, argv);
|
||||
auto fuel = [](std::int64_t& x) { return x=x/3-2; };
|
||||
|
||||
std::int64_t x;
|
||||
std::int64_t part1 = 0;
|
||||
std::int64_t part2 = 0;
|
||||
|
||||
while (in >> x) {
|
||||
part1 += fuel(x);
|
||||
for (; x > 0; fuel(x)) {
|
||||
part2 += x;
|
||||
}
|
||||
}
|
||||
std::cout << "Part 1: " << part1 << std::endl;
|
||||
std::cout << "Part 2: " << part2 << std::endl;
|
||||
}
|
32
2019/02.cpp
Normal file
32
2019/02.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <intcode/intcode.hpp>
|
||||
|
||||
using namespace intcode;
|
||||
|
||||
namespace {
|
||||
|
||||
auto Compute(Machine machine, ValueType x, ValueType y) {
|
||||
machine.At(1) = x;
|
||||
machine.At(2) = y;
|
||||
Step(machine);
|
||||
return machine.At(0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
||||
|
||||
std::cout << "Part 1: " << Compute(machine, 12, 2) << std::endl;
|
||||
|
||||
for (std::int64_t i = 0; i < 100; i++) {
|
||||
for (std::int64_t j = 0; j < 100; j++) {
|
||||
if (19690720 == Compute(machine, i, j)) {
|
||||
std::cout << "Part 2: " << 100 * i + j << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
93
2019/03.cpp
Normal file
93
2019/03.cpp
Normal 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& in = aocpp::Startup(argc, argv);
|
||||
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
auto wire0 = BuildLine(line);
|
||||
std::getline(in, 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;
|
||||
}
|
62
2019/04.cpp
Normal file
62
2019/04.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
auto Parse(std::istream & in) -> std::pair<std::int64_t, std::int64_t> {
|
||||
std::int64_t lo, hi;
|
||||
std::string line;
|
||||
std::getline(in, line, '-');
|
||||
lo = std::stol(std::move(line));
|
||||
std::getline(in, line);
|
||||
hi = std::stol(std::move(line));
|
||||
return {lo,hi};
|
||||
}
|
||||
|
||||
auto Valid1(std::string const& str) {
|
||||
for (std::size_t i = 1; i < str.size(); i++) {
|
||||
if (str[i-1] == str[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Valid2(std::string const& str) {
|
||||
for (std::size_t i = 1; i < str.size(); i++) {
|
||||
if ( str[i] == str[i-1] &&
|
||||
(i == str.size() - 1 || str[i] != str[i+1]) &&
|
||||
(i == 1 || str[i] != str[i-2]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto [lo,hi] = Parse(aocpp::Startup(argc, argv));
|
||||
|
||||
std::int64_t part1 = 0;
|
||||
std::int64_t part2 = 0;
|
||||
|
||||
for (auto i = lo; i <= hi; i++) {
|
||||
auto str = std::to_string(i);
|
||||
if (std::is_sorted(str.begin(), str.end())) {
|
||||
if (Valid1(str)) part1++;
|
||||
if (Valid2(str)) part2++;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Part 1: " << part1 << std::endl;
|
||||
std::cout << "Part 2: " << part2 << std::endl;
|
||||
}
|
24
2019/05.cpp
Normal file
24
2019/05.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <intcode/intcode.hpp>
|
||||
using namespace intcode;
|
||||
|
||||
namespace {
|
||||
|
||||
auto Compute(Machine machine, ValueType d) -> ValueType {
|
||||
ValueType last_output = -1;
|
||||
Run(machine,
|
||||
[=]() { return d; },
|
||||
[&](auto o) { last_output = o; });
|
||||
return last_output;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
||||
std::cout << "Part 1: " << Compute(machine, 1) << std::endl;
|
||||
std::cout << "Part 2: " << Compute(std::move(machine), 5) << std::endl;
|
||||
}
|
81
2019/06.cpp
Normal file
81
2019/06.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
auto Parse(std::istream & in) {
|
||||
std::map<std::string, std::string> parents;
|
||||
std::string line;
|
||||
while (std::getline(in, line)) {
|
||||
auto it = line.find(')');
|
||||
if (it == std::string::npos) throw std::runtime_error{"bad input entry"};
|
||||
parents.insert({line.substr(it+1), line.substr(0, it)});
|
||||
}
|
||||
|
||||
return parents;
|
||||
}
|
||||
|
||||
auto Path(std::map<std::string, std::string> const& parents, std::string const& start)
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
std::string const* name = &start;
|
||||
while (*name != "COM") {
|
||||
name = &parents.at(*name);
|
||||
path.push_back(*name);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
auto Part1(std::map<std::string, std::string> const& parents) {
|
||||
std::map<std::string, std::size_t> depths {{"COM", 0}};
|
||||
std::size_t part1 {0};
|
||||
|
||||
for (auto & [k, _] : parents) {
|
||||
|
||||
std::string const* cursor = &k;
|
||||
std::vector<std::string const*> todo;
|
||||
|
||||
decltype(depths)::iterator it;
|
||||
while (depths.end() == (it = depths.find(*cursor))) {
|
||||
todo.push_back(cursor);
|
||||
cursor = &parents.at(*cursor);
|
||||
}
|
||||
auto n = it->second;
|
||||
|
||||
for (; !todo.empty(); todo.pop_back()) {
|
||||
depths[*todo.back()] = ++n;
|
||||
}
|
||||
|
||||
part1 += n;
|
||||
}
|
||||
|
||||
|
||||
return part1;
|
||||
}
|
||||
|
||||
auto Part2(std::map<std::string, std::string> const& parents) {
|
||||
auto p1 = Path(parents, "SAN");
|
||||
auto p2 = Path(parents, "YOU");
|
||||
|
||||
while (p1.back() == p2.back()) {
|
||||
p1.pop_back();
|
||||
p2.pop_back();
|
||||
}
|
||||
|
||||
return p1.size() + p2.size();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto parents = Parse(aocpp::Startup(argc, argv));
|
||||
std::cout << "Part 1: " << Part1(parents) << std::endl;
|
||||
std::cout << "Part 2: " << Part2(parents) << std::endl;
|
||||
}
|
68
2019/07.cpp
Normal file
68
2019/07.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <algorithm>
|
||||
#include <concepts>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <intcode/intcode.hpp>
|
||||
using namespace intcode;
|
||||
|
||||
namespace {
|
||||
|
||||
template <class R> auto Controller(Machine machine, R const ¶ms) {
|
||||
auto& i = std::get<Input>(Step(machine)).input;
|
||||
std::vector<Machine> amps;
|
||||
amps.reserve(params.size());
|
||||
for (auto p : params) {
|
||||
i = p;
|
||||
amps.push_back(machine);
|
||||
}
|
||||
return amps;
|
||||
}
|
||||
|
||||
template <class R>
|
||||
auto Feed(R &&s, ValueType start) -> std::optional<ValueType> {
|
||||
for (auto &m : amps) {
|
||||
auto e = Step(m);
|
||||
if (auto i = std::get_if<Input>(&e)) {
|
||||
i->input = start;
|
||||
start = StepOutput(m);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return {start};
|
||||
}
|
||||
|
||||
auto compute1(Machine machine, std::vector<ValueType> const ¶ms)
|
||||
-> ValueType {
|
||||
return *Feed(Controller(std::move(machine), params), 0);
|
||||
}
|
||||
auto compute2(Machine machine, std::vector<ValueType> const ¶ms)
|
||||
-> ValueType {
|
||||
auto amps = Controller(std::move(machine), params);
|
||||
ValueType last = 0;
|
||||
while (auto next = Feed(amps, last)) {
|
||||
last = *next;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
template <std::invocable<Machine, std::vector<ValueType> const &> F>
|
||||
auto optimize(Machine machine, std::vector<ValueType> params, F f) {
|
||||
ValueType best = 0;
|
||||
do {
|
||||
best = std::max(best, f(machine, params));
|
||||
} while (std::next_permutation(params.begin(), params.end()));
|
||||
return best;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
||||
std::cout << "Part 1: " << optimize(machine, {0, 1, 2, 3, 4}, compute1) << std::endl;
|
||||
std::cout << "Part 2: " << optimize(std::move(machine), {5, 6, 7, 8, 9}, compute2) << std::endl;
|
||||
}
|
74
2019/08.cpp
Normal file
74
2019/08.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
using Layer = std::array<char, 150>;
|
||||
|
||||
auto SplitLayers(std::istream & in) {
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
|
||||
std::vector<Layer> layers;
|
||||
|
||||
auto it = line.begin();
|
||||
auto layer_n = line.size() / 150;
|
||||
for (std::size_t layer = 0; layer < layer_n; layer++) {
|
||||
layers.push_back({});
|
||||
for (std::size_t y = 0; y < 150; y++) {
|
||||
layers.back()[y] = *it++;
|
||||
}
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
auto Part1(std::vector<Layer> const& layers) {
|
||||
std::size_t part1 = 0;
|
||||
std::size_t seen = std::numeric_limits<std::size_t>::max();
|
||||
for (auto & layer : layers) {
|
||||
auto zeros = std::count(layer.begin(), layer.end(), '0');
|
||||
if (zeros < seen) {
|
||||
seen = zeros;
|
||||
part1
|
||||
= std::count(layer.begin(), layer.end(), '1')
|
||||
* std::count(layer.begin(), layer.end(), '2');
|
||||
}
|
||||
}
|
||||
return part1;
|
||||
}
|
||||
|
||||
auto Flatten(std::vector<Layer> const& layers) {
|
||||
Layer merged {};
|
||||
for (std::size_t i = 0; i < 150; i++) {
|
||||
for (auto & layer : layers) {
|
||||
if ('2' != layer[i]) {
|
||||
merged[i] = layer[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
auto Draw(Layer picture) {
|
||||
for (std::size_t y = 0; y < 6; y++) {
|
||||
for (std::size_t x = 0; x < 25; x++) {
|
||||
std::cout << ('1' == picture[y*25+x] ? "▓" : "░");
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto layers = SplitLayers(aocpp::Startup(argc, argv));
|
||||
std::cout << "Part 1: " << Part1(layers) << std::endl;
|
||||
Draw(Flatten(layers));
|
||||
}
|
24
2019/09.cpp
Normal file
24
2019/09.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <intcode/intcode.hpp>
|
||||
using namespace intcode;
|
||||
|
||||
namespace {
|
||||
|
||||
auto Compute(Machine machine, ValueType d) -> ValueType {
|
||||
ValueType output = -1;
|
||||
Run(machine,
|
||||
[=](){ return d; },
|
||||
[&](auto o) { output = o; });
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
||||
std::cout << "Part 1: " << Compute(machine, 1) << std::endl;
|
||||
std::cout << "Part 2: " << Compute(std::move(machine), 2) << std::endl;
|
||||
}
|
44
2019/11.cpp
Normal file
44
2019/11.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <map>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <aocpp/Coord.hpp>
|
||||
#include <intcode/intcode.hpp>
|
||||
using namespace aocpp;
|
||||
using namespace intcode;
|
||||
|
||||
namespace {
|
||||
|
||||
auto Compute(Machine machine, ValueType start)
|
||||
-> std::map<Coord, ValueType> {
|
||||
|
||||
Coord here {0,0};
|
||||
std::map<Coord, ValueType> paint {{here,start}};
|
||||
Coord dir {0, -1};
|
||||
|
||||
bool next_color = true;
|
||||
|
||||
Run(machine,
|
||||
[&]() { return paint[here]; },
|
||||
[&](auto o) {
|
||||
if (next_color) {
|
||||
paint[here] = o;
|
||||
} else {
|
||||
dir = (o ? CW : CCW)(dir);
|
||||
here += dir;
|
||||
}
|
||||
next_color = !next_color;
|
||||
});
|
||||
|
||||
return paint;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
||||
std::cout << "Part 1: " << Compute(machine, 0).size() << "\nPart 2\n";
|
||||
Draw(std::cout, Compute(std::move(machine), 1));
|
||||
}
|
66
2019/13.cpp
Normal file
66
2019/13.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <set>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <aocpp/Coord.hpp>
|
||||
#include <intcode/intcode.hpp>
|
||||
using namespace aocpp;
|
||||
using namespace intcode;
|
||||
|
||||
namespace {
|
||||
|
||||
auto Compute1(Machine machine)
|
||||
-> std::size_t {
|
||||
std::set<Coord> screen;
|
||||
|
||||
Run(machine,
|
||||
[]() -> ValueType { throw std::runtime_error{"unexpected input request"}; },
|
||||
[&](auto x) {
|
||||
auto y = StepOutput(machine);
|
||||
auto v = StepOutput(machine);
|
||||
if (2 == v) { screen.insert({x,y}); } else { screen.erase({x,y}); }
|
||||
});
|
||||
return screen.size();
|
||||
}
|
||||
|
||||
auto Compute2(Machine machine) {
|
||||
ValueType score {0};
|
||||
ValueType paddleX {0};
|
||||
ValueType ballX {0};
|
||||
|
||||
machine.At(0) = 2;
|
||||
|
||||
Run(machine,
|
||||
[&]() {
|
||||
return paddleX < ballX ? 1 : paddleX > ballX ? -1 : 0;
|
||||
},
|
||||
[&](auto x) {
|
||||
auto y = StepOutput(machine);
|
||||
auto v = StepOutput(machine);
|
||||
|
||||
if (-1 == x && 0 == y) {
|
||||
score = v;
|
||||
} else {
|
||||
switch (v) {
|
||||
case 3: // paddle
|
||||
paddleX = x;
|
||||
break;
|
||||
case 4: // ball
|
||||
ballX = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return score;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))};
|
||||
std::cout << "Part 1: " << Compute1(machine) << std::endl;
|
||||
std::cout << "Part 2: " << Compute2(std::move(machine)) << std::endl;
|
||||
}
|
97
2019/15.cpp
Normal file
97
2019/15.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <aocpp/Coord.hpp>
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <intcode/intcode.hpp>
|
||||
using namespace aocpp;
|
||||
using namespace intcode;
|
||||
|
||||
namespace {
|
||||
|
||||
using CoordOp = Coord(Coord);
|
||||
CoordOp* const moves[4] {Up, Down, Left, Right};
|
||||
|
||||
auto Interact(Machine & m, ValueType cmd) -> ValueType {
|
||||
StepInput(m, cmd);
|
||||
return StepOutput(m);
|
||||
}
|
||||
|
||||
auto CounterCommand(ValueType x) -> ValueType {
|
||||
return ((x-1)^1)+1;
|
||||
}
|
||||
|
||||
// Depth first search of the maze
|
||||
auto Explore(Machine m) -> std::map<Coord, ValueType> {
|
||||
std::map<Coord, ValueType> world;
|
||||
std::vector<ValueType> path {0};
|
||||
Coord here {};
|
||||
|
||||
for(;;) {
|
||||
while (path.back() < 4) {
|
||||
path.back()++;
|
||||
auto here_ = moves[path.back() - 1](here);
|
||||
auto [it, success] = world.insert({here_,0});
|
||||
if (success && 0 != (it->second = Interact(m, path.back()))) {
|
||||
here = here_;
|
||||
path.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
path.pop_back();
|
||||
if (path.empty()) { break; }
|
||||
|
||||
auto rev = CounterCommand(path.back());
|
||||
here = moves[rev - 1](here);
|
||||
Interact(m, rev);
|
||||
}
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
// Breadth first search of maze finding shortest path to origin
|
||||
// and furthest point in the maze from the airsource.
|
||||
auto Compute(std::map<Coord, ValueType> world) -> std::pair<int, int> {
|
||||
// Find starting coordinate and remove all the walls from the map
|
||||
Coord start {};
|
||||
for (auto it = world.begin(); it != world.end(); ) {
|
||||
switch (it->second) {
|
||||
case 2: start = it->first;
|
||||
case 0: it = world.erase(it); break;
|
||||
default: it++;
|
||||
}
|
||||
}
|
||||
|
||||
int part1 = -1;
|
||||
int part2 = -1;
|
||||
|
||||
for (std::deque<std::pair<int, Coord>> todo {{0,start}};
|
||||
!todo.empty();
|
||||
todo.pop_front())
|
||||
{
|
||||
auto [steps, here] = todo.front();
|
||||
if (Coord{0,0} == here) part1 = steps;
|
||||
part2 = steps;
|
||||
|
||||
for (auto fn : moves) {
|
||||
auto next = fn(here);
|
||||
if (world.erase(next)) {
|
||||
todo.emplace_back(steps+1, next);
|
||||
}
|
||||
}
|
||||
}
|
||||
return {part1, part2};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto [p1,p2] = Compute(Explore(Machine{ParseStream(aocpp::Startup(argc, argv))}));
|
||||
std::cout << "Part 1: " << p1 << std::endl;
|
||||
std::cout << "Part 2: " << p2 << std::endl;
|
||||
}
|
89
2019/23.cpp
Normal file
89
2019/23.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <intcode/intcode.hpp>
|
||||
using namespace intcode;
|
||||
|
||||
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) -> Machines {
|
||||
Machines machines;
|
||||
auto& i = std::get<Input>(Step(m)).input;
|
||||
for (i = 0; i < machines.size(); i++) {
|
||||
machines[i] = m;
|
||||
}
|
||||
return machines;
|
||||
}
|
||||
|
||||
auto Interact(Ethernet & ethernet, Machine & m, std::optional<Payload> p) -> void {
|
||||
for(;;) {
|
||||
auto e = Step(m);
|
||||
switch (e.index()) {
|
||||
default: throw std::runtime_error{"unexpected halt"};
|
||||
case 0: {
|
||||
auto& i = std::get<0>(e).input;
|
||||
if (p) {
|
||||
i = p->x;
|
||||
StepInput(m, p->y);
|
||||
p = {};
|
||||
break;
|
||||
}
|
||||
i = -1; // no packet
|
||||
return;
|
||||
}
|
||||
case 1: {
|
||||
auto d = std::get<1>(e).output;
|
||||
auto x = StepOutput(m);
|
||||
auto y = StepOutput(m);
|
||||
ethernet.push_back({d, {x,y}});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int const argc, char** const argv) -> int {
|
||||
auto machines = BuildNetwork(Machine{ParseStream(aocpp::Startup(argc, argv))});
|
||||
auto ethernet = Ethernet{};
|
||||
|
||||
std::optional<ValueType> part1;
|
||||
std::optional<ValueType> part2;
|
||||
std::optional<Payload> nat;
|
||||
|
||||
for(;;) {
|
||||
if (!ethernet.empty()) {
|
||||
auto const packet = ethernet.front();
|
||||
ethernet.pop_front();
|
||||
if (packet.destination == 255) {
|
||||
nat = packet.payload;
|
||||
if (!part1) { part1 = packet.payload.y; }
|
||||
} else {
|
||||
Interact(ethernet, machines.at(packet.destination), packet.payload);
|
||||
}
|
||||
} else if (nat) {
|
||||
if (part2 == nat->y) { break; }
|
||||
part2 = nat->y;
|
||||
Interact(ethernet, machines[0], nat);
|
||||
} else {
|
||||
for (auto & m : machines) {
|
||||
Interact(ethernet, m, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Part 1: " << *part1 << std::endl;
|
||||
std::cout << "Part 2: " << *part2 << std::endl;
|
||||
}
|
38
2019/CMakeLists.txt
Normal file
38
2019/CMakeLists.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
add_executable(01 01.cpp)
|
||||
target_link_libraries(01 aocpp)
|
||||
|
||||
add_executable(02 02.cpp)
|
||||
target_link_libraries(02 aocpp intcode)
|
||||
|
||||
add_executable(03 03.cpp)
|
||||
target_link_libraries(03 aocpp)
|
||||
|
||||
add_executable(04 04.cpp)
|
||||
target_link_libraries(04 aocpp)
|
||||
|
||||
add_executable(05 05.cpp)
|
||||
target_link_libraries(05 aocpp intcode)
|
||||
|
||||
add_executable(06 06.cpp)
|
||||
target_link_libraries(06 aocpp)
|
||||
|
||||
add_executable(07 07.cpp)
|
||||
target_link_libraries(07 aocpp intcode)
|
||||
|
||||
add_executable(08 08.cpp)
|
||||
target_link_libraries(08 aocpp)
|
||||
|
||||
add_executable(09 09.cpp)
|
||||
target_link_libraries(09 aocpp intcode)
|
||||
|
||||
add_executable(11 11.cpp)
|
||||
target_link_libraries(11 aocpp intcode)
|
||||
|
||||
add_executable(13 13.cpp)
|
||||
target_link_libraries(13 aocpp intcode)
|
||||
|
||||
add_executable(15 15.cpp)
|
||||
target_link_libraries(15 aocpp intcode)
|
||||
|
||||
add_executable(23 23.cpp)
|
||||
target_link_libraries(23 aocpp intcode)
|
Reference in New Issue
Block a user