#include <bits/stdc++.h>
using namespace std;
const int maxN = 2018, INF = 1000000;
long long cap[maxN][maxN];
struct Max_flow {
  vector<int>* G;
  int parent[maxN], vis[maxN];
  int source, target, bfs_ctr;
  queue<int> Q;
  bool bfs() {
    vis[source] = ++bfs_ctr;
    Q.push(source);
    while (!Q.empty()) {
      int v = Q.front();
      Q.pop();
      for (int u : G[v]) {
        if ((vis[u] == bfs_ctr) or (cap[v][u] <= 0)) continue;
        vis[u] = bfs_ctr;
        Q.push(u);
        parent[u] = v;
        if (u == target) {
          while (!Q.empty()) Q.pop();
          break;
        }
      }
    }
    return (vis[target] == bfs_ctr);
  }
  long long max_flow(vector<int>* g, int n, int src, int trg) {
    G = g;
    source = src;
    target = trg;
    long long res = 0;
    while (bfs()) {
      long long min_cap = INF;
      for (int v = target; v != source; v = parent[v])
        min_cap = min(min_cap, cap[parent[v]][v]);
      for (int v = target; v != source; v = parent[v]) {
        cap[parent[v]][v] -= min_cap;
        cap[v][parent[v]] += min_cap;
      }
      res += min_cap;
    }
    return res;
  }
} compute;
pair<int, int> verts[maxN], hor[maxN];
vector<pair<pair<int, int>, pair<int, int> > > res;
vector<int> G[maxN];
bool incut[maxN], vis[maxN];
void dfs(int v) {
  vis[v] = true;
  for (int u : G[v])
    if (!vis[u] and cap[v][u] > 0) dfs(u);
}
void conn(int a, int b, int c) {
  G[a].push_back(b);
  G[b].push_back(a);
  cap[a][b] = c;
}
bool betw(int a, int b, int c) { return a < b and b < c; }
void printres() {
  printf("%d\n", (int)res.size());
  for (auto p : res)
    printf("%d %d %d %d\n", p.first.first, p.first.second, p.second.first,
           p.second.second);
  res.resize(0);
}
int main() {
  int n;
  scanf("%d", &n);
  for (int(i) = (0); (i) < (n); (i)++) {
    scanf("%d%d", &verts[i].first, &verts[i].second);
    hor[i] = make_pair(verts[i].second, verts[i].first);
  }
  sort(verts, verts + n);
  sort(hor, hor + n);
  for (int(i) = (0); (i) < (n); (i)++) swap(hor[i].first, hor[i].second);
  for (int(i) = (0); (i) < (n - 1); (i)++)
    for (int(j) = (0); (j) < (n - 1); (j)++) {
      if (verts[i].first != verts[i + 1].first or
          hor[j].second != hor[j + 1].second)
        continue;
      if (betw(verts[i].second, hor[j].second, verts[i + 1].second) and
          betw(hor[j].first, verts[i].first, hor[j + 1].first))
        conn(i, n + j, INF);
    }
  int src = n * 2, trg = n * 2 + 1;
  for (int(i) = (0); (i) < (n - 1); (i)++) {
    if (verts[i].first == verts[i + 1].first) conn(src, i, 1);
    if (hor[i].second == hor[i + 1].second) conn(n + i, trg, 1);
  }
  compute.max_flow(G, trg, src, trg);
  dfs(src);
  for (int(i) = (0); (i) < (n); (i)++) {
    incut[i] = !vis[i];
    incut[n + i] = vis[n + i];
  }
  pair<int, int> prev = hor[0];
  for (int(i) = (0); (i) < (n - 1); (i)++) {
    if (!incut[n + i] and hor[i].second == hor[i + 1].second) continue;
    res.push_back(make_pair(prev, hor[i]));
    prev = hor[i + 1];
  }
  res.push_back(make_pair(prev, hor[n - 1]));
  printres();
  prev = verts[0];
  for (int(i) = (0); (i) < (n - 1); (i)++) {
    if (!incut[i] and verts[i].first == verts[i + 1].first) continue;
    res.push_back(make_pair(prev, verts[i]));
    prev = verts[i + 1];
  }
  res.push_back(make_pair(prev, verts[n - 1]));
  printres();
  return 0;
}
