Skip to content

Instantly share code, notes, and snippets.

@HappyCerberus
Created December 9, 2022 10:33
Show Gist options
  • Save HappyCerberus/350ac795e6688247428b22928ce07310 to your computer and use it in GitHub Desktop.
Save HappyCerberus/350ac795e6688247428b22928ce07310 to your computer and use it in GitHub Desktop.
enum class Direction {
Right,
Left,
Up,
Down
};
struct Order {
Direction direction;
uint32_t count;
};
struct Position {
int row;
int column;
};
void single_step(Position& head, Direction direction) {
switch (direction) {
case Direction::Down: head.row--; break;
case Direction::Up: head.row++; break;
case Direction::Left: head.column--; break;
case Direction::Right: head.column++; break;
}
}
void follow_step(Position& head, Position& tail) {
// Move if the distance is two in either direction
if (std::abs(head.row - tail.row) >= 2) {
tail.row += (head.row - tail.row) / 2;
// If we are also on a diagonal, head.colum - tail.column
// will be 1 or -1, resulting in a diagonal move.
tail.column += head.column - tail.column;
} else if (std::abs(head.column - tail.column) >= 2) {
// Same, but for the columns.
tail.column += (head.column - tail.column) / 2;
tail.row += head.row - tail.row;
}
}
size_t simulate_motions(const std::vector<Order>& orders) {
Position head{0,0}, tail{0,0};
std::unordered_set<Position> visited{{0,0}};
auto single_order = [&](const Order& order) {
// Repeat each step as many times as requested in the order.
for (auto c : std::views::iota(0uz, order.count)) {
// Move the head.
single_step(head, order.direction);
// Follow with the tail.
follow_step(head, tail);
// Remember the position of the tail
visited.insert(tail);
}
};
std::ranges::for_each(orders, single_order);
// Return unique positions visited by the tail.
return visited.size();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment