using System;
using System.Collections.Generic;
class main
{
static readonly int[] DR = {0, 1, -1, 0, 0};
static readonly int[] DC = {0, 0, 0, 1, -1};
private static List<int> move_rows, move_cols;
private static int[,] tiles;
private static int h, w;
private static bool check(int r1, int c1, int r2, int c2)
{
if(r1 < 0 || h <= r1 || c1 < 0 || w <= c1)
return false;
if(r2 < 0 || h <= r2 || c2 < 0 || w <= c2)
return false;
if(r1 == r2 && c1 == c2)
return true;
if(r1 != r2 && c1 != c2)
return false;
int len = Math.Abs(r1 - r2) + Math.Abs(c1 - c2);
int dr = (r2 - r1)/len;
int dc = (c2 - c1)/len;
while(r1 != r2 || c1 != c2)
{
if(tiles[r1, c1] < 0)
return false;
r1 += dr;
c1 += dc;
}
return tiles[r1, c1] >= 0;
}
private static void shift(int r1, int c1, int r2, int c2)
{
if(r1 == r2 && c1 == c2)
return;
int len = Math.Abs(r1 - r2) + Math.Abs(c1 - c2);
int dr = (r2 - r1)/len;
int dc = (c2 - c1)/len;
int tile = tiles[r1, c1];
while(r1 != r2 || c1 != c2)
{
tiles[r1, c1] = tiles[r1 + dr, c1 + dc];
r1 += dr;
c1 += dc;
}
tiles[r1, c1] = tile;
move_rows.Add(r2);
move_cols.Add(c2);
}
private static void slide(int r1, int c1, int r2, int c2)
{
for(int i = 0; i < 5; ++i)
for(int j = 0; j < 5; ++j)
{
int rs = r1 + DR[i];
int cs = c1 + DC[i];
int rf = r2 + DR[j];
int cf = c2 + DC[j];
int[] rm = {rs, rf};
int[] cm = {cf, cs};
int way = 0;
while(way < 2 && (!check(rs, cs, rm[way], cm[way]) || !check(rm[way], cm[way], rf, cf)))
++way;
if(way < 2)
{
shift(r1, c1, rs, cs);
shift(rs, cs, rm[way], cm[way]);
shift(rm[way], cm[way], rf, cf);
shift(rf, cf, r2, c2);
return;
}
}
}
private static void move(int r1, int c1, int r2, int c2)
{
if(r1 == r2 && c1 == c2)
return;
int rs = -1, cs = -1;
for(int i = 0; i < h; ++i)
for(int j = 0; j < w; ++j)
if(tiles[i, j] == 0)
{
rs = i;
cs = j;
}
int len = Math.Abs(r1 - r2) + Math.Abs(c1 - c2);
int dr = (r2 - r1)/len;
int dc = (c2 - c1)/len;
while(r1 != r2 || c1 != c2)
{
tiles[r1, c1] = -tiles[r1, c1];
slide(rs, cs, r1 + dr, c1 + dc);
tiles[r1, c1] = -tiles[r1, c1];
shift(r1 + dr, c1 + dc, r1, c1);
rs = r1;
cs = c1;
r1 += dr;
c1 += dc;
}
}
private static void move(int label, int row, int col)
{
int rs = -1, cs = -1;
for(int i = 0; i < h; ++i)
for(int j = 0; j < w; ++j)
if(tiles[i, j] == label)
{
rs = i;
cs = j;
}
int[] rm = {rs, row};
int[] cm = {col, cs};
int way = 0;
while(way < 2 && (!check(rs, cs, rm[way], cm[way]) || !check(rm[way], cm[way], row, col)))
++way;
move(rs, cs, rm[way], cm[way]);
move(rm[way], cm[way], row, col);
}
private static bool build()
{
move_rows = new List<int>();
move_cols = new List<int>();
for(int i = 0; i < h - 2; ++i)
{
for(int j = 0; j < w - 2; ++j)
{
move(i*w + j + 1, i, j);
tiles[i, j] = -tiles[i, j];
}
move(i*w + w - 1, i, w - 1);
if(tiles[i, w - 2] == 0)
shift(i, w - 2, i + 1, w - 2);
if(tiles[i, w - 2] == i*w + w)
{
move(i, w - 2, i + 1, w - 2);
shift(i, w - 2, i, w - 1);
shift(i, w - 1, i + 2, w - 1);
shift(i + 2, w - 1, i + 2, w - 2);
shift(i + 2, w - 2, i + 1, w - 2);
shift(i + 1, w - 2, i + 1, w - 1);
shift(i + 1, w - 1, i, w - 1);
shift(i, w - 1, i, w - 2);
shift(i, w - 2, i + 1, w - 2);
}
move(i*w + w, i + 1, w - 1);
tiles[i + 1, w - 1] = -tiles[i + 1, w - 1];
move(i, w - 1, i, w - 2);
tiles[i + 1, w - 1] = -tiles[i + 1, w - 1];
shift(i, w - 1, i + 1, w - 1);
tiles[i, w - 2] = -tiles[i, w - 2];
tiles[i, w - 1] = -tiles[i, w - 1];
}
for(int j = 0; j < w - 2; ++j)
{
move((h - 2)*w + j + 1, h - 1, j);
if(tiles[h - 2, j] == 0)
shift(h - 2, j, h - 2, j + 1);
if(tiles[h - 2, j] == (h - 1)*w + j + 1)
{
move(h - 2, j, h - 2, j + 1);
shift(h - 2, j, h - 1, j);
shift(h - 1, j, h - 1, j + 2);
shift(h - 1, j + 2, h - 2, j + 2);
shift(h - 2, j + 2, h - 2, j + 1);
shift(h - 2, j + 1, h - 1, j + 1);
shift(h - 1, j + 1, h - 1, j);
shift(h - 1, j, h - 2, j);
shift(h - 2, j, h - 2, j + 1);
}
move((h - 1)*w + j + 1, h - 1, j + 1);
tiles[h - 1, j + 1] = -tiles[h - 1, j + 1];
move(h - 1, j, h - 2, j);
tiles[h - 1, j + 1] = -tiles[h - 1, j + 1];
shift(h - 1, j, h - 1, j + 1);
tiles[h - 2, j] = -tiles[h - 2, j];
tiles[h - 1, j] = -tiles[h - 1, j];
}
int[] rows = {h - 1, h - 2, h - 2, h - 1};
int[] cols = {w - 1, w - 1, w - 2, w - 2};
for(int i = 0; i < 4; ++i)
{
int cnt = 0;
for(int j = 1; j < 4; ++j)
if(tiles[rows[j], cols[j]] == rows[j]*w + cols[j] + 1)
++cnt;
if(cnt == 3)
return true;
for(int j = 0; j < 4; ++j)
if(tiles[rows[j], cols[j]] == 0)
slide(rows[j], cols[j], rows[(j + 1) % 4], cols[(j + 1) % 4]);
}
return false;
}
private static bool solve()
{
string[] line = Console.ReadLine().Split(' ');
h = Int32.Parse(line[0]);
w = Int32.Parse(line[1]);
string[] puzzle = new string[h];
for(int i = 0; i < h; ++i)
puzzle[i] = Console.ReadLine();
List<int> rows = new List<int>(), cols = new List<int>();
List<char> chars = new List<char>();
for(char c = 'a'; c <= 'z'; ++c)
for(int i = 0; i < h; ++i)
for(int j = 0; j < w; ++j)
if(puzzle[i][j] == c)
{
rows.Add(i);
cols.Add(j);
chars.Add(c);
}
for(int i = 0; i < 2; ++i)
{
tiles = new int[h, w];
for(int j = 0; j < chars.Count; ++j)
tiles[rows[j], cols[j]] = j + 1;
if(build())
return true;
for(int j = 1; j < chars.Count; ++j)
if(chars[j] == chars[j - 1])
{
int temp = rows[j];
rows[j] = rows[j - 1];
rows[j - 1] = temp;
temp = cols[j];
cols[j] = cols[j - 1];
cols[j - 1] = temp;
break;
}
}
return false;
}
public static void Main(string[] args)
{
solve();
Console.WriteLine(move_rows.Count);
for(int i = 0; i < move_rows.Count; ++i)
Console.WriteLine("{0} {1}", move_rows[i] + 1, move_cols[i] + 1);
}
}