#include <iostream>
#include <memory>
#include <tuple>
#include <map>
struct Position { int x, y; };
bool operator<(Position const &a, Position const &b)
{
return std::tie(a.x, a.y) < std::tie(b.x, b.y);
}
std::ostream &operator<<(std::ostream &os, Position const &p)
{
return os << '(' << p.x << ", " << p.y << ')';
}
struct Board
{
class Piece
{
Position p;
friend struct ::Board;
public:
Position const &pos = p;
Piece(Position const &p)
: p(p)
{
}
};
void swap(Position const &source, Position const &target)
{
std::cout << "Swapping " << source << " to " << target << std::endl;
pieces[target].swap(pieces[source]);
pieces[target]->p = target;
pieces[source]->p = source;
std::cout << "Swapped " << source << " to " << target << std::endl;
}
void add(Position const &p)
{
pieces[p] = std::unique_ptr<Piece>(new Piece(p));
}
Piece *at(Position const &p)
{
return pieces[p].get();
}
private:
std::map<Position, std::unique_ptr<Piece>> pieces;
};
int main()
{
Board b;
b.add({1, 1});
b.add({1, 2});
b.add({2, 1});
b.add({2, 2});
std::cout << "First swap:" << std::endl;
b.swap({1, 1}, {1, 2});
std::cout << std::endl
<< "Second swap:" << std::endl;
b.swap(b.at({2, 1})->pos, {2, 2});
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWVtb3J5PgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDxtYXA+CgpzdHJ1Y3QgUG9zaXRpb24geyBpbnQgeCwgeTsgfTsKYm9vbCBvcGVyYXRvcjwoUG9zaXRpb24gY29uc3QgJmEsIFBvc2l0aW9uIGNvbnN0ICZiKQp7CglyZXR1cm4gc3RkOjp0aWUoYS54LCBhLnkpIDwgc3RkOjp0aWUoYi54LCBiLnkpOwp9CnN0ZDo6b3N0cmVhbSAmb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0gJm9zLCBQb3NpdGlvbiBjb25zdCAmcCkKewoJcmV0dXJuIG9zIDw8ICcoJyA8PCBwLnggPDwgIiwgIiA8PCBwLnkgPDwgJyknOwp9CgpzdHJ1Y3QgQm9hcmQKewoJY2xhc3MgUGllY2UKCXsKCQlQb3NpdGlvbiBwOwoJCWZyaWVuZCBzdHJ1Y3QgOjpCb2FyZDsKCXB1YmxpYzoKCQlQb3NpdGlvbiBjb25zdCAmcG9zID0gcDsKCQlQaWVjZShQb3NpdGlvbiBjb25zdCAmcCkKCQk6IHAocCkKCQl7CgkJfQoJfTsKCgl2b2lkIHN3YXAoUG9zaXRpb24gY29uc3QgJnNvdXJjZSwgUG9zaXRpb24gY29uc3QgJnRhcmdldCkKCXsKCQlzdGQ6OmNvdXQgPDwgIlN3YXBwaW5nICIgPDwgc291cmNlIDw8ICIgdG8gIiA8PCB0YXJnZXQgPDwgc3RkOjplbmRsOwoJCXBpZWNlc1t0YXJnZXRdLnN3YXAocGllY2VzW3NvdXJjZV0pOwoJCXBpZWNlc1t0YXJnZXRdLT5wID0gdGFyZ2V0OwoJCXBpZWNlc1tzb3VyY2VdLT5wID0gc291cmNlOwoJCXN0ZDo6Y291dCA8PCAiU3dhcHBlZCAgIiA8PCBzb3VyY2UgPDwgIiB0byAiIDw8IHRhcmdldCA8PCBzdGQ6OmVuZGw7Cgl9CgkKCXZvaWQgYWRkKFBvc2l0aW9uIGNvbnN0ICZwKQoJewoJCXBpZWNlc1twXSA9IHN0ZDo6dW5pcXVlX3B0cjxQaWVjZT4obmV3IFBpZWNlKHApKTsKCX0KCVBpZWNlICphdChQb3NpdGlvbiBjb25zdCAmcCkKCXsKCQlyZXR1cm4gcGllY2VzW3BdLmdldCgpOwoJfQoKcHJpdmF0ZToKCXN0ZDo6bWFwPFBvc2l0aW9uLCBzdGQ6OnVuaXF1ZV9wdHI8UGllY2U+PiBwaWVjZXM7Cn07CgppbnQgbWFpbigpCnsKCUJvYXJkIGI7CgliLmFkZCh7MSwgMX0pOwoJYi5hZGQoezEsIDJ9KTsKCWIuYWRkKHsyLCAxfSk7CgliLmFkZCh7MiwgMn0pOwoJCglzdGQ6OmNvdXQgPDwgIkZpcnN0IHN3YXA6IiA8PCBzdGQ6OmVuZGw7CgliLnN3YXAoezEsIDF9LCB7MSwgMn0pOwoJc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbAoJICAgICAgICAgIDw8ICJTZWNvbmQgc3dhcDoiIDw8IHN0ZDo6ZW5kbDsKCWIuc3dhcChiLmF0KHsyLCAxfSktPnBvcywgezIsIDJ9KTsKfQo=
First swap:
Swapping (1, 1) to (1, 2)
Swapped (1, 1) to (1, 2)
Second swap:
Swapping (2, 1) to (2, 2)
Swapped (2, 2) to (2, 2)