#include <bits/stdc++.h>
using namespace std;
const int inf = 1000000000;
int N;
map<int, vector<pair<int, int> > > xPos;
map<int, vector<pair<int, int> > > yPos;
vector<tuple<int, int, int> > xSegs;
vector<tuple<int, int, int> > ySegs;
vector<int> connectionsX[2000];
int pairX[2000];
int pairY[2000];
int dist[2000];
bool inSetX[2000], inSetY[2000];
vector<tuple<int, int, int, int> > xAns;
vector<tuple<int, int, int, int> > yAns;
bool bfs() {
  queue<int> Q;
  for (int i = 1; i < xSegs.size(); i++) {
    if (pairX[i] == 0) {
      dist[i] = 0;
      Q.push(i);
    } else {
      dist[i] = inf;
    }
    inSetX[i] = false;
  }
  for (int i = 1; i < ySegs.size(); i++) {
    inSetY[i] = false;
  }
  dist[0] = inf;
  while (!Q.empty()) {
    int x = Q.front();
    Q.pop();
    inSetX[x] = true;
    if (dist[x] < dist[0]) {
      for (int i = 0; i < connectionsX[x].size(); i++) {
        int y = connectionsX[x][i];
        if (pairY[y] != x) {
          inSetY[y] = true;
        }
        if (dist[pairY[y]] == inf) {
          dist[pairY[y]] = dist[x] + 1;
          Q.push(pairY[y]);
        }
      }
    }
  }
  return (dist[0] != inf);
}
bool dfs(int x) {
  if (x != 0) {
    for (int i = 0; i < connectionsX[x].size(); i++) {
      int y = connectionsX[x][i];
      if (dist[pairY[y]] == dist[x] + 1) {
        if (dfs(pairY[y])) {
          pairY[y] = x;
          pairX[x] = y;
          return true;
        }
      }
    }
    dist[x] = inf;
    return false;
  }
  return true;
}
void hopcroft() {
  for (int i = 0; i < xSegs.size(); i++) {
    pairX[i] = 0;
  }
  for (int i = 0; i < ySegs.size(); i++) {
    pairY[i] = 0;
  }
  int res = 0;
  while (bfs()) {
    for (int i = 1; i < xSegs.size(); i++) {
      if (pairX[i] == 0 && dfs(i)) {
        res++;
      }
    }
  }
}
int main() {
  scanf("%d", &N);
  for (int i = 0; i < N; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    xPos[x].push_back(make_pair(y, -1));
    yPos[y].push_back(make_pair(x, -1));
  }
  xSegs.push_back(make_tuple(0, 0, 0));
  ySegs.push_back(make_tuple(0, 0, 0));
  for (auto it = xPos.begin(); it != xPos.end(); it++) {
    sort(it->second.begin(), it->second.end());
    int x = it->first;
    for (int i = 0; i < it->second.size() - 1; i++) {
      int y = it->second[i].first;
      int nexY = it->second[i + 1].first;
      it->second[i].second = xSegs.size();
      xSegs.push_back(make_tuple(y, nexY, x));
    }
  }
  for (auto it = yPos.begin(); it != yPos.end(); it++) {
    sort(it->second.begin(), it->second.end());
    int y = it->first;
    for (int i = 0; i < it->second.size() - 1; i++) {
      int x = it->second[i].first;
      int nexX = it->second[i + 1].first;
      it->second[i].second = ySegs.size();
      ySegs.push_back(make_tuple(x, nexX, y));
    }
  }
  for (int i = 1; i < xSegs.size(); i++) {
    for (int j = 1; j < ySegs.size(); j++) {
      tuple<int, int, int> x = xSegs[i], y = ySegs[j];
      if (get<0>(x) < get<2>(y) && get<2>(y) < get<1>(x) &&
          get<0>(y) < get<2>(x) && get<2>(x) < get<1>(y)) {
        connectionsX[i].push_back(j);
      }
    }
  }
  hopcroft();
  for (auto it = xPos.begin(); it != xPos.end(); it++) {
    int x = it->first;
    bool last = true;
    int yf;
    for (int i = 0; i < it->second.size(); i++) {
      int y = it->second[i].first;
      if (last) {
        last = false;
        yf = y;
      }
      if (it->second[i].second == -1 || !inSetX[it->second[i].second]) {
        last = true;
        xAns.push_back(make_tuple(x, yf, x, y));
      }
    }
  }
  for (auto it = yPos.begin(); it != yPos.end(); it++) {
    int y = it->first;
    bool last = true;
    int xf;
    for (int i = 0; i < it->second.size(); i++) {
      int x = it->second[i].first;
      if (last) {
        last = false;
        xf = x;
      }
      if (it->second[i].second == -1 || inSetY[it->second[i].second]) {
        last = true;
        yAns.push_back(make_tuple(xf, y, x, y));
      }
    }
  }
  printf("%d\n", yAns.size());
  for (int i = 0; i < yAns.size(); i++) {
    auto v = yAns[i];
    printf("%d %d %d %d\n", get<0>(v), get<1>(v), get<2>(v), get<3>(v));
  }
  printf("%d\n", xAns.size());
  for (int i = 0; i < xAns.size(); i++) {
    auto v = xAns[i];
    printf("%d %d %d %d\n", get<0>(v), get<1>(v), get<2>(v), get<3>(v));
  }
  return 0;
}
