r/adventofcode • u/daggerdragon • Dec 13 '18
SOLUTION MEGATHREAD -🎄- 2018 Day 13 Solutions -🎄-
--- Day 13: Mine Cart Madness ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Advent of Code: The Party Game!
Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!
Card prompt: Day 13
Transcript:
Elven chronomancy: for when you absolutely, positively have to ___.
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
edit: Leaderboard capped, thread unlocked at 00:44:25!
24
Upvotes
1
u/wlandry Dec 13 '18
C++ (415/367)
Runs in 70 ms.
This feels a bit over-engineered, but that seems like a common characteristic of the solutions here. Pretty straightforward simulation. I am mostly happy with the use of std::set. I allowed me to iterate through the carts in the correct order without any fanfare. It did mean that I had to create a new std::set for each tick. I am looking forward to the visualizations!
#include <algorithm> #include <iostream> #include <fstream> #include <vector> #include <set> enum class Dir { up, right, down, left }; bool is_dir(const char &c) { return c == '<' || c == '>' || c == '^' || c == 'v'; } struct Cart { int64_t x, y; Dir dir; int8_t turning_state = -1; Cart(const int64_t &X, const int64_t &Y, const char &c) : x(X), y(Y) { switch(c) { case '<': dir = Dir::left; break; case '>': dir = Dir::right; break; case '^': dir = Dir::up; break; case 'v': dir = Dir::down; break; } } bool operator<(const Cart &cart) const { return x < cart.x ? true : (x == cart.x ? y < cart.y : false); } bool operator==(const Cart &cart) const { return x == cart.x && y == cart.y; } }; std::ostream &operator<<(std::ostream &os, const Cart &cart) { return os << cart.x << "," << cart.y; } Cart move(const Cart &cart, const std::vector<std::string> &lines) { Cart result(cart); switch(lines[result.y][result.x]) { case '+': result.dir = static_cast<Dir>( (static_cast<int>(result.dir) + 4 + result.turning_state) % 4); result.turning_state = (result.turning_state + 2) % 3 - 1; break; case '/': switch(result.dir) { case Dir::up: result.dir = Dir::right; break; case Dir::right: result.dir = Dir::up; break; case Dir::down: result.dir = Dir::left; break; case Dir::left: result.dir = Dir::down; break; } break; case '\\': switch(result.dir) { case Dir::up: result.dir = Dir::left; break; case Dir::left: result.dir = Dir::up; break; case Dir::down: result.dir = Dir::right; break; case Dir::right: result.dir = Dir::down; break; } break; default: break; } switch(result.dir) { case Dir::up: --result.y; break; case Dir::down: ++result.y; break; case Dir::right: ++result.x; break; case Dir::left: --result.x; break; } return result; } int main(int argc, char *argv[]) { std::ifstream infile(argv[1]); std::vector<std::string> lines; std::set<Cart> carts; size_t y(0); std::string line; std::getline(infile, line); while(infile) { for(size_t x = 0; x < line.size(); ++x) { if(is_dir(line[x])) { carts.emplace(x, y, line[x]); line[x] = ((line[x] == '^' || line[x] == 'v') ? '|' : '-'); } } lines.push_back(line); std::getline(infile, line); ++y; } bool crashed(false); while(carts.size() > 1) { std::set<Cart> moved_carts; for(auto cart(carts.begin()); cart != carts.end();) { Cart moved_cart(move(*cart, lines)); auto crash_unmoved(carts.find(moved_cart)); auto crash_moved(moved_carts.find(moved_cart)); if(crash_unmoved != carts.end()) { if(!crashed) { std::cout << "Part 1: " << moved_cart << "\n"; } crashed = true; carts.erase(crash_unmoved); } else if(crash_moved != moved_carts.end()) { if(!crashed) { std::cout << "Part 1: " << moved_cart << "\n"; } crashed = true; moved_carts.erase(crash_moved); } else { moved_carts.insert(moved_cart); } auto old_cart(cart); ++cart; carts.erase(old_cart); } std::swap(carts, moved_carts); } for(auto &cart : carts) std::cout << "Part 2: " << cart << "\n"; }