program xo;

const
  MAX_N = 300;
  MAX_W = 600;

type
  TCoord = record
    x, y: integer;
  end;

const
  kr: array [0 .. 7] of TCoord = ((x:-1; y:0), (x:1; y:0), (x:0; y:-1), (x:0; y:1),
                                (x:-1; y:1), (x:1; y:-1), (x:1; y:1), (x:-1; y:-1));

var
  n, wmn: integer;
  // moves[0] - pirmojo žaidėjo ėjimai,
  // moves[1] - antrojo žaidėjo ėjimai
  mn: array [0..1] of integer;
  moves: array [0..1, 1 .. MAX_N] of TCoord;
  wm: array [1 .. MAX_W] of TCoord;

// Grąžina numerį žaidėjo, kurio ženklas stovi ant nurodyto langelio.
// Jei langelis turščias, grąžina -1
function occupied(cr: TCoord): integer;
var
  i, k: integer;
begin
  for k := 0 to 1 do
    for i := 1 to mn[k] do
      if (moves[k,i].x = cr.x) and (moves[k,i].y = cr.y) then
      begin
        Result := k; exit;
      end;
  Result := -1;
end;

// Grąžina, ar padėjus ženklą koordinatėse cr, žaidėjas laimėtų
function wins(player: integer; cr: TCoord): boolean;
var
  zc: array [0..3] of integer;
  k: integer;
  c: TCoord;
begin
  for k := 0 to 3 do zc[k] := 1; // kryptys, kuriomis gali būti išsidėstę XO
  for k := low(kr) to high(kr) do
  begin
    c.x := cr.x + kr[k].x; c.y := cr.y + kr[k].y;
    while occupied(c) = player do // langelyje nagrinėjamo žaidėjo ženklas
    begin
      inc(zc[k div 2]);
      c.x := c.x + kr[k].x; c.y := c.y + kr[k].y;
    end;
    if zc[k div 2] >= 5 then
    begin
      Result := True; exit;
    end;
  end;
  Result := False;
end;

// Randa, ar CR langelis dar nėra įdėtas į rezultatų masyvą
function NotInResult(cr: TCoord): boolean;
var
  i: integer;
begin
  for i := 1 to wmn do
    if (cr.x = wm[i].x) and (cr.y = wm[i].y) then
    begin
      Result := False; exit;
    end;
  Result := True;
end;

// player - kuriam žaidėjui ieškoti laiminčiųjų ėjimų
// winningmovecount - kiek reikia rasti laiminčių ėjimu
// wm - laimintieji ėjimai
// funkcijos rezultatas - kiek buvo rasta laiminčiųjų ėjimų
procedure FindWinningMoves(player: shortint);
var
  i, k: integer;
  nk: TCoord;
begin
  wmn := 0;
  for i := 1 to mn[player] do
  begin
    for k := low(kr) to high(kr) do
    begin
      nk.x := moves[player][i].x + kr[k].x;
      nk.y := moves[player][i].y + kr[k].y;

      if NotInResult(nk) and (occupied(nk) = -1) and wins(player, nk) then
      // Radom laimintįjį ėjimą
      begin
        inc(wmn); wm[wmn] := nk;
      end;
    end;
  end;
end;

procedure ReadData;
var
  fin: textfile;
  i: integer;
begin
  assignfile(fin, 'XO.IN'); reset(fin);
  readln(fin, n);
  mn[0] := 0; mn[1] := 0;
  for i := 0 to n-1 do
  begin
    inc(mn[i mod 2]);
    readln(fin, moves[i mod 2, mn[i mod 2]].x, moves[i mod 2, mn[i mod 2]].y);
  end;
  closefile(fin);
end;

procedure WriteAnswer;
var
  i: integer;
  fout: textfile;
begin
  assignfile(fout, 'XO.OUT'); rewrite(fout);
  writeln(fout, wmn);
  for i := 1 to wmn do
    writeln(fout, wm[i].x, ' ', wm[i].y);
  close(fout);
end;

begin
  ReadData;
  FindWinningMoves(n mod 2);
  WriteAnswer;
end.
