aocpp/2019/03.cpp
2023-01-31 09:15:25 -08:00

94 lines
2.1 KiB
C++

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
#include <map>
#include <tuple>
#include <string>
#include <numeric>
#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(std::istream & in, std::ostream & out) -> void
{
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);
}
}
out << "Part 1: " << part1 << std::endl;
out << "Part 2: " << part2 << std::endl;
}