#include #include #include #include #include #include using namespace std; vector> read_file(string_view filename) { fstream input{ filename }; vector> result; char dir = 0; int count = 0; while ( input >> dir >> count ) { result.emplace_back(dir, count); } return result; } int distance(const tuple& head, const tuple& tail) { auto dist_x = abs(get<0>(head) - get<0>(tail)); auto dist_y = abs(get<1>(head) - get<1>(tail)); return max(dist_x, dist_y); }; static map> direction = { { 'R', { +1, 0 } }, { 'L', { -1, 0 } }, { 'U', { 0, +1 } }, { 'D', { 0, -1 } } }; void part1(const vector>& data) { tuple head = { 0, 0 }; tuple tail = head; set> positions; for ( auto [dir, count]: data ) { while ( count-- > 0 ) { const auto [delta_x, delta_y] = direction[dir]; const auto old_head = head; get<0>(head) += delta_x; get<1>(head) += delta_y; if ( distance(head, tail) > 1 ) { tail = old_head; } positions.insert(tail); } } cout << positions.size() << endl; } void part2(const vector>& data) { static const auto rope_size = 10; array, rope_size> rope; set> positions; for ( auto [dir, count]: data ) { while ( count-- > 0 ) { auto [delta_x, delta_y] = direction[dir]; get<0>(rope[0]) += delta_x; get<1>(rope[0]) += delta_y; for ( size_t i = 1; i < rope.size(); ++i ) { auto& head = rope.at(i - 1); auto& tail = rope.at(i); if ( distance(head, tail) > 1 ) { delta_x = get<0>(head) - get<0>(tail); delta_y = get<1>(head) - get<1>(tail); if ( abs(delta_x) > 1 ) { delta_x /= abs(delta_x); } if ( abs(delta_y) > 1 ) { delta_y /= abs(delta_y); } get<0>(tail) += delta_x; get<1>(tail) += delta_y; } } positions.insert(rope[9]); } } cout << positions.size() << endl; } int main() { const auto data = read_file("data/day09.txt"); part1(data); part2(data); }