#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC tet( \
    "sse,sse2,sse3,ssse3,sse4,sse4.1,sse4.2,popcnt,abm,mmx,avx,tune=native")
using namespace std;
const int MOD = 1000000007;
const int UNDEF = -1;
const int INF = 1 << 30;
template <typename T>
inline bool chkmax(T &aa, T bb) {
  return aa < bb ? aa = bb, true : false;
}
template <typename T>
inline bool chkmin(T &aa, T bb) {
  return aa > bb ? aa = bb, true : false;
}
template <typename T>
class Dinic {
 public:
  static const T MAXN = 2004;
  struct edge {
    T a, b, cap, flow;
  };
  T dinic_numnodes, dinic_src, dinic_dest, d[MAXN], ptr[MAXN], q[MAXN];
  vector<edge> dinic_edge;
  vector<T> dinic_graph[MAXN];
  void add_edge(T a, T b, T cap) {
    edge e1 = {a, b, cap, 0};
    edge e2 = {b, a, 0, 0};
    dinic_graph[a].push_back((T)dinic_edge.size());
    dinic_edge.push_back(e1);
    dinic_graph[b].push_back((T)dinic_edge.size());
    dinic_edge.push_back(e2);
  }
  bool dinic_bfs() {
    int qh = 0, qt = 0;
    q[qt++] = dinic_src;
    memset(d, -1, dinic_numnodes * sizeof d[0]);
    d[dinic_src] = 0;
    while (qh < qt && d[dinic_dest] == -1) {
      T v = q[qh++];
      for (size_t i = 0; i < dinic_graph[v].size(); ++i) {
        T id = dinic_graph[v][i], to = dinic_edge[id].b;
        if (d[to] == -1 && dinic_edge[id].flow < dinic_edge[id].cap) {
          q[qt++] = to;
          d[to] = d[v] + 1;
        }
      }
    }
    return d[dinic_dest] != -1;
  }
  T dinic_dfs(T v, T flow) {
    if (!flow) return 0;
    if (v == dinic_dest) return flow;
    for (; ptr[v] < (T)dinic_graph[v].size(); ++ptr[v]) {
      T id = dinic_graph[v][ptr[v]], to = dinic_edge[id].b;
      if (d[to] != d[v] + 1) continue;
      T pushed =
          dinic_dfs(to, min(flow, dinic_edge[id].cap - dinic_edge[id].flow));
      if (pushed) {
        dinic_edge[id].flow += pushed;
        dinic_edge[id ^ 1].flow -= pushed;
        return pushed;
      }
    }
    return 0;
  }
  T flow(T src, T dest, T numnodes) {
    if (src == dest) return INF;
    dinic_src = src;
    dinic_dest = dest;
    dinic_numnodes = numnodes;
    T flow = 0;
    for (;;) {
      if (!dinic_bfs()) break;
      memset(ptr, 0, dinic_numnodes * sizeof ptr[0]);
      while (T pushed = dinic_dfs(dinic_src, INF)) flow += pushed;
    }
    return flow;
  }
  void dinic_clear(T numnodes) {
    dinic_edge.clear();
    for (int v = 0; v < numnodes; v++) dinic_graph[v].clear();
  }
  bitset<MAXN> inS;
  void _getCut(int x) {
    inS[x] = true;
    for (auto &ei : dinic_graph[x]) {
      auto &e = dinic_edge[ei];
      if (e.cap > e.flow) {
        int y = e.b;
        if (!inS[y]) {
          _getCut(y);
        }
      }
    }
  }
  void getCut() {
    inS.reset();
    _getCut(dinic_src);
  }
};
template <typename T>
int bins(const vector<T> &v, const T key) {
  int imin = 0, imax = v.size();
  while (imin < imax) {
    int imid = (imin + imax) >> 1;
    if (v[imid] < key)
      imin = imid + 1;
    else
      imax = imid;
  }
  return imin;
}
int gid = 2;
int SRC = 0, DEST = 1;
map<pair<int, int>, int> h[2];
Dinic<int> dinic;
vector<pair<int, pair<int, int> > > g2t;
int getid(int t, pair<int, int> p) {
  auto it = h[t].find(p);
  if (it != h[t].end()) return it->second;
  h[t][p] = gid;
  g2t.push_back(make_pair(t, p));
  if (t == 0)
    dinic.add_edge(SRC, gid, 1);
  else
    dinic.add_edge(gid, DEST, 1);
  return gid++;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  g2t.resize(2);
  int n;
  cin >> n;
  map<int, vector<int> > x2y[2];
  set<pair<int, int> > s;
  for (int i = 0; i < n; i++) {
    int x, y;
    cin >> x >> y;
    x2y[0][x].push_back(y);
    x2y[1][y].push_back(x);
    s.insert(make_pair(x, y));
  }
  for (int t = 0; t < 2; t++)
    for (auto &a : x2y[t]) sort(a.second.begin(), a.second.end());
  for (int t = 0; t < 2; t++) {
    for (auto &a : x2y[t]) {
      int py = -1;
      for (auto &ny : a.second) {
        if (py != -1) getid(t, make_pair(a.first, py));
        py = ny;
      }
    }
  }
  {
    int t = 0;
    for (auto &a : x2y[t]) {
      int x = a.first;
      int py = -1;
      auto yit = x2y[t ^ 1].begin();
      for (auto &ny : a.second) {
        if (py != -1) {
          while (yit != x2y[t ^ 1].end() && yit->first < py) ++yit;
          while (yit != x2y[t ^ 1].end() && yit->first <= ny) {
            int cix = bins(yit->second, x);
            for (int ix = max(0, cix - 3);
                 ix < min((int)yit->second.size() - 1, cix + 3); ix++) {
              int px = yit->second[ix];
              int nx = yit->second[ix + 1];
              int y = yit->first;
              if (px <= x && x <= nx && py <= y && y <= ny &&
                  s.find(make_pair(x, y)) == s.end()) {
                int id1 = getid(t, make_pair(x, py)),
                    id2 = getid(t ^ 1, make_pair(y, px));
                if (t == 1) swap(id1, id2);
                dinic.add_edge(id1, id2, 5000);
              }
            }
            ++yit;
          }
          if (yit != x2y[t ^ 1].begin()) --yit;
        }
        py = ny;
      }
    }
  }
  int flow = dinic.flow(SRC, DEST, gid);
  dinic.getCut();
  vector<pair<int, pair<int, int> > > vans[2];
  for (int t = 0; t < 2; t++) {
    for (auto &a : x2y[t]) {
      int x = a.first;
      int ly = -1;
      int py = -1;
      for (auto &ny : a.second) {
        if (ly == -1) ly = ny;
        if (py != -1) {
          int id = getid(t, make_pair(x, py));
          if ((t == 0) != (dinic.inS[id])) {
            vans[t].push_back(make_pair(x, make_pair(ly, py)));
            ly = ny;
          }
        }
        py = ny;
      }
      if (ly != -1) {
        vans[t].push_back(make_pair(x, make_pair(ly, py)));
      }
    }
  }
  printf("%d\n", (int)vans[1].size());
  for (auto &w : vans[1]) {
    printf("%d %d %d %d\n", w.second.first, w.first, w.second.second, w.first);
  }
  printf("%d\n", (int)vans[0].size());
  for (auto &w : vans[0]) {
    printf("%d %d %d %d\n", w.first, w.second.first, w.first, w.second.second);
  }
  int nume = gid - 2;
  int ans = 2 * n - nume + flow;
}
