#include <bits/stdc++.h>
using namespace std;
const double EPS = 1e-7;
struct PT {
  double x, y;
  PT() {}
  PT(double xx, double yy) : x(xx), y(yy) {}
  bool operator<(const PT &rhs) const {
    return make_pair(y, x) < make_pair(rhs.y, rhs.x);
  }
  bool operator==(const PT &rhs) const {
    return make_pair(y, x) == make_pair(rhs.y, rhs.x);
  }
};
double cross(PT p, PT q) { return p.x * q.y - p.y * q.x; }
double area2(PT a, PT b, PT c) {
  return cross(a, b) + cross(b, c) + cross(c, a);
}
bool between(const PT &a, const PT &b, const PT &c) {
  return (fabs(area2(a, b, c)) < EPS && (a.x - b.x) * (c.x - b.x) <= 0 &&
          (a.y - b.y) * (c.y - b.y) <= 0);
}
void ConvexHull(vector<PT> &pts) {
  sort(pts.begin(), pts.end());
  pts.erase(unique(pts.begin(), pts.end()), pts.end());
  vector<PT> up, dn;
  for (int i = 0; i < (int)pts.size(); i++) {
    while (up.size() > 1 && area2(up[up.size() - 2], up.back(), pts[i]) >= 0)
      up.pop_back();
    while (dn.size() > 1 && area2(dn[dn.size() - 2], dn.back(), pts[i]) <= 0)
      dn.pop_back();
    up.push_back(pts[i]);
    dn.push_back(pts[i]);
  }
  pts = dn;
  for (int i = (int)up.size() - 2; i >= 1; i--) pts.push_back(up[i]);
  if (pts.size() <= 2) return;
  dn.clear();
  dn.push_back(pts[0]);
  dn.push_back(pts[1]);
  for (int i = 2; i < (int)pts.size(); i++) {
    if (between(dn[dn.size() - 2], dn[dn.size() - 1], pts[i])) dn.pop_back();
    dn.push_back(pts[i]);
  }
  if (dn.size() >= 3 && between(dn.back(), dn[0], dn[1])) {
    dn[0] = dn.back();
    dn.pop_back();
  }
  pts = dn;
}
ostream &operator<<(ostream &os, PT p) { return os << p.y << ' ' << p.x; }
map<int, vector<int> > known;
map<int, vector<int> > known2;
int main() {
  int n, m;
  while (cin >> n >> m, n) {
    known.clear();
    known2.clear();
    for (int i = (0); i < (int)(m); i++) {
      int x, y;
      cin >> x >> y;
      known[x].push_back(y);
      known2[y].push_back(x);
    }
    for (auto kv : known) sort(kv.second.begin(), kv.second.end());
    for (auto kv : known2) sort(kv.second.begin(), kv.second.end());
    vector<PT> pts;
    for (auto kv : known) {
      int first = *(kv.second.begin());
      if (known.find(kv.first - 1) == known.end() ||
          *known[kv.first - 1].begin() > first) {
        pts.push_back({(double)(first), (double)(kv.first)});
      }
    }
    for (auto kv : known) {
      int first = *(kv.second.begin());
      if (known.find(kv.first + 1) == known.end() ||
          *known[kv.first + 1].begin() > first) {
        pts.push_back({(double)(first), (double)(kv.first - 1)});
      }
    }
    for (auto kv : known) {
      int first = *(kv.second.rbegin());
      if (known.find(kv.first - 1) == known.end() ||
          *known[kv.first - 1].rbegin() < first) {
        pts.push_back({(double)(first - 1), (double)(kv.first)});
      }
    }
    for (auto kv : known) {
      int first = *(kv.second.rbegin());
      if (known.find(kv.first + 1) == known.end() ||
          *known[kv.first + 1].rbegin() < first) {
        pts.push_back({(double)(first - 1), (double)(kv.first - 1)});
      }
    }
    ConvexHull(pts);
    cout << pts.size() << endl;
    for (int i = (0); i < (int)(pts.size()); i++) {
      cout << pts[i] << endl;
    }
  }
}
