#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

const int max_coord = int(1e4);
const double pi = double(acosl(-1));

/// Due to some rounding issues, iterating up to max_coord
/// can lead to annoying situations. Let's not do that.
const int good_coord = max_coord - 3;
const int max_sqlen = 2 * good_coord * good_coord;
bitset<max_sqlen> can_repr;

struct point
{
    int x, y;

    point () : x(0), y(0) {}
    point (const int x_, const int y_) : x(x_), y(y_) {}

    point operator + (const point &o) const
    {
        return point(x + o.x, y + o.y);
    }

    point operator - (const point &o) const
    {
        return point(x - o.x, y - o.y);
    }

    int operator * (const point &o) const
    {
        return x * o.x + y * o.y;
    }

    int operator % (const point &o) const
    {
        return x * o.y - o.x * y;
    }

    bool operator == (const point &o) const
    {
        return x == o.x && y == o.y;
    }

    bool operator < (const point &o) const
    {
        return x < o.x || (x == o.x && y < o.y);
    }
};

point get_repr (const int sqlen)
{
    for (int i = 0; i <= good_coord && i * i <= sqlen; i++)
    {
        const int rem = sqlen - i * i;
        int j = max(0, int(sqrt(rem)) - 2);
        while (j * j < rem)
            j++;

        if (i * i + j * j == sqlen)
            return point(max(i, j), min(i, j));
    }

    ensure(false);
    return point(-1, -1);
}

bool inside (const vector<point> &v, const point &p)
{
    ensure(int(v.size()) == 4);

    for (int i = 0; i < 4; i++)
    {
        const point cur = (v[(i + 1) % 4] - v[i]);
        const point nxt = (v[(i + 2) % 4] - v[(i + 1) % 4]);
        ensure(cur % nxt > 0);
    }

    for (int i = 0; i < 4; i++)
    {
        const point cur = (v[i] - p);
        const point nxt = (v[(i + 1) % 4] - p);
        if (cur % nxt <= 0)
            return false;
    }

    return true;
}

int main (int argc, char *argv[])
{
    registerGen(argc, argv, 1);

    const int n = opt<int>("n");
    const string mode = opt<string>("mode");

    vector<point> corners;

    if (mode == "naive" || mode == "triangle")
    {
        const int side = opt<int>("side");

        if (mode == "naive")
        {
            corners.emplace_back(0, 0);
            corners.emplace_back(side + 1, 0);
            corners.emplace_back(side + 1, side - 1);
            corners.emplace_back(1, side);
        }
        else
        {
            corners.emplace_back(0, 0);
            corners.emplace_back(side + 1, side - 1);
            corners.emplace_back(side, side);
        }
    }
    else if (mode == "free")
    {
        int sqlen = opt<int>("sqlen");

        for (int i = 0; i <= good_coord; i++)
        for (int j = 0; j <= i; j++)
            can_repr[i * i + j * j] = 1;

        while (sqlen >= 2 && (can_repr[sqlen] != 1 || can_repr[sqlen - 1] != 1))
            sqlen--;
        ensure(sqlen >= 2);

        const point p = get_repr(sqlen);
        point q = get_repr(sqlen - 1);
        swap(q.x, q.y);

        auto half = [&] (const int x, const int to_add)
        {
            return (x + to_add) / 2;
        };

        vector<point> shifts;
        shifts.emplace_back(-half(p.x, 0), -half(p.y, 0));
        shifts.emplace_back(half(q.x, 0), -half(q.y, 0));
        shifts.emplace_back(half(p.x, 1), half(p.y, 1));
        shifts.emplace_back(-half(q.x, 1), half(q.y, 1));

        ensure(shifts[2] - shifts[0] == p);
        ensure(shifts[3] - shifts[1] == point(-q.x, q.y));

        point center(0, 0);
        for (const auto &it : shifts)
        {
            if (it.x < 0)
                center.x = max(center.x, -it.x);
            if (it.y < 0)
                center.y = max(center.y, -it.y);
        }

        for (const auto &it : shifts)
            corners.push_back(center + it);

        for (const auto &it : corners)
            ensure(0 <= min(it.x, it.y) && max(it.x, it.y) <= max_coord);
    }
    else
        ensure(false);




    set<point> pts;
    for (auto it : corners)
        pts.insert(it);

    if (mode == "triangle")
    {
        for (int sum = 1; int(pts.size()) < n; sum++)
        for (int x = 0; x <= sum && int(pts.size()) < n; x++)
            pts.emplace(x, sum - x);
    }
    else
    {
        while (int(pts.size()) < n)
        {
            const int x = rnd.next(0, max_coord);
            const int y = rnd.next(0, max_coord);
            const point cur(x, y);

            if (inside(corners, cur))
                pts.insert(cur);
        }
    }



    vector<point> v(pts.begin(), pts.end());
    shuffle(v.begin(), v.end());


    int min_x = max_coord + 1, max_x = -1;
    int min_y = max_coord + 1, max_y = -1;

    for (const auto &pr : v)
    {
        min_x = min(min_x, pr.x);
        max_x = max(max_x, pr.x);

        min_y = min(min_y, pr.y);
        max_y = max(max_y, pr.y);
    }

    const int shift_x = rnd.next(-min_x, max_coord - max_x);
    const int shift_y = rnd.next(-min_y, max_coord - max_y);

    for (auto &it : v)
        it = it + point(shift_x, shift_y);

    cout << n << endl;
    for (int i = 0; i < n; i++)
        cout << v[i].x << ' ' << v[i].y << "\n";
}
