diff options
-rw-r--r-- | 22.9/main.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/22.9/main.cpp b/22.9/main.cpp new file mode 100644 index 0000000..46cc68e --- /dev/null +++ b/22.9/main.cpp @@ -0,0 +1,72 @@ +#include <cstdio> +#include <unordered_set> +#include <iostream> +using namespace std; + +int signum(int n) { + if (0 < n) return 1; + if (n < 0) return -1; + return 0; +} + +struct Pos { + int x, y; + + Pos add(Pos other) { + return Pos{this->x+other.x,this->y+other.y}; + } + Pos sub(Pos other) { + return Pos{this->x-other.x,this->y-other.y}; + } + + bool touching(Pos other) { + return abs(this->x - other.x) <= 1 + && abs(this->y - other.y) <= 1; + } + + Pos moveTowards(Pos other) { + Pos p = *this; + if (!touching(other)) { + p.x += signum(other.x - this->x); + p.y += signum(other.y - this->y); + } + return p; + } + + bool operator==(Pos const& p) const noexcept + { + return x == p.x && y == p.y; + } +}; + +template<> +struct std::hash<Pos> +{ + size_t operator()(Pos const& p) const noexcept + { + return std::hash<int>{}(p.x) ^ (std::hash<int>{}(p.x) << 1); + } +}; + +int main() { + char dir; + int steps; + Pos head{0,0}, tail{0,0}; + unordered_set<Pos> visited; + while (scanf("%c %d ", &dir, &steps) == 2) { + Pos d; + switch (dir) { + case 'R': d = {1, 0}; break; + case 'L': d = {-1, 0}; break; + case 'U': d = {0, -1}; break; + case 'D': d = {0, 1}; break; + default: throw "bad input"; + } + for (int i = 0; i < steps; i++) { + head = head.add(d); + tail = tail.moveTowards(head); + visited.insert(tail); + } + } + cout << visited.size() << endl; +} |