#include <algorithm>
#include <iostream>

struct point
{
    int x, y;
};

inline point operator-(point const & a, point const & b)
{
    const point result = {a.x - b.x, a.y - b.y};
    return result;
}

inline long squared_distance(point const & a, point const & b)
{
    const point d = b - a;
    return d.x * d.x + d.y * d.y;
}

point project_to_units(point const & o, point const & e)
{
    const int dx = std::abs(e.x - o.x);
    const int dy = std::abs(e.y - o.y);
    point result = {e.x, e.y};
    if (dy < dx) {
        result.x = o.x + (e.y - o.y);
    } else if (dx < dy) {
        result.y = o.y + (e.x - o.x);
    }
    return result;
}

struct closer_to
{
    const point o;

    closer_to(point const & p) : o(p) {}

    bool operator()(point const & a, point const & b) const
    {
        return squared_distance(o, a) < squared_distance(o, b);
    }
};

point approximate(const point o, const point e)
{
    const point points[] = {
        {e.x, o.y},            // projection to X
        {o.x, e.y},            // projection to Y
        project_to_units(o, e) // projection to [(2n+1)*pi / 4] axis
    };
    return *std::min_element(points, points + 3, closer_to(e));
}


std::ostream & operator<<(std::ostream & os, point const & p)
{
    os << "(" << p.x << ", " << p.y << ")";
    return os;
}

int main()
{
    const point o = {0, 0};

    const point points[] = {
        {-1, -1}, {1, 3}, {2, 2}, {2, 3}
    };

    std::cout << "center: " << o << std::endl;

    for (std::size_t i = 0; i < sizeof(points)/sizeof(points[0]); ++i) {
        const point a = approximate(o, points[i]);
        std::cout << "point " << points[i] << ", approx " << a << std::endl;
    }
    return 0;
}

