#include <bits/stdc++.h>
using namespace std;
char second[555][555];
int n;
bool check(int x, int y) {
  if (x < 0 || y < 0 || x >= n || y >= n) return true;
  return (second[x][y] == '0');
}
bool check_1(int x, int y) {
  return check(x - 1, y - 1) && check(x - 1, y) && check(x, y - 1);
}
bool check_2(int x, int y) {
  return check(x - 1, y + 1) && check(x - 1, y) && check(x, y + 1);
}
bool check_3(int x, int y) {
  return check(x + 1, y + 1) && check(x + 1, y) && check(x, y + 1);
}
bool check_4(int x, int y) {
  return check(x + 1, y - 1) && check(x + 1, y) && check(x, y - 1);
}
bool three_points_collinear(const pair<int, int> &a, const pair<int, int> &b,
                            const pair<int, int> &c) {
  return (a.second - b.second) * (a.first - c.first) ==
         (a.second - c.second) * (a.first - b.first);
}
int crosss(const pair<int, int> &O, const pair<int, int> &A,
           const pair<int, int> &B) {
  return (A.first - O.first) * (B.second - O.second) -
         (A.second - O.second) * (B.first - O.first);
}
vector<pair<int, int> > convex_hull(vector<pair<int, int> > &P) {
  int n = P.size(), k = 0;
  vector<pair<int, int> > H(2 * n);
  for (int i = 0; i < n; i++) {
    while (k >= 2 && crosss(H[k - 2], H[k - 1], P[i]) <= 0) k--;
    H[k++] = P[i];
  }
  for (int i = n - 2, t = k + 1; i >= 0; i--) {
    while (k >= t && crosss(H[k - 2], H[k - 1], P[i]) <= 0) k--;
    H[k++] = P[i];
  }
  H.resize(k);
  return H;
}
int main() {
  while (1) {
    scanf("%d", &n);
    if (n == 0) break;
    for (int i = n - 1; i >= 0; i--) scanf("%s", second[i]);
    vector<pair<int, int> > v;
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (second[i][j] != '1') continue;
        int c = 0;
        if (check_1(i, j)) v.push_back(make_pair(i + 1, j + 1)), c++;
        if (check_2(i, j)) v.push_back(make_pair(i + 1, j)), c++;
        if (check_3(i, j)) v.push_back(make_pair(i, j)), c++;
        if (check_4(i, j)) v.push_back(make_pair(i, j + 1)), c++;
        assert(c <= 1);
      }
    }
    for (int i = 0; i < v.size(); i++) swap(v[i].first, v[i].second);
    sort(v.begin(), v.end());
    vector<pair<int, int> > tmp = v;
    v.clear();
    for (int i = 0; i < tmp.size(); i++) {
      if (i && tmp[i] == tmp[i - 1]) continue;
      v.push_back(tmp[i]);
    }
    bool bad = true;
    for (int i = 0; i + 2 < v.size() && bad; i++)
      if (!three_points_collinear(v[i], v[i + 1], v[i + 2])) bad = false;
    if (bad) {
      if (v.empty())
        printf("0\n");
      else if (v[0] != v.back()) {
        printf("2\n");
        printf("%d %d\n", v[0].first, v[0].second);
        printf("%d %d\n", v.back().first, v.back().second);
      } else {
        printf("1\n");
        printf("%d %d\n", v[0].first, v[0].second);
      }
      continue;
    }
    v = convex_hull(v);
    assert(v.size() > 3);
    reverse(v.begin(), v.end());
    v.pop_back();
    printf("%d\n", v.size());
    for (int i = 0; i < v.size(); i++)
      printf("%d %d\n", v[i].first, v[i].second);
  }
  return 0;
}
