Files
advent-of-code/2018/puzzle-13-02.cc

150 lines
3.3 KiB
C++

//
// Created by Matthew Gretton-Dann on 01/12/2022.
//
#include <array>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <regex>
#include <set>
#include <utility>
using Int = std::int64_t;
using UInt = std::uint64_t;
using Point = std::pair<Int, Int>;
enum DirSelect {
left = 0,
straight = 1,
right = 2,
};
constexpr Point north{0, -1};
constexpr Point east{1, 0};
constexpr Point south{0, 1};
constexpr Point west{-1, 0};
struct Truck
{
Point pt_{0, 0};
Point dir_{north};
std::size_t dir_select_{0};
UInt time_stamp_{0};
constexpr auto operator<(Truck const& r) const noexcept -> bool
{
return pt_.first < r.pt_.first || (pt_.first == r.pt_.first && pt_.second < r.pt_.second);
}
};
using State = std::set<Truck>;
auto main() -> int
{
std::string line;
std::vector<std::string> map;
State trucks;
Point pos{0, 0};
while (std::getline(std::cin, line)) {
for (auto& c : line) {
switch (c) {
case '>':
trucks.insert({pos, east, 0, 0});
c = '-';
break;
case '<':
trucks.insert({pos, west, 0, 0});
c = '-';
break;
case '^':
trucks.insert({pos, north, 0, 0});
c = '|';
break;
case 'v':
trucks.insert({pos, south, 0, 0});
c = '|';
break;
}
pos.first += 1;
}
map.push_back(line);
pos.first = 0;
pos.second += 1;
}
UInt time_step{0};
while (trucks.size() > 1) {
++time_step;
std::cout << "\n" << std::setw(3) << time_step << ": ";
auto truck{trucks.begin()};
while (truck != trucks.end()) {
if (truck->time_stamp_ >= time_step) {
++truck;
continue;
}
std::cout << truck->pt_.first << "," << truck->pt_.second << ", ";
Point dir{truck->dir_};
std::size_t dir_select = truck->dir_select_;
Point const pos{truck->pt_.first + dir.first, truck->pt_.second + dir.second};
auto c{map.at(pos.second).at(pos.first)};
switch (c) {
case '|':
case '-':
break;
case '/':
if (dir == west) {
dir = south;
}
else if (dir == south) {
dir = west;
}
else if (dir == east) {
dir = north;
}
else if (dir == north) {
dir = east;
}
break;
case '\\':
if (dir == west) {
dir = north;
}
else if (dir == north) {
dir = west;
}
else if (dir == east) {
dir = south;
}
else if (dir == south) {
dir = east;
}
break;
case '+':
if (dir_select == left) {
dir = Point{dir.second, -dir.first};
}
else if (dir_select == right) {
dir = Point{-dir.second, dir.first};
}
dir_select = (dir_select + 1) % 3;
break;
default:
abort();
}
Truck const next_truck{pos, dir, dir_select, time_step};
truck = trucks.erase(truck);
auto [next_it, success] = trucks.insert(next_truck);
if (!success) {
std::cout << "Crash at: " << pos.first << "," << pos.second << "\n";
trucks.erase(next_it);
truck = trucks.begin();
}
}
}
auto truck(trucks.begin());
std::cout << "Point: " << truck->pt_.first << "," << truck->pt_.second << "\n";
}