#include<bits/stdc++.h>
using namespace std;
#define _SZ(n) memset((n),0,sizeof(n))
#define _SMO(n) memset((n),-1,sizeof(n))
#define _MC(n,m) memcpy((n),(m),sizeof(n))
#define _F first
#define _S second
#define _MP make_pair
#define _PB push_back
#define FOR(x,y) for(__typeof(y.begin())x=y.begin();x!=y.end();x++)
#define IOS ios_base::sync_with_stdio(0)
#ifdef ONLINE_JUDGE
#define FILEIO(name) \
  freopen(name".in", "r", stdin); \
  freopen(name".out", "w", stdout);
#else
#define FILEIO(name)
#endif
// Let's Fight!

const int MX = 35;

struct Point{
  int x,y;
  Point () {}
  Point (int _x, int _y) : x(_x), y(_y) {}
  bool operator == (const Point &b) const{
    return x == b.x && y == b.y;
  }
  bool operator != (const Point &b) const{
    return !(*this == b);
  }
};

int N,M,ip[MX][MX],op[MX][MX];
Point p(-1,-1), q; // p move q to ed
vector<Point> ans;
vector<Point> seq;
int bad[MX][MX];
Point prv[MX][MX];
Point que[MX*MX];
int vst[MX][MX];
int fr,bk;
int dir[8][2] = {{-1,0},{1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
vector<Point> path;

void BFS(Point ed){
//  printf("BFS %d %d -> %d %d\n", p.x, p.y, ed.x, ed.y);
  fr = bk = 0;
  _SZ(vst);
  que[bk++] = p;
  vst[p.x][p.y] = 1;
  while (fr < bk){
    Point u = que[fr++];
    for (int i=0; i<8; i++){
      int nx = u.x + dir[i][0];
      int ny = u.y + dir[i][1];
      if (nx < 1 || ny < 1 || nx > N || ny > M) continue;
      if (bad[nx][ny]) continue;
      if (q.x == nx && q.y == ny) continue;
      if (vst[nx][ny]) continue;
      que[bk++] = Point(nx,ny);
      prv[nx][ny] = u;
      vst[nx][ny] = 1;
    }
    if (vst[ed.x][ed.y]) break;
  }
  assert(vst[ed.x][ed.y] == 1);
  path.clear();
  Point cur = ed;
  while (cur != p){
    path._PB(cur);
    cur = prv[cur.x][cur.y];
  }
  reverse(path.begin(),path.end());
}
void move(Point a){
  if (ans.size()){
    assert(a != ans.back());
  }
  ans._PB(a);
  swap(ip[a.x][a.y],ip[p.x][p.y]);
  p = a;
}
void solve(Point ed){
  /*
  printf("solving %d %d\n", ed.x, ed.y);
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++)
      printf("%d ", bad[i][j]);
    puts("");
  }
  printf("st (%d, %d)\n", p.x, p.y);
  */
  q = Point(-1,-1);
  for (int i=1; i<=N && q.x==-1; i++){
    for (int j=1; j<=M && q.x==-1; j++){
      if (bad[i][j]) continue;
      if (p.x == i && p.y == j) continue;
      if (ip[i][j] == op[ed.x][ed.y])
        q = Point(i,j);
    }
  }
//  printf("tar (%d, %d)\n", q.x, q.y);
  int dx=1;
  int dy=1;
  if (ed.x < q.x) dx = -1;
  if (ed.y < q.y) dy = -1;
  while (q != ed){
    if (q.x != ed.x && q.y != ed.y && !bad[q.x+dx][q.y+dy]){
      BFS(Point(q.x+dx,q.y+dy));
    } else if (q.x != ed.x && !bad[q.x+dx][q.y]){
      BFS(Point(q.x+dx,q.y));
    } else if (q.y != ed.y && !bad[q.x][q.y+dy]){
      BFS(Point(q.x,q.y+dy));
    } else {
      assert(false);
    }
      for (auto i : path)
        move(i);
      Point tmp = p;
      move(q);
      q = tmp;
  }
}
void solve_seq(){
  for (auto v : seq){
    solve(v);
    bad[v.x][v.y] = 1;
  }
}
void solve22(){
  if (p != Point(1,1)){
    q = Point(-1,-1);
    BFS(Point(1,1));
    for (auto i : path){
      move(i);
    }
  }
  if (ip[2][2] != op[2][2]){
    if (ip[1][2] == op[2][2]){
      move(Point(2,2));
      move(Point(1,2));
    } else if (ip[2][1] == op[2][2]){
      move(Point(2,2));
      move(Point(2,1));
    }
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
  if (ip[1][2] != op[1][2]){
    move(Point(2,1));
    move(Point(1,2));
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
}
int main()
{
  int c1[MX*MX] = {0};
  int c2[MX*MX] = {0};
  scanf("%d%d", &N, &M);
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &ip[i][j]);
      c1[ip[i][j]]++;
    }
  }
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &op[i][j]);
      c2[op[i][j]]++;
    }
  }
  for (int i=1; i<MX*MX; i++){
    if (c1[i] != c2[i]){
      puts("-1");
      return 0;
    }
  }
  if (N == 1){
    int sy = -1;
    int ey = -1;
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j]){
        if (sy == -1){
          sy = j;
        }
        ey = j;
      }
    }
    if (sy == -1){
      puts("0");
      puts("1 1");
      return 0;
    }
    int fail=0;
    // check sy -> ey
    for (int j=sy; j<ey; j++)
      swap(ip[1][j],ip[1][j+1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=sy; j<=ey; j++)
        printf("%d %d\n", 1, j);
      return 0;
    }
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    // check ey -> sy
    fail = 0;
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=ey; j>=sy; j--)
        printf("%d %d\n", 1, j);
    } else {
      puts("-1");
    }
    return 0;
  } else if (M == 1){
    int sx = -1;
    int ex = -1;
    for (int i=1; i<=N; i++){
      if (ip[i][1] != op[i][1]){
        if (sx == -1){
          sx = i;
        }
        ex = i;
      }
    }
    if (sx == -1){
      puts("0");
      puts("1 1");
      return 0;
    }
    int fail = 0;
    // check sx -> ex
    for (int i=sx; i<ex; i++)
      swap(ip[i][1],ip[i+1][1]);
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=sx; i<=ex; i++)
        printf("%d %d\n", i, 1);
      return 0;
    }
    for (int i=ex; i>sx; i--)
      swap(ip[i][1],ip[i-1][1]);
    // check ex -> sx
    for (int i=ex; i>sx; i--)
      swap(ip[i][1], ip[i-1][1]);
    fail = 0;
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=ex; i>=sx; i--)
        printf("%d %d\n", i, 1);
    } else {
      puts("-1");
    }
    return 0;
  } else {
    p = Point(-1,-1);
    for (int i=1; i<=N && p.x == -1; i++){
      for (int j=1; j<=M && p.x == -1; j++){
        if (ip[i][j] == op[1][1]){
          p = Point(i,j);
        }
      }
    }
    int x = p.x;
    int y = p.y;
    for (int j=M; j>2; j--){
      for (int i=N; i>=1; i--){
        seq._PB(Point(i,j));
      }
    }
    for (int i=N; i>2; i--){
      seq._PB(Point(i,2));
      seq._PB(Point(i,1));
    }
    _SZ(bad);
    solve_seq();

    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        if (i>2 && j>2 && ip[i][j] != op[i][j]){
          assert(false);
        }
      }
    }

    solve22();
    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        if (ip[i][j] != op[i][j]){
          assert(false);
        }
      }
    }
    assert(ans.size() <= 1000000);
    printf("%d\n", (int)ans.size());
    printf("%d %d\n", x, y);
    for (auto i : ans)
      printf("%d %d\n", i.x, i.y);
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define _SZ(n) memset((n),0,sizeof(n))
#define _SMO(n) memset((n),-1,sizeof(n))
#define _MC(n,m) memcpy((n),(m),sizeof(n))
#define _F first
#define _S second
#define _MP make_pair
#define _PB push_back
#define FOR(x,y) for(__typeof(y.begin())x=y.begin();x!=y.end();x++)
#define IOS ios_base::sync_with_stdio(0)
#ifdef ONLINE_JUDGE
#define FILEIO(name) \
  freopen(name".in", "r", stdin); \
  freopen(name".out", "w", stdout);
#else
#define FILEIO(name)
#endif
// Let's Fight!

const int MX = 35;

struct Point{
  int x,y;
  Point () {}
  Point (int _x, int _y) : x(_x), y(_y) {}
  bool operator == (const Point &b) const{
    return x == b.x && y == b.y;
  }
  bool operator != (const Point &b) const{
    return !(*this == b);
  }
};

int N,M,ip[MX][MX],op[MX][MX];
Point p(-1,-1), q; // p move q to ed
vector<Point> ans;
vector<Point> seq;
int bad[MX][MX];
Point prv[MX][MX];
Point que[MX*MX];
int vst[MX][MX];
int fr,bk;
int dir[8][2] = {{-1,0},{1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
vector<Point> path;

void BFS(Point ed){
//  printf("BFS %d %d -> %d %d\n", p.x, p.y, ed.x, ed.y);
  fr = bk = 0;
  _SZ(vst);
  que[bk++] = p;
  vst[p.x][p.y] = 1;
  while (fr < bk){
    Point u = que[fr++];
    for (int i=0; i<8; i++){
      int nx = u.x + dir[i][0];
      int ny = u.y + dir[i][1];
      if (nx < 1 || ny < 1 || nx > N || ny > M) continue;
      if (bad[nx][ny]) continue;
      if (q.x == nx && q.y == ny) continue;
      if (vst[nx][ny]) continue;
      que[bk++] = Point(nx,ny);
      prv[nx][ny] = u;
      vst[nx][ny] = 1;
    }
    if (vst[ed.x][ed.y]) break;
  }
  assert(vst[ed.x][ed.y] == 1);
  path.clear();
  Point cur = ed;
  while (cur != p){
    path._PB(cur);
    cur = prv[cur.x][cur.y];
  }
  reverse(path.begin(),path.end());
}
void move(Point a){
  ans._PB(a);
  swap(ip[a.x][a.y],ip[p.x][p.y]);
  p = a;
}
void solve(Point ed){
  if (ip[ed.x][ed.y] == op[ed.x][ed.y]) return ;
  q = Point(-1,-1);
  for (int i=1; i<=N && q.x==-1; i++){
    for (int j=1; j<=M && q.x==-1; j++){
      if (bad[i][j]) continue;
      if (p.x == i && p.y == j) continue;
      if (ip[i][j] == op[ed.x][ed.y])
        q = Point(i,j);
    }
  }
  while (q.x != ed.x){
    while (q.x > ed.x){
      BFS(Point(q.x-1,q.y));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
    while (q.x < ed.x){
      BFS(Point(q.x+1,q.y));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
  }
  while (q.y != ed.y){
    while (q.y > ed.y){
      BFS(Point(q.x,q.y-1));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
    while (q.y < ed.y){
      BFS(Point(q.x,q.y+1));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
  }
}
void solve_seq(){
  for (auto v : seq){
//    printf("solving %d %d\n", v.x , v.y);
    solve(v);
    bad[v.x][v.y] = 1;
  }
}
void solve22(){
  if (p != Point(1,1)){
    move(Point(1,1));
  }
  if (ip[2][2] != op[2][2]){
    if (ip[1][2] == op[2][2]){
      move(Point(2,2));
      move(Point(1,2));
    } else if (ip[2][1] == op[2][2]){
      move(Point(2,2));
      move(Point(2,1));
    }
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
  if (ip[1][2] != op[1][2]){
    move(Point(2,1));
    move(Point(1,2));
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
}
int main()
{
  int c1[MX*MX] = {0};
  int c2[MX*MX] = {0};
  scanf("%d%d", &N, &M);
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &ip[i][j]);
      c1[ip[i][j]]++;
    }
  }
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &op[i][j]);
      c2[op[i][j]]++;
    }
  }
  for (int i=1; i<MX*MX; i++){
    if (c1[i] != c2[i]){
      puts("-1");
      return 0;
    }
  }
  if (N == 1){
    int sy = -1;
    int ey = -1;
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j]){
        if (sy == -1){
          sy = j;
        }
        ey = j;
      }
    }
    if (sy == -1){
      puts("0");
      puts("1 1");
      return 0;
    }
    int fail=0;
    // check sy -> ey
    for (int j=sy; j<ey; j++)
      swap(ip[1][j],ip[1][j+1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=sy; j<=ey; j++)
        printf("%d %d\n", 1, j);
      return 0;
    }
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    // check ey -> sy
    fail = 0;
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=ey; j>=sy; j--)
        printf("%d %d\n", 1, j);
    } else {
      puts("-1");
    }
    return 0;
  } else if (M == 1){
    int sx = -1;
    int ex = -1;
    for (int i=1; i<=N; i++){
      if (ip[i][1] != op[i][1]){
        if (sx == -1){
          sx = i;
        }
        ex = i;
      }
    }
    if (sx == -1){
      puts("0");
      puts("1 1");
      return 0;
    }
    int fail = 0;
    // check sx -> ex
    for (int i=sx; i<ex; i++)
      swap(ip[i][1],ip[i+1][1]);
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=sx; i<=ex; i++)
        printf("%d %d\n", i, 1);
      return 0;
    }
    for (int i=ex; i>sx; i--)
      swap(ip[i][1],ip[i-1][1]);
    // check ex -> sx
    for (int i=ex; i>sx; i--)
      swap(ip[i][1], ip[i-1][1]);
    fail = 0;
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=ex; i>=sx; i--)
        printf("%d %d\n", i, 1);
    } else {
      puts("-1");
    }
  } else {
    p = Point(-1,-1);
    for (int i=1; i<=N && p.x == -1; i++){
      for (int j=1; j<=M && p.x == -1; j++){
        if (ip[i][j] == op[1][1]){
          p = Point(i,j);
        }
      }
    }
    int x = p.x;
    int y = p.y;
//    printf("st = (%d, %d)\n", x, y);
    for (int j=M; j>2; j--){
      for (int i=N; i>=1; i--){
        seq._PB(Point(i,j));
      }
    }
    for (int i=N; i>2; i--){
      seq._PB(Point(i,2));
      seq._PB(Point(i,1));
    }
    _SZ(bad);
    /*
    puts("seq : ");
    for (auto i : seq)
      printf("%d %d\n", i.x, i.y);
    puts("==");
    */
    solve_seq();

    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        //printf("%d ", ip[i][j]);
        if (i>2 && j>2 && ip[i][j] != op[i][j]){
          assert(false);
          puts("FAIL QAQ");
        }
      }
     //puts("");
    }

    solve22();
    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        if (ip[i][j] != op[i][j]){
          //printf("fail @ %d %d\n", i, j);
          exit(0);
        }
      }
    }
    assert(ans.size() <= 1000000);
    printf("%d\n", (int)ans.size());
    printf("%d %d\n", x, y);
    for (auto i : ans)
      printf("%d %d\n", i.x, i.y);
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define _SZ(n) memset((n),0,sizeof(n))
#define _SMO(n) memset((n),-1,sizeof(n))
#define _MC(n,m) memcpy((n),(m),sizeof(n))
#define _F first
#define _S second
#define _MP make_pair
#define _PB push_back
#define FOR(x,y) for(__typeof(y.begin())x=y.begin();x!=y.end();x++)
#define IOS ios_base::sync_with_stdio(0)
#ifdef ONLINE_JUDGE
#define FILEIO(name) \
  freopen(name".in", "r", stdin); \
  freopen(name".out", "w", stdout);
#else
#define FILEIO(name)
#endif
// Let's Fight!

const int MX = 35;

struct Point{
  int x,y;
  Point () {}
  Point (int _x, int _y) : x(_x), y(_y) {}
  bool operator == (const Point &b) const{
    return x == b.x && y == b.y;
  }
  bool operator != (const Point &b) const{
    return !(*this == b);
  }
};

int N,M,ip[MX][MX],op[MX][MX];
Point p(-1,-1), q; // p move q to ed
vector<Point> ans;
vector<Point> seq;
int bad[MX][MX];
Point prv[MX][MX];
Point que[MX*MX];
int vst[MX][MX];
int fr,bk;
int dir[8][2] = {{-1,0},{1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
vector<Point> path;

void BFS(Point ed){
//  printf("BFS %d %d -> %d %d\n", p.x, p.y, ed.x, ed.y);
  fr = bk = 0;
  _SZ(vst);
  que[bk++] = p;
  vst[p.x][p.y] = 1;
  while (fr < bk){
    Point u = que[fr++];
    for (int i=0; i<8; i++){
      int nx = u.x + dir[i][0];
      int ny = u.y + dir[i][1];
      if (nx < 1 || ny < 1 || nx > N || ny > M) continue;
      if (bad[nx][ny]) continue;
      if (q.x == nx && q.y == ny) continue;
      if (vst[nx][ny]) continue;
      que[bk++] = Point(nx,ny);
      prv[nx][ny] = u;
      vst[nx][ny] = 1;
    }
    if (vst[ed.x][ed.y]) break;
  }
  path.clear();
  Point cur = ed;
  while (cur != p){
    path._PB(cur);
    cur = prv[cur.x][cur.y];
  }
  reverse(path.begin(),path.end());
}
void move(Point a){
  ans._PB(a);
  swap(ip[a.x][a.y],ip[p.x][p.y]);
  p = a;
}
void solve(Point ed){
  if (ip[ed.x][ed.y] == op[ed.x][ed.y]) return ;
  q = Point(-1,-1);
  for (int i=1; i<=N && q.x==-1; i++){
    for (int j=1; j<=M && q.x==-1; j++){
      if (bad[i][j]) continue;
      if (p.x == i && p.y == j) continue;
      if (ip[i][j] == op[ed.x][ed.y])
        q = Point(i,j);
    }
  }
  while (q.x != ed.x){
    while (q.x > ed.x){
      BFS(Point(q.x-1,q.y));
      for (auto i : path){
        move(i);
      }
      move(Point(p.x+1,p.y));
      q = Point(p.x-1,p.y);
    }
    while (q.x < ed.x){
      BFS(Point(q.x+1,q.y));
      for (auto i : path){
        move(i);
      }
      move(Point(p.x-1,p.y));
      q = Point(p.x+1,p.y);
    }
  }
  while (q.y != ed.y){
    while (q.y > ed.y){
      BFS(Point(q.x,q.y-1));
      for (auto i : path){
        move(i);
      }
      move(Point(p.x,p.y+1));
      q = Point(p.x,p.y-1);
    }
    while (q.y < ed.y){
      BFS(Point(q.x,q.y+1));
      for (auto i : path){
        move(i);
      }
      move(Point(p.x,p.y-1));
      q = Point(p.x,p.y+1);
    }
  }
}
void solve_seq(){
  for (auto v : seq){
//    printf("solving %d %d\n", v.x , v.y);
    solve(v);
    bad[v.x][v.y] = 1;
  }
}
void solve22(){
  if (p != Point(1,1)){
    move(Point(1,1));
  }
  if (ip[2][2] != op[2][2]){
    if (ip[1][2] == op[2][2]){
      move(Point(2,2));
      move(Point(1,2));
    } else if (ip[2][1] == op[2][2]){
      move(Point(2,2));
      move(Point(2,1));
    }
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
  if (ip[1][2] != op[1][2]){
    move(Point(2,1));
    move(Point(1,2));
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
}
int main()
{
  int c1[MX*MX] = {0};
  int c2[MX*MX] = {0};
  scanf("%d%d", &N, &M);
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &ip[i][j]);
      c1[ip[i][j]]++;
    }
  }
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &op[i][j]);
      c2[op[i][j]]++;
    }
  }
  for (int i=1; i<MX*MX; i++){
    if (c1[i] != c2[i]){
      puts("-1");
      return 0;
    }
  }
  if (N == 1){
    int sy = -1;
    int ey = -1;
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j]){
        if (sy == -1){
          sy = j;
        }
        ey = j;
      }
    }
    if (sy == -1){
      puts("0");
      return 0;
    }
    int fail=0;
    // check sy -> ey
    for (int j=sy; j<ey; j++)
      swap(ip[1][j],ip[1][j+1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=sy; j<=ey; j++)
        printf("%d %d\n", 1, j);
      return 0;
    }
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    // check ey -> sy
    fail = 0;
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=ey; j>=sy; j--)
        printf("%d %d\n", 1, j);
    } else {
      puts("-1");
    }
    return 0;
  } else if (M == 1){
    int sx = -1;
    int ex = -1;
    for (int i=1; i<=N; i++){
      if (ip[i][1] != op[i][1]){
        if (sx == -1){
          sx = i;
        }
        ex = i;
      }
    }
    if (sx == -1){
      puts("0");
      return 0;
    }
    int fail = 0;
    // check sx -> ex
    for (int i=sx; i<ex; i++)
      swap(ip[i][1],ip[i+1][1]);
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=sx; i<=ex; i++)
        printf("%d %d\n", i, 1);
      return 0;
    }
    for (int i=ex; i>sx; i--)
      swap(ip[i][1],ip[i-1][1]);
    // check ex -> sx
    for (int i=ex; i>sx; i--)
      swap(ip[i][1], ip[i-1][1]);
    fail = 0;
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=ex; i>=sx; i--)
        printf("%d %d\n", i, 1);
    } else {
      puts("-1");
    }
  } else {
    p = Point(-1,-1);
    for (int i=1; i<=N && p.x == -1; i++){
      for (int j=1; j<=M && p.x == -1; j++){
        if (ip[i][j] == op[1][1]){
          p = Point(i,j);
        }
      }
    }
    int x = p.x;
    int y = p.y;
//    printf("st = (%d, %d)\n", x, y);
    for (int j=M; j>2; j--){
      for (int i=N; i>=1; i--){
        seq._PB(Point(i,j));
      }
    }
    for (int i=N; i>2; i--){
      seq._PB(Point(i,2));
      seq._PB(Point(i,1));
    }
    _SZ(bad);
    /*
    puts("seq : ");
    for (auto i : seq)
      printf("%d %d\n", i.x, i.y);
    puts("==");
    */
    solve_seq();
    /*
    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        printf("%d ", ip[i][j]);
        if (i>2 && j>2 && ip[i][j] != op[i][j]){
          puts("FAIL QAQ");
        }
      }
      puts("");
    }
    */
    solve22();
    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        if (ip[i][j] != op[i][j]){
          printf("fail @ %d %d\n", i, j);
          exit(0);
        }
      }
    }
    printf("%d\n", (int)ans.size());
    printf("%d %d\n", x, y);
    for (auto i : ans)
      printf("%d %d\n", i.x, i.y);
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define _SZ(n) memset((n),0,sizeof(n))
#define _SMO(n) memset((n),-1,sizeof(n))
#define _MC(n,m) memcpy((n),(m),sizeof(n))
#define _F first
#define _S second
#define _MP make_pair
#define _PB push_back
#define FOR(x,y) for(__typeof(y.begin())x=y.begin();x!=y.end();x++)
#define IOS ios_base::sync_with_stdio(0)
#ifdef ONLINE_JUDGE
#define FILEIO(name) \
  freopen(name".in", "r", stdin); \
  freopen(name".out", "w", stdout);
#else
#define FILEIO(name)
#endif
// Let's Fight!

const int MX = 35;

struct Point{
  int x,y;
  Point () {}
  Point (int _x, int _y) : x(_x), y(_y) {}
  bool operator == (const Point &b) const{
    return x == b.x && y == b.y;
  }
  bool operator != (const Point &b) const{
    return !(*this == b);
  }
};

int N,M,ip[MX][MX],op[MX][MX];
Point p(-1,-1), q; // p move q to ed
vector<Point> ans;
vector<Point> seq;
int bad[MX][MX];
Point prv[MX][MX];
Point que[MX*MX];
int vst[MX][MX];
int fr,bk;
int dir[8][2] = {{-1,0},{1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
vector<Point> path;

void BFS(Point ed){
//  printf("BFS %d %d -> %d %d\n", p.x, p.y, ed.x, ed.y);
  fr = bk = 0;
  _SZ(vst);
  que[bk++] = p;
  vst[p.x][p.y] = 1;
  while (fr < bk){
    Point u = que[fr++];
    for (int i=0; i<8; i++){
      int nx = u.x + dir[i][0];
      int ny = u.y + dir[i][1];
      if (nx < 1 || ny < 1 || nx > N || ny > M) continue;
      if (bad[nx][ny]) continue;
      if (q.x == nx && q.y == ny) continue;
      if (vst[nx][ny]) continue;
      que[bk++] = Point(nx,ny);
      prv[nx][ny] = u;
      vst[nx][ny] = 1;
    }
  //  if (vst[ed.x][ed.y]) break;
  }
  assert(vst[ed.x][ed.y] == 1);
  path.clear();
  Point cur = ed;
  while (cur != p){
    path._PB(cur);
    cur = prv[cur.x][cur.y];
  }
  reverse(path.begin(),path.end());
}
void move(Point a){
  if (ans.size()){
    assert(a != ans.back());
  }
  ans._PB(a);
  swap(ip[a.x][a.y],ip[p.x][p.y]);
  p = a;
}
void solve(Point ed){
  if (ip[ed.x][ed.y] == op[ed.x][ed.y]) return ;
  q = Point(-1,-1);
  for (int i=1; i<=N && q.x==-1; i++){
    for (int j=1; j<=M && q.x==-1; j++){
      if (bad[i][j]) continue;
      if (p.x == i && p.y == j) continue;
      if (ip[i][j] == op[ed.x][ed.y])
        q = Point(i,j);
    }
  }
  while (q.x != ed.x){
    while (q.x > ed.x){
      BFS(Point(q.x-1,q.y));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
    while (q.x < ed.x){
      BFS(Point(q.x+1,q.y));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
  }
  while (q.y != ed.y){
    while (q.y > ed.y){
      BFS(Point(q.x,q.y-1));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
    while (q.y < ed.y){
      BFS(Point(q.x,q.y+1));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
  }
}
void solve_seq(){
  for (auto v : seq){
//    printf("solving %d %d\n", v.x , v.y);
    solve(v);
    bad[v.x][v.y] = 1;
  }
}
void solve22(){
  if (p != Point(1,1)){
    q = Point(-1,-1);
    BFS(Point(1,1));
    for (auto i : path){
      move(i);
    }
  }
  if (ip[2][2] != op[2][2]){
    if (ip[1][2] == op[2][2]){
      move(Point(2,2));
      move(Point(1,2));
    } else if (ip[2][1] == op[2][2]){
      move(Point(2,2));
      move(Point(2,1));
    }
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
  if (ip[1][2] != op[1][2]){
    move(Point(2,1));
    move(Point(1,2));
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
}
int main()
{
  int c1[MX*MX] = {0};
  int c2[MX*MX] = {0};
  scanf("%d%d", &N, &M);
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &ip[i][j]);
      c1[ip[i][j]]++;
    }
  }
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &op[i][j]);
      c2[op[i][j]]++;
    }
  }
  for (int i=1; i<MX*MX; i++){
    if (c1[i] != c2[i]){
      puts("-1");
      return 0;
    }
  }
  if (N == 1){
    int sy = -1;
    int ey = -1;
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j]){
        if (sy == -1){
          sy = j;
        }
        ey = j;
      }
    }
    if (sy == -1){
      puts("0");
      puts("1 1");
      return 0;
    }
    int fail=0;
    // check sy -> ey
    for (int j=sy; j<ey; j++)
      swap(ip[1][j],ip[1][j+1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=sy; j<=ey; j++)
        printf("%d %d\n", 1, j);
      return 0;
    }
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    // check ey -> sy
    fail = 0;
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=ey; j>=sy; j--)
        printf("%d %d\n", 1, j);
    } else {
      puts("-1");
    }
    return 0;
  } else if (M == 1){
    int sx = -1;
    int ex = -1;
    for (int i=1; i<=N; i++){
      if (ip[i][1] != op[i][1]){
        if (sx == -1){
          sx = i;
        }
        ex = i;
      }
    }
    if (sx == -1){
      puts("0");
      puts("1 1");
      return 0;
    }
    int fail = 0;
    // check sx -> ex
    for (int i=sx; i<ex; i++)
      swap(ip[i][1],ip[i+1][1]);
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=sx; i<=ex; i++)
        printf("%d %d\n", i, 1);
      return 0;
    }
    for (int i=ex; i>sx; i--)
      swap(ip[i][1],ip[i-1][1]);
    // check ex -> sx
    for (int i=ex; i>sx; i--)
      swap(ip[i][1], ip[i-1][1]);
    fail = 0;
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=ex; i>=sx; i--)
        printf("%d %d\n", i, 1);
    } else {
      puts("-1");
    }
    return 0;
  } else {
    p = Point(-1,-1);
    for (int i=1; i<=N && p.x == -1; i++){
      for (int j=1; j<=M && p.x == -1; j++){
        if (ip[i][j] == op[1][1]){
          p = Point(i,j);
        }
      }
    }
    int x = p.x;
    int y = p.y;
//    printf("st = (%d, %d)\n", x, y);
    for (int j=M; j>2; j--){
      for (int i=N; i>=1; i--){
        seq._PB(Point(i,j));
      }
    }
    for (int i=N; i>2; i--){
      seq._PB(Point(i,2));
      seq._PB(Point(i,1));
    }
    _SZ(bad);
    /*
    puts("seq : ");
    for (auto i : seq)
      printf("%d %d\n", i.x, i.y);
   puts("==");
    */
    solve_seq();

    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        //printf("%d ", ip[i][j]);
        if (i>2 && j>2 && ip[i][j] != op[i][j]){
          assert(false);
        }
      }
     //puts("");
    }

    solve22();
    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        if (ip[i][j] != op[i][j]){
          assert(false);
          //printf("fail @ %d %d\n", i, j);
        }
      }
    }
    assert(ans.size() <= 1000000);
    printf("%d\n", (int)ans.size());
    printf("%d %d\n", x, y);
    for (auto i : ans)
      printf("%d %d\n", i.x, i.y);
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define _SZ(n) memset((n),0,sizeof(n))
#define _SMO(n) memset((n),-1,sizeof(n))
#define _MC(n,m) memcpy((n),(m),sizeof(n))
#define _F first
#define _S second
#define _MP make_pair
#define _PB push_back
#define FOR(x,y) for(__typeof(y.begin())x=y.begin();x!=y.end();x++)
#define IOS ios_base::sync_with_stdio(0)
#ifdef ONLINE_JUDGE
#define FILEIO(name) \
  freopen(name".in", "r", stdin); \
  freopen(name".out", "w", stdout);
#else
#define FILEIO(name)
#endif
// Let's Fight!

const int MX = 35;

struct Point{
  int x,y;
  Point () {}
  Point (int _x, int _y) : x(_x), y(_y) {}
  bool operator == (const Point &b) const{
    return x == b.x && y == b.y;
  }
  bool operator != (const Point &b) const{
    return !(*this == b);
  }
};

int N,M,ip[MX][MX],op[MX][MX];
Point p(-1,-1), q; // p move q to ed
vector<Point> ans;
vector<Point> seq;
int bad[MX][MX];
Point prv[MX][MX];
Point que[MX*MX];
int vst[MX][MX];
int fr,bk;
int dir[8][2] = {{-1,0},{1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
vector<Point> path;

void BFS(Point ed){
//  printf("BFS %d %d -> %d %d\n", p.x, p.y, ed.x, ed.y);
  fr = bk = 0;
  _SZ(vst);
  que[bk++] = p;
  vst[p.x][p.y] = 1;
  while (fr < bk){
    Point u = que[fr++];
    for (int i=0; i<8; i++){
      int nx = u.x + dir[i][0];
      int ny = u.y + dir[i][1];
      if (nx < 1 || ny < 1 || nx > N || ny > M) continue;
      if (bad[nx][ny]) continue;
      if (q.x == nx && q.y == ny) continue;
      if (vst[nx][ny]) continue;
      que[bk++] = Point(nx,ny);
      prv[nx][ny] = u;
      vst[nx][ny] = 1;
    }
  //  if (vst[ed.x][ed.y]) break;
  }
  assert(vst[ed.x][ed.y] == 1);
  path.clear();
  Point cur = ed;
  while (cur != p){
    path._PB(cur);
    cur = prv[cur.x][cur.y];
  }
  reverse(path.begin(),path.end());
}
void move(Point a){
  ans._PB(a);
  swap(ip[a.x][a.y],ip[p.x][p.y]);
  p = a;
}
void solve(Point ed){
  if (ip[ed.x][ed.y] == op[ed.x][ed.y]) return ;
  q = Point(-1,-1);
  for (int i=1; i<=N && q.x==-1; i++){
    for (int j=1; j<=M && q.x==-1; j++){
      if (bad[i][j]) continue;
      if (p.x == i && p.y == j) continue;
      if (ip[i][j] == op[ed.x][ed.y])
        q = Point(i,j);
    }
  }
  while (q.x != ed.x){
    while (q.x > ed.x){
      BFS(Point(q.x-1,q.y));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
    while (q.x < ed.x){
      BFS(Point(q.x+1,q.y));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
  }
  while (q.y != ed.y){
    while (q.y > ed.y){
      BFS(Point(q.x,q.y-1));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
    while (q.y < ed.y){
      BFS(Point(q.x,q.y+1));
      for (auto i : path){
        move(i);
      }
      Point tmp = p;
      move(q);
      q = tmp;
    }
  }
}
void solve_seq(){
  for (auto v : seq){
//    printf("solving %d %d\n", v.x , v.y);
    solve(v);
    bad[v.x][v.y] = 1;
  }
}
void solve22(){
  if (p != Point(1,1)){
    move(Point(1,1));
  }
  if (ip[2][2] != op[2][2]){
    if (ip[1][2] == op[2][2]){
      move(Point(2,2));
      move(Point(1,2));
    } else if (ip[2][1] == op[2][2]){
      move(Point(2,2));
      move(Point(2,1));
    }
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
  if (ip[1][2] != op[1][2]){
    move(Point(2,1));
    move(Point(1,2));
  }
  if (p != Point(1,1)){
    move(Point(1,1));
  }
}
int main()
{
  int c1[MX*MX] = {0};
  int c2[MX*MX] = {0};
  scanf("%d%d", &N, &M);
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &ip[i][j]);
      c1[ip[i][j]]++;
    }
  }
  for (int i=1; i<=N; i++){
    for (int j=1; j<=M; j++){
      scanf("%d", &op[i][j]);
      c2[op[i][j]]++;
    }
  }
  for (int i=1; i<MX*MX; i++){
    if (c1[i] != c2[i]){
      puts("-1");
      return 0;
    }
  }
  if (N == 1){
    int sy = -1;
    int ey = -1;
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j]){
        if (sy == -1){
          sy = j;
        }
        ey = j;
      }
    }
    if (sy == -1){
      puts("0");
      puts("1 1");
      return 0;
    }
    int fail=0;
    // check sy -> ey
    for (int j=sy; j<ey; j++)
      swap(ip[1][j],ip[1][j+1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=sy; j<=ey; j++)
        printf("%d %d\n", 1, j);
      return 0;
    }
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    // check ey -> sy
    fail = 0;
    for (int j=ey; j>sy; j--)
      swap(ip[1][j],ip[1][j-1]);
    for (int j=1; j<=M; j++){
      if (ip[1][j] != op[1][j])
        fail = 1;
    }
    if (!fail){
      printf("%d\n", ey-sy);
      for (int j=ey; j>=sy; j--)
        printf("%d %d\n", 1, j);
    } else {
      puts("-1");
    }
    return 0;
  } else if (M == 1){
    int sx = -1;
    int ex = -1;
    for (int i=1; i<=N; i++){
      if (ip[i][1] != op[i][1]){
        if (sx == -1){
          sx = i;
        }
        ex = i;
      }
    }
    if (sx == -1){
      puts("0");
      puts("1 1");
      return 0;
    }
    int fail = 0;
    // check sx -> ex
    for (int i=sx; i<ex; i++)
      swap(ip[i][1],ip[i+1][1]);
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=sx; i<=ex; i++)
        printf("%d %d\n", i, 1);
      return 0;
    }
    for (int i=ex; i>sx; i--)
      swap(ip[i][1],ip[i-1][1]);
    // check ex -> sx
    for (int i=ex; i>sx; i--)
      swap(ip[i][1], ip[i-1][1]);
    fail = 0;
    for (int i=1; i<=N; i++)
      if (ip[i][1] != op[i][1])
        fail = 1;
    if (!fail){
      printf("%d\n", ex-sx);
      for (int i=ex; i>=sx; i--)
        printf("%d %d\n", i, 1);
    } else {
      puts("-1");
    }
    return 0;
  } else {
    p = Point(-1,-1);
    for (int i=1; i<=N && p.x == -1; i++){
      for (int j=1; j<=M && p.x == -1; j++){
        if (ip[i][j] == op[1][1]){
          p = Point(i,j);
        }
      }
    }
    int x = p.x;
    int y = p.y;
//    printf("st = (%d, %d)\n", x, y);
    for (int j=M; j>2; j--){
      for (int i=N; i>=1; i--){
        seq._PB(Point(i,j));
      }
    }
    for (int i=N; i>2; i--){
      seq._PB(Point(i,2));
      seq._PB(Point(i,1));
    }
    _SZ(bad);
    /*
    puts("seq : ");
    for (auto i : seq)
      printf("%d %d\n", i.x, i.y);
    puts("==");
    */
    solve_seq();

    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        //printf("%d ", ip[i][j]);
        if (i>2 && j>2 && ip[i][j] != op[i][j]){
          assert(false);
        }
      }
     //puts("");
    }

    solve22();
    for (int i=1; i<=N; i++){
      for (int j=1; j<=M; j++){
        if (ip[i][j] != op[i][j]){
          assert(false);
          //printf("fail @ %d %d\n", i, j);
        }
      }
    }
    assert(ans.size() <= 1000000);
    printf("%d\n", (int)ans.size());
    printf("%d %d\n", x, y);
    for (auto i : ans)
      printf("%d %d\n", i.x, i.y);
  }

  return 0;
}


// {{{ by shik
#include <bits/stdc++.h>
#include <unistd.h>
#define SZ(x) ((int)(x).size())
#define ALL(x) begin(x),end(x)
#define REP(i,n) for ( int i=0; i<int(n); i++ )
#define REP1(i,a,b) for ( int i=(a); i<=int(b); i++ )
#define FOR(it,c) for ( auto it=(c).begin(); it!=(c).end(); it++ )
#define MP make_pair
#define PB push_back
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef vector<int> VI;

void RI() {}

template<typename... T>
void RI( int& head, T&... tail ) {
    scanf("%d",&head);
    RI(tail...);
}
// }}}

#define N 33
int n,m,s[N][N],t[N][N];

void print_sol( const vector<PII> &sol ) {
    printf("%d\n",SZ(sol)-1);
    FOR(it,sol) printf("%d %d\n",it->first,it->second);
}

bool test_lr( int nn, int ss[N], int tt[N], int l, int r ) {
    if ( l<r ) {
        REP1(i,l,r-1) swap(ss[i],ss[i+1]);
    } else {
        for ( int i=l; i>r; i-- ) swap(ss[i],ss[i-1]);
    }
    REP1(i,1,nn) if ( ss[i]!=tt[i] ) return 0;
    return 1;
}

bool test_n1( int l, int r ) {
    static int ss[N],tt[N];
    REP1(i,1,m) {
        ss[i]=s[1][i];
        tt[i]=t[1][i];
    }
    return test_lr(m,ss,tt,l,r);
}

bool test_m1( int l, int r ) {
    static int ss[N],tt[N];
    REP1(i,1,n) {
        ss[i]=s[i][1];
        tt[i]=t[i][1];
    }
    return test_lr(n,ss,tt,l,r);
}

void solve_n1() {
    REP1(i,1,m) REP1(j,1,m) if ( test_n1(i,j) ) {
        vector<PII> sol;
        if ( i<j ) {
            REP1(k,i,j) sol.PB(MP(1,k));
        } else {
            for ( int k=i; k>=j; k-- ) sol.PB(MP(1,k));
        }
        print_sol(sol);
        return;
    }
    puts("-1");
}

void solve_m1() {
    REP1(i,1,n) REP1(j,1,n) if ( test_m1(i,j) ) {
        vector<PII> sol;
        if ( i<j ) {
            REP1(k,i,j) sol.PB(MP(k,1));
        } else {
            for ( int k=i; k>=j; k-- ) sol.PB(MP(k,1));
        }
        print_sol(sol);
        return;
    }
    puts("-1");
}

int x,y;
vector<PII> sol;
bool fix[N][N];

int sg( int v ) { return (v>0)-(v<0); }

void go( int xx, int yy ) {
    //printf("go %d, %d\n",xx,yy);
    assert(max(abs(xx-x),abs(yy-y))==1);
    swap(s[x][y],s[xx][yy]);
    sol.PB(MP(xx,yy));
    x=xx; y=yy;
}

void move_to( int tx, int ty ) {
    //printf("move to: (%d,%d) => (%d,%d)\n",x,y,tx,ty);
    static int q[2*N*N],ql,qr,fx[N][N],fy[N][N],vis[N][N],vid;
    auto push=[&]( int xx, int yy ) {
        q[qr++]=xx;
        q[qr++]=yy;
        vis[xx][yy]=vid;
    };
    auto pop=[&]( int &xx, int &yy ) {
        xx=q[ql++];
        yy=q[ql++];
    };
    vid++;
    ql=qr=0;
    push(x,y);
    while ( ql!=qr && vis[tx][ty]!=vid ) {
        int xx,yy; pop(xx,yy);
        REP1(i,-1,+1) REP1(j,-1,+1) {
            int nx=xx+i;
            int ny=yy+j;
            if ( nx<1 || nx>n || ny<1 || ny>m ) continue;
            if ( fix[nx][ny] || vis[nx][ny]==vid ) continue;
            fx[nx][ny]=xx;
            fy[nx][ny]=yy;
            push(nx,ny);
        }
    }
    assert(vis[tx][ty]==vid);
    vector<PII> v;
    while ( tx!=x || ty!=y ) {
        v.PB(MP(tx,ty));
        int ntx=fx[tx][ty];
        int nty=fy[tx][ty];
        tx=ntx; ty=nty;
    }
    reverse(ALL(v));
    FOR(it,v) go(it->first,it->second);
}

void move_one( int x1, int y1, int x2, int y2 ) {
    //printf("move one (%d,%d) => (%d,%d)\n",x1,y1,x2,y2);
    while ( x1!=x2 || y1!=y2 ) {
        int dx=sg(x2-x1);
        int dy=sg(y2-y1);
        //printf("(%d, %d)\n",dx,dy);
        int nx1=x1,ny1=y1;
        if ( !fix[x1+dx][y1+dy] ) nx1=x1+dx,ny1=y1+dy;
        else if ( dx!=0 && !fix[x1+dx][y1] ) nx1=x1+dx;
        else if ( dy!=0 && !fix[x1][y1+dy] ) ny1=y1+dy;
        assert(x1!=nx1 || y1!=ny1);
        //printf("-- move one: %d,%d => %d,%d\n",x1,y1,nx1,ny1);
        fix[x1][y1]=1;
        move_to(nx1,ny1);
        fix[x1][y1]=0;
        go(x1,y1);
        x1=nx1; y1=ny1;
    }
}

void solve_one( int gx, int gy ) {
    int gz=t[gx][gy];
    //printf("solve_one (%d,%d,%d)\n",gx,gy,gz);
    REP1(i,1,n) REP1(j,1,m) if ( (i!=x || j!=y) && !fix[i][j] && s[i][j]==gz ) {
        move_one(i,j,gx,gy);
        i=j=N;
    }
    //REP1(i,1,n) REP1(j,1,m) printf("%d%c",s[i][j],j==m?'\n':' ');
    assert(s[gx][gy]==t[gx][gy]);
    fix[gx][gy]=1;
}

void solve() {
    REP1(i,1,n) REP1(j,1,m) if ( s[i][j]==t[n][m] ) {
        x=i; y=j;
        i=j=N;
    }
    assert(x && y);
    sol.PB(MP(x,y));
    REP1(i,1,n-2) REP1(j,1,m) solve_one(i,j);
    REP1(i,1,m-2) {
        solve_one(n-1,i);
        solve_one(n,i);
    }
    assert(n-1<=x && x<=n);
    assert(m-1<=y && y<=m);
    while ( 1 ) {
        bool done=1;
        //REP1(i,n-1,n) REP1(j,m-1,m) printf("(%d, %d) ",s[i][j],t[i][j]); puts("");
        REP1(i,n-1,n) REP1(j,m-1,m) if ( s[i][j]!=t[i][j] ) done=0;
        if ( done ) break;
        int nx=n-1+rand()%2;
        int ny=m-1+rand()%2;
        if ( x==nx && y==ny ) continue;
        go(nx,ny);
    }
    REP1(i,1,n) REP1(j,1,m) assert(s[i][j]==t[i][j]);
    print_sol(sol);
}

int main() {
    srand(time(0)^514514514^getpid());
    RI(n,m);
    REP1(i,1,n) REP1(j,1,m) RI(s[i][j]);
    REP1(i,1,n) REP1(j,1,m) RI(t[i][j]);
    int c[1000]={};
    REP1(i,1,n) REP1(j,1,m) c[s[i][j]]++;
    REP1(i,1,n) REP1(j,1,m) c[t[i][j]]--;
    REP(i,1000) if ( c[i]!=0 ) {
        puts("-1");
        return 0;
    }
    if ( n==1 ) solve_n1();
    else if ( m==1 ) solve_m1();
    else solve();
    //fprintf(stderr, "%d %d %d\n",n,m,SZ(sol));
    return 0;
}


// {{{ by shik
#include <bits/stdc++.h>
#include <unistd.h>
#define SZ(x) ((int)(x).size())
#define ALL(x) begin(x),end(x)
#define REP(i,n) for ( int i=0; i<int(n); i++ )
#define REP1(i,a,b) for ( int i=(a); i<=int(b); i++ )
#define FOR(it,c) for ( auto it=(c).begin(); it!=(c).end(); it++ )
#define MP make_pair
#define PB push_back
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef vector<int> VI;

void RI() {}

template<typename... T>
void RI( int& head, T&... tail ) {
    scanf("%d",&head);
    RI(tail...);
}
// }}}

#define N 33
int n,m,s[N][N],t[N][N];

void print_sol( const vector<PII> &sol ) {
    printf("%d\n",SZ(sol));
    FOR(it,sol) printf("%d %d\n",it->first,it->second);
}

bool test_lr( int nn, int ss[N], int tt[N], int l, int r ) {
    if ( l<r ) {
        REP1(i,l,r-1) swap(ss[i],ss[i+1]);
    } else {
        for ( int i=l; i>r; i-- ) swap(ss[i],ss[i-1]);
    }
    REP1(i,1,nn) if ( ss[i]!=tt[i] ) return 0;
    return 1;
}

bool test_n1( int l, int r ) {
    static int ss[N],tt[N];
    REP1(i,1,m) {
        ss[i]=s[1][i];
        tt[i]=t[1][i];
    }
    return test_lr(m,ss,tt,l,r);
}

bool test_m1( int l, int r ) {
    static int ss[N],tt[N];
    REP1(i,1,n) {
        ss[i]=s[i][1];
        tt[i]=t[i][1];
    }
    return test_lr(n,ss,tt,l,r);
}

void solve_n1() {
    REP1(i,1,m) REP1(j,1,m) if ( test_n1(i,j) ) {
        vector<PII> sol;
        if ( i<j ) {
            REP1(k,i,j) sol.PB(MP(1,k));
        } else {
            for ( int k=i; k>=j; k-- ) sol.PB(MP(1,k));
        }
        print_sol(sol);
        return;
    }
    puts("-1");
}

void solve_m1() {
    REP1(i,1,n) REP1(j,1,n) if ( test_m1(i,j) ) {
        vector<PII> sol;
        if ( i<j ) {
            REP1(k,i,j) sol.PB(MP(k,1));
        } else {
            for ( int k=i; k>=j; k-- ) sol.PB(MP(k,1));
        }
        print_sol(sol);
        return;
    }
    puts("-1");
}

int x,y;
vector<PII> sol;
bool fix[N][N];

int sg( int v ) { return (v>0)-(v<0); }

void go( int xx, int yy ) {
    //printf("go %d, %d\n",xx,yy);
    assert(max(abs(xx-x),abs(yy-y))==1);
    swap(s[x][y],s[xx][yy]);
    sol.PB(MP(xx,yy));
    x=xx; y=yy;
}

void move_to( int tx, int ty ) {
    //printf("move to: (%d,%d) => (%d,%d)\n",x,y,tx,ty);
    static int q[2*N*N],ql,qr,fx[N][N],fy[N][N],vis[N][N],vid;
    auto push=[&]( int xx, int yy ) {
        q[qr++]=xx;
        q[qr++]=yy;
        vis[xx][yy]=vid;
    };
    auto pop=[&]( int &xx, int &yy ) {
        xx=q[ql++];
        yy=q[ql++];
    };
    vid++;
    ql=qr=0;
    push(x,y);
    while ( ql!=qr && vis[tx][ty]!=vid ) {
        int xx,yy; pop(xx,yy);
        REP1(i,-1,+1) REP1(j,-1,+1) {
            int nx=xx+i;
            int ny=yy+j;
            if ( nx<1 || nx>n || ny<1 || ny>m ) continue;
            if ( fix[nx][ny] || vis[nx][ny]==vid ) continue;
            fx[nx][ny]=xx;
            fy[nx][ny]=yy;
            push(nx,ny);
        }
    }
    assert(vis[tx][ty]==vid);
    vector<PII> v;
    while ( tx!=x || ty!=y ) {
        v.PB(MP(tx,ty));
        int ntx=fx[tx][ty];
        int nty=fy[tx][ty];
        tx=ntx; ty=nty;
    }
    reverse(ALL(v));
    FOR(it,v) go(it->first,it->second);
}

void move_one( int x1, int y1, int x2, int y2 ) {
    //printf("move one (%d,%d) => (%d,%d)\n",x1,y1,x2,y2);
    while ( x1!=x2 || y1!=y2 ) {
        int dx=sg(x2-x1);
        int dy=sg(y2-y1);
        //printf("(%d, %d)\n",dx,dy);
        int nx1=x1,ny1=y1;
        if ( !fix[x1+dx][y1+dy] ) nx1=x1+dx,ny1=y1+dy;
        else if ( dx!=0 && !fix[x1+dx][y1] ) nx1=x1+dx;
        else if ( dy!=0 && !fix[x1][y1+dy] ) ny1=y1+dy;
        assert(x1!=nx1 || y1!=ny1);
        //printf("-- move one: %d,%d => %d,%d\n",x1,y1,nx1,ny1);
        fix[x1][y1]=1;
        move_to(nx1,ny1);
        fix[x1][y1]=0;
        go(x1,y1);
        x1=nx1; y1=ny1;
    }
}

void solve_one( int gx, int gy ) {
    int gz=t[gx][gy];
    //printf("solve_one (%d,%d,%d)\n",gx,gy,gz);
    REP1(i,1,n) REP1(j,1,m) if ( (i!=x || j!=y) && !fix[i][j] && s[i][j]==gz ) {
        move_one(i,j,gx,gy);
        i=j=N;
    }
    //REP1(i,1,n) REP1(j,1,m) printf("%d%c",s[i][j],j==m?'\n':' ');
    assert(s[gx][gy]==t[gx][gy]);
    fix[gx][gy]=1;
}

void solve() {
    REP1(i,1,n) REP1(j,1,m) if ( s[i][j]==t[n][m] ) {
        x=i; y=j;
        i=j=N;
    }
    assert(x && y);
    sol.PB(MP(x,y));
    REP1(i,1,n-2) REP1(j,1,m) solve_one(i,j);
    REP1(i,1,m-2) {
        solve_one(n-1,i);
        solve_one(n,i);
    }
    assert(n-1<=x && x<=n);
    assert(m-1<=y && y<=m);
    while ( 1 ) {
        bool done=1;
        //REP1(i,n-1,n) REP1(j,m-1,m) printf("(%d, %d) ",s[i][j],t[i][j]); puts("");
        REP1(i,n-1,n) REP1(j,m-1,m) if ( s[i][j]!=t[i][j] ) done=0;
        if ( done ) break;
        int nx=n-1+rand()%2;
        int ny=m-1+rand()%2;
        if ( x==nx && y==ny ) continue;
        go(nx,ny);
    }
    REP1(i,1,n) REP1(j,1,m) assert(s[i][j]==t[i][j]);
    print_sol(sol);
}

int main() {
    srand(time(0)^514514514^getpid());
    RI(n,m);
    REP1(i,1,n) REP1(j,1,m) RI(s[i][j]);
    REP1(i,1,n) REP1(j,1,m) RI(t[i][j]);
    int c[1000]={};
    REP1(i,1,n) REP1(j,1,m) c[s[i][j]]++;
    REP1(i,1,n) REP1(j,1,m) c[t[i][j]]--;
    REP(i,1000) if ( c[i]!=0 ) {
        puts("-1");
        return 0;
    }
    if ( n==1 ) solve_n1();
    else if ( m==1 ) solve_m1();
    else solve();
    //fprintf(stderr, "%d %d %d\n",n,m,SZ(sol));
    return 0;
}


//by david942j
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <map>
#include <queue>
#include <iostream>
#include <set>
#include <cassert>
#include <stack>
#define PAUSE fgetc(stdin);
#include <string>
#include <cmath>
#include <algorithm>
#define openfile(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define mpr std::make_pair
#define X first
#define Y second
#define mst(x) memset(x,0,sizeof(x))
#define mst1(x) memset(x,-1,sizeof(x))
#define ALL(c) (c).begin(),(c).end()
#define FOR(i,n) for(int i=0;i<n;i++)
#define FOR1(i,n) for(int i=1;i<=n;i++)
#define FORit(it,c) for(__typeof(c.begin()) it=c.begin();it!=c.end();++it)
#define pb push_back
#define __count(x) __builtin_popcount(x)
#define RI(x) scanf("%d",&x)
#define RI2(a,b) scanf("%d%d",&a,&b)
#define RI3(a,b,c) scanf("%d%d%d",&a,&b,&c)
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef std::pair<int,int> PII;
template<class T>inline void maz(T &a,T b){if(a<b)a=b;}
template<class T>inline void miz(T &a,T b){if(a>b)a=b;}
template<class T>inline T abs(T a){return a>0?a:-a;}
const int N=40, lgN=20;
const int INF=2000000000;
int n,m,*A[N],*B[N];
bool fail;
bool rev;
vector<PII> ans;

int *bA[N];
void print(int **A,int n,int m) {
    FOR(i,n)FOR(j,m)printf("%d%c",A[i][j],j==m-1?'\n':' ');
}
int **reflex(int n,int m,int **A) {
    int **B=new int*[m];
    FOR(i,m)B[i]=new int[n];
    FOR(i,n)FOR(j,m)B[j][i]=A[i][j];
    return B;
}
bool same(int **A,int **B,int n,int m) {
    FOR(i,n)FOR(j,m)if(A[i][j]!=B[i][j])return false;
    return true;
}
void find_c(int n,int m,int p,int **A,int c,int &x,int &y) {
    FOR(j,m)FOR(i,n)
    if(i+j==0)continue;
    else if(j==m-1 && i>=p)return;
    else if(A[i][j]==c) {
        x=i;y=j;
        return;
    }
}
enum {
    UP=0,
    DOWN=1,
    LEFT=2,
    RIGHT=3,
    RU=4,
    RD=5,
    LD=6,
    LU=7
};
int dx[]={-1,1,0,0,-1,1,1,-1},dy[]={0,0,-1,1,1,1,-1,-1};
void udlr(int **A,int &x,int &y,int d) {
    swap(A[x][y],A[x+dx[d]][y+dy[d]]);
    x+=dx[d];y+=dy[d];
    if(rev)ans.pb(mpr(y,x));
    else ans.pb(mpr(x,y));
}
void d_move(int **A,int &x,int &y,int a,int b) {
    while(x!=a || y!=b) {
        if(x>a)udlr(A,x,y,0);
        else if(x<a)udlr(A,x,y,1);
        else if(y>b)udlr(A,x,y,2);
        else if(y<b)udlr(A,x,y,3);
    }
}

void make_up(int **A,int &x,int &y) {
    udlr(A,x,y,DOWN);
    if(x==1)return;
    if(y>0) {
        udlr(A,x,y,LU);
        udlr(A,x,y,RU);
        make_up(A,x,y);
    }
    else {
        udlr(A,x,y,RU);
        udlr(A,x,y,LU);
        make_up(A,x,y);
    }
}
void make_right(int **A,int &x,int &y,int m) {
    udlr(A,x,y,RU);
    udlr(A,x,y,LEFT);
    if(y==m-2)return;
    udlr(A,x,y,RD);
    make_right(A,x,y,m);
}
void make_down(int **A,int &x,int &y,int n) {
    udlr(A,x,y,RD);
    udlr(A,x,y,UP);
    if(x==n-2)return;
    udlr(A,x,y,LD);
    make_down(A,x,y,n);
}
void just_go(int x,int a,int **A) {
    if(x==a)return;
    if(x<a) {
        for(int i=x+1;i<=a;i++)
            swap(A[0][i],A[0][i-1]);
    }
    else {
        for(int i=x-1;i>=a;i--)
            swap(A[0][i],A[0][i+1]);
    }
}
void solve1(int n,int m,int **A,int **B) {
    if(n>m) {
        int **C,**D;
        C=reflex(n,m,A);
        D=reflex(n,m,B);
        rev^=1;
        return solve1(m,n,C,D);
    }
    FOR(i,m)FOR(j,m) {
        just_go(i,j,A);
        if(same(A,B,1,m)) {
            int x=0,y=i;
            if(rev)ans.pb(mpr(y,x));
            else ans.pb(mpr(x,y));
            d_move(A,x,y,0,j);
            return;
        }
        just_go(j,i,A);
    }
    fail=true;
}
void solve22(int **A,int **B) {
    int x=0,y=0;
    int step=0;
    while(true) {
        if(same(A,B,2,2))return;
        if(step>1000){fail=true;return;}
        while(true) {
            int r=rand()%8;
            int a=x+dx[r],b=y+dy[r];
            if(a<0||a>=2||b<0||b>=2)continue;
            udlr(A,x,y,r);
            step++;
            break;
        }
    }
}
void solve(int n,int m,int **A,int **B) {
    if(n>m) {
        int **C,**D;
        C=reflex(n,m,A);
        D=reflex(n,m,B);
        rev^=1;
        return solve(m,n,C,D);
    }
    if(n==2 && m==2)
        return solve22(A,B);
    for(int i=n-1;i>=0;i--) {
        int x=-1,y=-1;
        if(A[i][m-1]==B[i][m-1])continue;
        find_c(n,m,i,A,B[i][m-1],x,y);
        if(x==-1){fail=true;return;}
        int nowx=0,nowy=0;
        if(x==0) {
            d_move(A,nowx,nowy,x,y-1);
            udlr(A,nowx,nowy,RD);
        }
        else {
            d_move(A,nowx,nowy,x-1,y);
            make_up(A,nowx,nowy); //make nowx+1,nowy to top
        }
        if(nowy==m-1)
            udlr(A,nowx,nowy,LU);
        else make_right(A,nowx,nowy,m); //make nowx-1,nowy to rightest
        if(nowx==i)d_move(A,nowx,nowy,0,0);//back
        else {
            make_down(A,nowx,nowy,i+1);//make nowx,nowy+1 to i,nowy+1
            d_move(A,nowx,nowy,0,0);//back
        }
    }
    solve(n,m-1,A,B);
}
int main() {
    FOR(i,N)A[i]=new int [N],bA[i]=new int [N];
    FOR(i,N)B[i]=new int [N];
    RI2(n,m);
    FOR(i,n)FOR(j,m)RI(A[i][j]),bA[i][j]=A[i][j];
    FOR(i,n)FOR(j,m)RI(B[i][j]);
    if(min(n,m)==1) solve1(n,m,A,B);
    else {
        if(A[0][0]!=B[0][0]) {
            int x=-1,y;
            find_c(n,m,N,A,B[0][0],x,y);
            if(x==-1){puts("-1");return 0;}
            ans.pb(mpr(x,y));
            d_move(A,x,y,0,0);
        }
        else ans.pb(mpr(0,0));
        solve(n,m,A,B);
    }
    if(fail)puts("-1");
    else {
        printf("%d\n",ans.size()-1);
        FOR(i,ans.size())
            printf("%d %d\n",ans[i].X+1,ans[i].Y+1);
    }
    /*FOR1(i,(int)ans.size()-1) {
        swap(bA[ans[i-1].X][ans[i-1].Y],bA[ans[i].X][ans[i].Y]);
    }*/
    //print(bA,n,m);
}
/*

  2 6
  1 2 3 4 5 6
  7 8 9 1 2 3

  1 6 5 4 3 2
  3 7 8 1 2 9

  3 3
  1 3 9
  2 4 1
  6 7 2

  4 7 6
  2 9 3
  1 1 2

  2 2
  1 3
  2 3
  1 3
  3 2

  2 2
  1 3
  2 3
  1 2
  2 3

  1 4
  1 2 3 4
  4 3 2 1

  4 1
  1
  2
  3
  4
  3
  1
  2
  4

 */


#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
#include<cmath>
#include<vector>
#define int64 long long
#define mk make_pair
#define pb push_back
#define sqr(x) (x)*(x)
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define VI vector<int>
#define VS vector<string>
#define PII pair<int,int>
#define PDD pair<double,double>
#define VPII vector< PII >
#define N 33
using namespace std;
const double pi=acos(-1);
const int d[8][2]={-1,0, 1,0, 0,-1, 0,1, -1,-1, -1,1, 1,-1, 1,1};
int num1[N*N],num2[N*N],map[N][N],End[N][N],bo[N][N];
int n,m,X,Y;
bool Rotate=0;
VPII ans;
void renum(int a[N][N],int num[]){
	rep(i,1,n)
		rep(j,1,m)num[a[i][j]]++;
	rep(i,1,900)num[i]+=num[i-1];
	rep(i,1,n)
		rep(j,1,m)a[i][j]=num[a[i][j]]--;
}
bool out(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	if(x<1 || x>n || y<1 || y>m)return 1;
	return 0;
}
void Move(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	swap(map[x][y],map[X][Y]);
	X=x; Y=y;
}
void Go(int tx,int ty){
	int tmpx=-1,tmpy=-1;
	for(;;){
		if(X==tx && Y==ty)break;
		int x,y,minn=1<<30,choose;
		rep(i,0,7){
			x=X+d[i][0];
			y=Y+d[i][1];
			if(out(i) || bo[x][y] || (x==tmpx && y==tmpy))continue;
			if(abs(x-tx)+abs(y-ty)<minn){
				minn=abs(x-tx)+abs(y-ty);
				choose=i;
			}
		}
		tmpx=X; tmpy=Y;
		Move(choose);
		ans.pb(mk(X,Y));
	}
}
void print(){
	printf("%d\n",ans.size()-1);
	for(PII tmp:ans)printf("%d %d\n",tmp.first,tmp.second);
	exit(0);
}
void init(){
	scanf("%d%d",&n,&m);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&map[i][j]);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&End[i][j]);
	renum(map,num1);
	renum(End,num2);
	rep(i,1,900)if(num1[i]!=num2[i]){
		printf("-1\n");
		exit(0);
	}
}
void work1(){
	rep(i,1,m)
		rep(j,1,m)if(i!=j){
			X=1; Y=i;
			ans.clear();
			ans.pb(mk(1,i));
			Go(1,j);
			bool f=1;
			rep(k,1,m)if(map[1][k]!=End[1][k])f=0;
			if(f){
				if(Rotate)for(PII &tmp:ans)swap(tmp.first,tmp.second);
				print();
			}
			Go(1,i);
		}
	printf("-1\n");
	exit(0);
}
PII Find(int x){
	rep(i,1,n)
		rep(j,1,m)if(map[i][j]==x)return mk(i,j);
	puts("***");
}
void Push(int &x,int &y,int dir){
	int xx=x+d[dir][0],yy=y+d[dir][1];
	Go(xx,yy);
	Move(dir^1);
	ans.pb(mk(x,y));
	swap(bo[x][y],bo[xx][yy]);
	x=xx;
	y=yy;
}
void work2(){
	X=n; Y=m;
	ans.pb(mk(n,m));
	rep(i,1,n-2)
		rep(j,1,m){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(y<j)Push(x,y,3);
			while(y>j)Push(x,y,2);
			while(x>i)Push(x,y,0);
		}
	rep(j,1,m-2)
		rep(i,n-1,n){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(x<i)Push(x,y,1);
			while(x>i)Push(x,y,0);
			while(y>j)Push(x,y,2);
		}
	//
	srand(time(0));
	for(;;){
		bool f=1;
		rep(i,n-1,n)
			rep(j,m-1,m)if(map[i][j]!=End[i][j])f=0;
		if(f)break;
		int dir=rand()%8;
		int x=X+d[dir][0],y=Y+d[dir][1];
		if((x==n-1 || x==n) && (y==m-1 || y==m))Move(dir),ans.pb(mk(X,Y));
	}
	print();
}
int main(){
	init();
	if(m==1){
		Rotate=1;
		rep(i,1,n)map[1][i]=map[i][1],End[1][i]=End[i][1];
		swap(n,m);
	}
	if(n==1)work1();
	else work2();
}


#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
#include<cmath>
#include<vector>
#define int64 long long
#define mk make_pair
#define pb push_back
#define sqr(x) (x)*(x)
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define VI vector<int>
#define VS vector<string>
#define PII pair<int,int>
#define PDD pair<double,double>
#define VPII vector< PII >
#define N 33
using namespace std;
const double pi=acos(-1);
const int d[8][2]={-1,0, 1,0, 0,-1, 0,1, -1,-1, -1,1, 1,-1, 1,1};
int num1[N*N],num2[N*N],map[N][N],End[N][N],bo[N][N];
int n,m,X,Y;
bool Rotate=0;
VPII ans;
void renum(int a[N][N],int num[]){
	rep(i,1,n)
		rep(j,1,m)num[a[i][j]]++;
	rep(i,1,900)num[i]+=num[i-1];
	rep(i,1,n)
		rep(j,1,m)a[i][j]=num[a[i][j]]--;
}
bool out(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	if(x<1 || x>n || y<1 || y>m)return 1;
	return 0;
}
void Move(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	swap(map[x][y],map[X][Y]);
	X=x; Y=y;
}
void Go(int tx,int ty){
	int tmpx=-1,tmpy=-1;
	for(;;){
		if(X==tx && Y==ty)break;
		int x,y,minn=1<<30,choose;
		rep(i,0,7){
			x=X+d[i][0];
			y=Y+d[i][1];
			if(out(i) || bo[x][y] || (x==tmpx && y==tmpy))continue;
			if(abs(x-tx)+abs(y-ty)<minn){
				minn=abs(x-tx)+abs(y-ty);
				choose=i;
			}
		}
		tmpx=X; tmpy=Y;
		Move(choose);
		ans.pb(mk(X,Y));
	}
}
void print(){
	printf("%d\n",ans.size()-1);
	for(PII tmp:ans)printf("%d %d\n",tmp.first,tmp.second);
	exit(0);
}
void init(){
	scanf("%d%d",&n,&m);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&map[i][j]);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&End[i][j]);
	renum(map,num1);
	renum(End,num2);
	rep(i,1,900)if(num1[i]!=num2[i]){
		printf("-1\n");
		exit(0);
	}
}
void work1(){
	rep(i,1,m)
		rep(j,1,m)if(i!=j){
			X=1; Y=i;
			ans.clear();
			ans.pb(mk(1,i));
			Go(1,j);
			bool f=1;
			rep(k,1,m)if(map[1][k]!=End[1][k])f=0;
			if(f){
				if(Rotate)for(PII &tmp:ans)swap(tmp.first,tmp.second);
				print();
			}
			Go(1,i);
		}
	printf("-1\n");
	exit(0);
}
PII Find(int x){
	rep(i,1,n)
		rep(j,1,m)if(map[i][j]==x)return mk(i,j);
}
void Push(int &x,int &y,int dir){
	int xx=x+d[dir][0],yy=y+d[dir][1];
	Go(xx,yy);
	Move(dir^1);
	ans.pb(mk(x,y));
	swap(bo[x][y],bo[xx][yy]);
	x=xx;
	y=yy;
}
void work2(){
	PII St=Find(End[n][m]);
	X=St.first;
	Y=St.second;
	ans.pb(mk(n,m));
	rep(i,1,n-2)
		rep(j,1,m){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(y<j)Push(x,y,3);
			while(y>j)Push(x,y,2);
			while(x>i)Push(x,y,0);
		}
	rep(j,1,m-2)
		rep(i,n-1,n){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(x<i)Push(x,y,1);
			while(x>i)Push(x,y,0);
			while(y>j)Push(x,y,2);
		}
	//wei
	srand(time(0));
	for(;;){
		bool f=1;
		rep(i,n-1,n)
			rep(j,m-1,m)if(map[i][j]!=End[i][j])f=0;
		if(f)break;
		int dir=rand()%8;
		int x=X+d[dir][0],y=Y+d[dir][1];
		if((x==n-1 || x==n) && (y==m-1 || y==m))Move(dir),ans.pb(mk(X,Y));
	}
	print();
}
int main(){
	init();
	if(m==1){
		Rotate=1;
		rep(i,1,n)map[1][i]=map[i][1],End[1][i]=End[i][1];
		swap(n,m);
	}
	if(n==1)work1();
	else work2();
}


#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
#include<cmath>
#include<vector>
#define int64 long long
#define mk make_pair
#define pb push_back
#define sqr(x) (x)*(x)
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define VI vector<int>
#define VS vector<string>
#define PII pair<int,int>
#define PDD pair<double,double>
#define VPII vector< PII >
#define N 33
using namespace std;
const double pi=acos(-1);
const int d[8][2]={-1,0, 1,0, 0,-1, 0,1, -1,-1, -1,1, 1,-1, 1,1};
int num1[N*N],num2[N*N],map[N][N],End[N][N],bo[N][N];
int n,m,X,Y;
bool Rotate=0;
VPII ans;
void renum(int a[N][N],int num[]){
	rep(i,1,n)
		rep(j,1,m)num[a[i][j]]++;
	rep(i,1,900)num[i]+=num[i-1];
	rep(i,1,n)
		rep(j,1,m)a[i][j]=num[a[i][j]]--;
}
bool out(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	if(x<1 || x>n || y<1 || y>m)return 1;
	return 0;
}
void Move(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	swap(map[x][y],map[X][Y]);
	X=x; Y=y;
}
void Go(int tx,int ty){
	int tmpx=-1,tmpy=-1;
	for(;;){
		if(X==tx && Y==ty)break;
		int x,y,minn=1<<30,choose;
		rep(i,0,7){
			x=X+d[i][0];
			y=Y+d[i][1];
			if(out(i) || bo[x][y] || (x==tmpx && y==tmpy))continue;
			if(abs(x-tx)+abs(y-ty)<minn){
				minn=abs(x-tx)+abs(y-ty);
				choose=i;
			}
		}
		tmpx=X; tmpy=Y;
		Move(choose);
		ans.pb(mk(X,Y));
	}
}
void print(){
	printf("%d\n",ans.size()-1);
	for(PII tmp:ans)printf("%d %d\n",tmp.first,tmp.second);
	for(;;);
	exit(0);
}
void init(){
	scanf("%d%d",&n,&m);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&map[i][j]);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&End[i][j]);
	renum(map,num1);
	renum(End,num2);
	rep(i,1,900)if(num1[i]!=num2[i]){
		printf("-1\n");
		exit(0);
	}
}
void work1(){
	rep(i,1,m)
		rep(j,1,m)if(i!=j){
			X=1; Y=i;
			ans.clear();
			ans.pb(mk(1,i));
			Go(1,j);
			bool f=1;
			rep(k,1,m)if(map[1][k]!=End[1][k])f=0;
			if(f){
				if(Rotate)for(PII &tmp:ans)swap(tmp.first,tmp.second);
				print();
			}
			Go(1,i);
		}
	printf("-1\n");
	exit(0);
}
PII Find(int x){
	rep(i,1,n)
		rep(j,1,m)if(map[i][j]==x)return mk(i,j);
	puts("***");
}
void Push(int &x,int &y,int dir){
	int xx=x+d[dir][0],yy=y+d[dir][1];
	Go(xx,yy);
	Move(dir^1);
	ans.pb(mk(x,y));
	swap(bo[x][y],bo[xx][yy]);
	x=xx;
	y=yy;
}
void work2(){
	X=n; Y=m;
	ans.pb(mk(n,m));
	rep(i,1,n-2)
		rep(j,1,m){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(y<j)Push(x,y,3);
			while(y>j)Push(x,y,2);
			while(x>i)Push(x,y,0);
		}
	rep(j,1,m-2)
		rep(i,n-1,n){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(x<i)Push(x,y,1);
			while(x>i)Push(x,y,0);
			while(y>j)Push(x,y,2);
		}
	//
	srand(time(0));
	for(;;){
		bool f=1;
		rep(i,n-1,n)
			rep(j,m-1,m)if(map[i][j]!=End[i][j])f=0;
		if(f)break;
		int dir=rand()%8;
		if(!out(dir))Move(dir),ans.pb(mk(X,Y));
	}
	print();
}
int main(){
	init();
	if(m==1){
		Rotate=1;
		rep(i,1,n)map[1][i]=map[i][1],End[1][i]=End[i][1];
		swap(n,m);
	}
	if(n==1)work1();
	else work2();
}


#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
#include<cmath>
#include<vector>
#define int64 long long
#define mk make_pair
#define pb push_back
#define sqr(x) (x)*(x)
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define VI vector<int>
#define VS vector<string>
#define PII pair<int,int>
#define PDD pair<double,double>
#define VPII vector< PII >
#define N 33
using namespace std;
const double pi=acos(-1);
const int d[8][2]={-1,0, 1,0, 0,-1, 0,1, -1,-1, -1,1, 1,-1, 1,1};
int num1[N*N],num2[N*N],map[N][N],End[N][N],bo[N][N];
int n,m,X,Y;
bool Rotate=0;
VPII ans;
void renum(int a[N][N],int num[]){
	rep(i,1,n)
		rep(j,1,m)num[a[i][j]]++;
	rep(i,1,900)num[i]+=num[i-1];
	rep(i,1,n)
		rep(j,1,m)a[i][j]=num[a[i][j]]--;
}
bool out(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	if(x<1 || x>n || y<1 || y>m)return 1;
	return 0;
}
void Move(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	swap(map[x][y],map[X][Y]);
	X=x; Y=y;
}
void Go(int tx,int ty){
	int tmpx=-1,tmpy=-1;
	for(;;){
		if(X==tx && Y==ty)break;
		int x,y,minn=1<<30,choose;
		rep(i,0,7){
			x=X+d[i][0];
			y=Y+d[i][1];
			if(out(i) || bo[x][y] || (x==tmpx && y==tmpy))continue;
			if(abs(x-tx)+abs(y-ty)<minn){
				minn=abs(x-tx)+abs(y-ty);
				choose=i;
			}
		}
		tmpx=X; tmpy=Y;
		Move(choose);
		ans.pb(mk(X,Y));
	}
}
void print(){
	printf("%d\n",ans.size()-1);
	for(PII tmp:ans)printf("%d %d\n",tmp.first,tmp.second);
	exit(0);
}
void init(){
	scanf("%d%d",&n,&m);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&map[i][j]);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&End[i][j]);
	renum(map,num1);
	renum(End,num2);
	rep(i,1,900)if(num1[i]!=num2[i]){
		printf("-1\n");
		exit(0);
	}
}
void work1(){
	rep(i,1,m)
		rep(j,1,m)if(i!=j){
			X=1; Y=i;
			ans.clear();
			ans.pb(mk(1,i));
			Go(1,j);
			bool f=1;
			rep(k,1,m)if(map[1][k]!=End[1][k])f=0;
			if(f){
				if(Rotate)for(PII &tmp:ans)swap(tmp.first,tmp.second);
				print();
			}
			Go(1,i);
		}
	printf("-1\n");
	exit(0);
}
PII Find(int x){
	rep(i,1,n)
		rep(j,1,m)if(map[i][j]==x)return mk(i,j);
	puts("***");
}
void Push(int &x,int &y,int dir){
	int xx=x+d[dir][0],yy=y+d[dir][1];
	Go(xx,yy);
	Move(dir^1);
	ans.pb(mk(x,y));
	swap(bo[x][y],bo[xx][yy]);
	x=xx;
	y=yy;
}
void work2(){
	PII St=Find(End[n][m]);
	X=St.first;
	Y=St.second;
	ans.pb(mk(X,Y));
	rep(i,1,n-2)
		rep(j,1,m){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(y<j)Push(x,y,3);
			while(y>j)Push(x,y,2);
			while(x>i)Push(x,y,0);
		}
	rep(j,1,m-2)
		rep(i,n-1,n){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(x<i)Push(x,y,1);
			while(x>i)Push(x,y,0);
			while(y>j)Push(x,y,2);
		}
	//wei
	srand(time(0));
	for(;;){
		bool f=1;
		rep(i,n-1,n)
			rep(j,m-1,m)if(map[i][j]!=End[i][j])f=0;
		if(f)break;
		int dir=rand()%8;
		int x=X+d[dir][0],y=Y+d[dir][1];
		if((x==n-1 || x==n) && (y==m-1 || y==m))Move(dir),ans.pb(mk(X,Y));
	}
	print();
}
int main(){
	init();
	if(m==1){
		Rotate=1;
		rep(i,1,n)map[1][i]=map[i][1],End[1][i]=End[i][1];
		swap(n,m);
	}
	if(n==1)work1();
	else work2();
}


#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
#include<cmath>
#include<vector>
#define int64 long long
#define mk make_pair
#define pb push_back
#define sqr(x) (x)*(x)
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define VI vector<int>
#define VS vector<string>
#define PII pair<int,int>
#define PDD pair<double,double>
#define VPII vector< PII >
#define N 33
using namespace std;
const double pi=acos(-1);
const int d[8][2]={-1,0, 1,0, 0,-1, 0,1, -1,-1, -1,1, 1,-1, 1,1};
int num1[N*N],num2[N*N],map[N][N],End[N][N],bo[N][N];
int n,m,X,Y;
bool Rotate=0;
VPII ans;
void renum(int a[N][N],int num[]){
	rep(i,1,n)
		rep(j,1,m)num[a[i][j]]++;
	rep(i,1,900)num[i]+=num[i-1];
	rep(i,1,n)
		rep(j,1,m)a[i][j]=num[a[i][j]]--;
}
bool out(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	if(x<1 || x>n || y<1 || y>m)return 1;
	return 0;
}
void Move(int dir){
	int x=X+d[dir][0],y=Y+d[dir][1];
	swap(map[x][y],map[X][Y]);
	X=x; Y=y;
}
void Go(int tx,int ty){
	int tmpx=-1,tmpy=-1;
	for(;;){
		if(X==tx && Y==ty)break;
		int x,y,minn=1<<30,choose;
		rep(i,0,7){
			x=X+d[i][0];
			y=Y+d[i][1];
			if(out(i) || bo[x][y] || (x==tmpx && y==tmpy))continue;
			if(abs(x-tx)+abs(y-ty)<minn){
				minn=abs(x-tx)+abs(y-ty);
				choose=i;
			}
		}
		tmpx=X; tmpy=Y;
		Move(choose);
		ans.pb(mk(X,Y));
	}
}
void print(){
	printf("%d\n",ans.size()-1);
	for(PII tmp:ans)printf("%d %d\n",tmp.first,tmp.second);
	exit(0);
}
void init(){
	scanf("%d%d",&n,&m);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&map[i][j]);
	rep(i,1,n)
		rep(j,1,m)scanf("%d",&End[i][j]);
	renum(map,num1);
	renum(End,num2);
	rep(i,1,900)if(num1[i]!=num2[i]){
		printf("-1\n");
		exit(0);
	}
}
void work1(){
	rep(i,1,m)
		rep(j,1,m)if(i!=j){
			X=1; Y=i;
			ans.clear();
			ans.pb(mk(1,i));
			Go(1,j);
			bool f=1;
			rep(k,1,m)if(map[1][k]!=End[1][k])f=0;
			if(f){
				if(Rotate)for(PII &tmp:ans)swap(tmp.first,tmp.second);
				print();
			}
			Go(1,i);
		}
	printf("-1\n");
	exit(0);
}
PII Find(int x){
	rep(i,1,n)
		rep(j,1,m)if(map[i][j]==x)return mk(i,j);
	puts("***");
}
void Push(int &x,int &y,int dir){
	int xx=x+d[dir][0],yy=y+d[dir][1];
	Go(xx,yy);
	Move(dir^1);
	ans.pb(mk(x,y));
	swap(bo[x][y],bo[xx][yy]);
	x=xx;
	y=yy;
}
void work2(){
	X=n; Y=m;
	ans.pb(mk(n,m));
	rep(i,1,n-2)
		rep(j,1,m){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(y<j)Push(x,y,3);
			while(y>j)Push(x,y,2);
			while(x>i)Push(x,y,0);
		}
	rep(j,1,m-2)
		rep(i,n-1,n){
			PII tmp=Find(End[i][j]);
			int x=tmp.first,y=tmp.second;
			bo[x][y]=1;
			while(x<i)Push(x,y,1);
			while(x>i)Push(x,y,0);
			while(y>j)Push(x,y,2);
		}
	//wei
	srand(time(0));
	for(;;){
		bool f=1;
		rep(i,n-1,n)
			rep(j,m-1,m)if(map[i][j]!=End[i][j])f=0;
		if(f)break;
		int dir=rand()%8;
		if(!out(dir))Move(dir),ans.pb(mk(X,Y));
	}
	print();
}
int main(){
	init();
	if(m==1){
		Rotate=1;
		rep(i,1,n)map[1][i]=map[i][1],End[1][i]=End[i][1];
		swap(n,m);
	}
	if(n==1)work1();
	else work2();
}


import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Egor Kulikov (egor@egork.net)
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
	int sx, sy;
	int[][] start;
	List<IntPair> answer;

    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int rowCount = in.readInt();
		int columnCount = in.readInt();
		start = IOUtils.readIntTable(in, rowCount, columnCount);
		int[][] target = IOUtils.readIntTable(in, rowCount, columnCount);
		if (rowCount == 1) {
			int from = 0;
			int to = columnCount - 1;
			while (start[0][from] == target[0][from]) {
				from++;
			}
			while (start[0][to] == target[0][to]) {
				to--;
			}
			if (start[0][from] == target[0][to]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[0][j + 1] != target[0][j]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = from; j <= to; j++) {
						out.printLine(1, j + 1);
					}
					return;
				}
			}
			if (start[0][to] == target[0][from]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[0][j] != target[0][j + 1]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = to; j >= from; j--) {
						out.printLine(1, j + 1);
					}
					return;
				}
			}
			out.printLine(-1);
			return;
		}
		if (columnCount == 1) {
			int from = 0;
			int to = rowCount - 1;
			while (start[from][0] == target[from][0]) {
				from++;
			}
			while (start[to][0] == target[to][0]) {
				to--;
			}
			if (start[from][0] == target[to][0]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[j + 1][0] != target[j][0]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = from; j <= to; j++) {
						out.printLine(j + 1, 1);
					}
					return;
				}
			}
			if (start[to][0] == target[from][0]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[j][0] != target[j + 1][0]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = to; j >= from; j--) {
						out.printLine(j + 1, 1);
					}
					return;
				}
			}
			out.printLine(-1);
			return;
		}
		sx = -1;
		sy = -1;
		answer = new ArrayList<>();
		for (int i = 0; i < rowCount && sx == -1; i++) {
			for (int j = 0; j < columnCount; j++) {
				if (start[i][j] == target[0][0]) {
					sx = i;
					sy = j;
					break;
				}
			}
		}
		if (sx == -1) {
			out.printLine(-1);
			return;
		}
		answer.add(new IntPair(sx, sy));
		for (int i = rowCount - 1; i >= 2; i--) {
			for (int j = columnCount - 1; j >= 0; j--) {
				int cx = -1;
				int cy = -1;
				for (int k = 0; k < i && cx == -1; k++) {
					for (int l = 0; l < columnCount; l++) {
						if (start[k][l] == target[i][j] && (k != sx || l != sy)) {
							cx = k;
							cy = l;
							break;
						}
					}
				}
				if (cx == -1) {
					for (int k = 0; k <= j; k++) {
						if (start[i][k] == target[i][j] && (i != sx || k != sy)) {
							cx = i;
							cy = k;
							break;
						}
					}
					if (cx == -1) {
						out.printLine(-1);
						return;
					}
				}
				if (cx == i && cy == j) {
					continue;
				}
				if (cy != 0) {
					if (cx == sx) {
						if (sx == 0) {
							go(sx + 1, sy);
						} else {
							go(sx - 1, sy);
						}
					}
					for (int k = sy - 1; k >= 0; k--) {
						go(sx, k);
					}
					for (int k = sx + 1; k <= cx; k++) {
						go(k, sy);
					}
					for (int k = sx - 1; k >= cx; k--) {
						go(k, sy);
					}
					for (int k = 1; k <= cy; k++) {
						go(sx, k);
					}
					cy--;
					while (cy > 0) {
						if (sx == 0) {
							go(sx + 1, sy - 1);
							go(sx - 1, sy - 1);
							go(sx, sy + 1);
						} else {
							go(sx - 1, sy - 1);
							go(sx + 1, sy - 1);
							go(sx, sy + 1);
						}
						cy--;
					}
				} else {
					while (sy > 1) {
						go(sx, sy - 1);
					}
					if (sy == 0) {
						go(sx, sy + 1);
					}
					while (sx < cx) {
						go(sx + 1, cx);
					}
					while (sx > cx) {
						go(sx - 1, cx);
					}
				}
				if (cx < i) {
					go(sx + 1, sy - 1);
					go(sx - 1, sy);
					cx++;
					while (cx < i) {
						go(sx + 1, sy + 1);
						go(sx + 1, sy - 1);
						go(sx - 1, sy);
						cx++;
					}
				} else {
					go(sx - 1, sy - 1);
				}
				if (cy < j) {
					go(sx + 1, sy + 1);
					go(sx, sy - 1);
					cy++;
					while (cy < j) {
						go(sx - 1, sy + 1);
						go(sx + 1, sy + 1);
						go(sx, sy - 1);
						cy++;
					}
				}
			}
		}
		for (int i = columnCount - 1; i >= 2; i--) {
			for (int j = 1; j >= 0; j--) {
				int cx = -1;
				int cy = -1;
				for (int k = 0; k < i && cx == -1; k++) {
					for (int l = 0; l < 2; l++) {
						if (start[l][k] == target[j][i] && (l != sx || k != sy)) {
							cx = l;
							cy = k;
						}
					}
				}
				if (cx == -1) {
					for (int k = 0; k <= j; k++) {
						if (start[k][i] == target[j][i] && (k != sx || i != sy)) {
							cx = k;
							cy = i;
						}
					}
					if (cx == -1) {
						out.printLine(-1);
						return;
					}
				}
				if (cx == j && cy == i) {
					continue;
				}
				while (cx > sx + 1) {
					go(sx + 1, sy);
				}
				while (cx < sx - 1) {
					go(sx - 1, sy);
				}
				go(cx ^ 1, cy);
				if (cx != j) {
					go(cx, cy);
					cx ^= 1;
				}
				if (cy < i) {
					go(cx, cy + 1);
					go(cx, cy);
					cy++;
					while (cy < i) {
						go(sx ^ 1, sy + 1);
						go(sx ^ 1, sy + 1);
						go(sx, sy - 1);
						cy++;
					}
				}
			}
		}
		if (sx != 0 || sy != 0) {
			go(0, 0);
		}
		if (start[1][1] != target[1][1]) {
			if (start[0][1] == target[1][1]) {
				go(0, 1);
				go(1, 1);
				go(0, 0);
			} else if (start[1][0] == target[1][1]) {
				go(1, 0);
				go(1, 1);
				go(0, 0);
			} else {
				out.printLine(-1);
				return;
			}
		}
		if (start[0][1] != target[0][1]) {
			if (start[1][0] == target[0][1]) {
				go(1, 0);
				go(0, 1);
				go(0, 0);
			} else {
				out.printLine(-1);
				return;
			}
		}
		if (start[1][0] != target[1][0]) {
			out.printLine(-1);
			return;
		}
		out.printLine(answer.size() - 1);
		for (IntPair pair : answer) {
			out.printLine(pair.first + 1, pair.second + 1);
		}
    }

	private void go(int nx, int ny) {
		int temp = start[sx][sy];
		start[sx][sy] = start[nx][ny];
		start[nx][ny] = temp;
		sx = nx;
		sy = ny;
		answer.add(new IntPair(nx, ny));
	}
}

class IntPair implements Comparable<IntPair> {
	public final int first, second;

	public IntPair(int first, int second) {
		this.first = first;
		this.second = second;
	}

	public String toString() {
		return "(" + first + "," + second + ")";
	}

	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		IntPair intPair = (IntPair) o;

		return first == intPair.first && second == intPair.second;

	}

	public int hashCode() {
		int result = first;
		result = 31 * result + second;
		return result;
	}

	public int compareTo(IntPair o) {
		if (first < o.first)
			return -1;
		if (first > o.first)
			return 1;
		if (second < o.second)
			return -1;
		if (second > o.second)
			return 1;
		return 0;
	}
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void print(Object...objects) {
		for (int i = 0; i < objects.length; i++) {
			if (i != 0)
				writer.print(' ');
			writer.print(objects[i]);
		}
	}

	public void printLine(Object...objects) {
		print(objects);
		writer.println();
	}

	public void close() {
		writer.close();
	}

	public void printLine(int i) {
		writer.println(i);
	}
}

class IOUtils {

	public static int[] readIntArray(InputReader in, int size) {
		int[] array = new int[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readInt();
		return array;
	}

	public static int[][] readIntTable(InputReader in, int rowCount, int columnCount) {
		int[][] table = new int[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readIntArray(in, columnCount);
		return table;
	}

}


import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Egor Kulikov (egor@egork.net)
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
	int sx, sy;
	int[][] start;
	List<IntPair> answer;

    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int rowCount = in.readInt();
		int columnCount = in.readInt();
		start = IOUtils.readIntTable(in, rowCount, columnCount);
		int[][] target = IOUtils.readIntTable(in, rowCount, columnCount);
		if (rowCount == 1) {
			int from = 0;
			int to = columnCount - 1;
			while (start[0][from] == target[0][from]) {
				from++;
			}
			while (start[0][to] == target[0][to]) {
				to--;
			}
			if (start[0][from] == target[0][to]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[0][j + 1] != target[0][j]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = from; j <= to; j++) {
						out.printLine(1, j + 1);
					}
					return;
				}
			}
			if (start[0][to] == target[0][from]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[0][j] != target[0][j + 1]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = to; j >= from; j--) {
						out.printLine(1, j + 1);
					}
					return;
				}
			}
			out.printLine(-1);
			return;
		}
		if (columnCount == 1) {
			int from = 0;
			int to = rowCount - 1;
			while (start[from][0] == target[from][0]) {
				from++;
			}
			while (start[to][0] == target[to][0]) {
				to--;
			}
			if (start[from][0] == target[to][0]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[j + 1][0] != target[j][0]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = from; j <= to; j++) {
						out.printLine(j + 1, 1);
					}
					return;
				}
			}
			if (start[to][0] == target[from][0]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[j][0] != target[j + 1][0]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = to; j >= from; j--) {
						out.printLine(j + 1, 1);
					}
					return;
				}
			}
			out.printLine(-1);
			return;
		}
		sx = -1;
		sy = -1;
		answer = new ArrayList<>();
		for (int i = 0; i < rowCount && sx == -1; i++) {
			for (int j = 0; j < columnCount; j++) {
				if (start[i][j] == target[0][0]) {
					sx = i;
					sy = j;
					break;
				}
			}
		}
		if (sx == -1) {
			out.printLine(-1);
			return;
		}
		answer.add(new IntPair(sx, sy));
		for (int i = rowCount - 1; i >= 2; i--) {
			for (int j = columnCount - 1; j >= 0; j--) {
				int cx = -1;
				int cy = -1;
				for (int k = 0; k < i && cx == -1; k++) {
					for (int l = 0; l < columnCount; l++) {
						if (start[k][l] == target[i][j] && (k != sx || l != sy)) {
							cx = k;
							cy = l;
							break;
						}
					}
				}
				if (cx == -1) {
					for (int k = 0; k <= j; k++) {
						if (start[i][k] == target[i][j] && (i != sx || k != sy)) {
							cx = i;
							cy = k;
							break;
						}
					}
					if (cx == -1) {
						out.printLine(-1);
						return;
					}
				}
				if (cx == i && cy == j) {
					continue;
				}
				if (cy != 0) {
					if (cx == sx) {
						if (sx == 0) {
							go(sx + 1, sy);
						} else {
							go(sx - 1, sy);
						}
					}
					for (int k = sy - 1; k >= 0; k--) {
						go(sx, k);
					}
					for (int k = sx + 1; k <= cx; k++) {
						go(k, sy);
					}
					for (int k = sx - 1; k >= cx; k--) {
						go(k, sy);
					}
					for (int k = 1; k <= cy; k++) {
						go(sx, k);
					}
					cy--;
					while (cy > 0) {
						if (sx == 0) {
							go(sx + 1, sy - 1);
							go(sx - 1, sy - 1);
							go(sx, sy + 1);
						} else {
							go(sx - 1, sy - 1);
							go(sx + 1, sy - 1);
							go(sx, sy + 1);
						}
						cy--;
					}
				} else {
					while (sy > 1) {
						go(sx, sy - 1);
					}
					if (cx != sx && sy != 0) {
						go(sx, sy - 1);
					}
					while (sx + 1 < cx) {
						go(sx + 1, sy);
					}
					while (sx - 1 > cx) {
						go(sx - 1, sy);
					}
					if (sy == 0) {
						go(cx, 1);
					}
				}
				if (cx < i) {
					go(sx + 1, sy - 1);
					go(sx - 1, sy);
					cx++;
					while (cx < i) {
						go(sx + 1, sy + 1);
						go(sx + 1, sy - 1);
						go(sx - 1, sy);
						cx++;
					}
				} else {
					go(sx - 1, sy - 1);
				}
				if (cy < j) {
					go(sx + 1, sy + 1);
					go(sx, sy - 1);
					cy++;
					while (cy < j) {
						go(sx - 1, sy + 1);
						go(sx + 1, sy + 1);
						go(sx, sy - 1);
						cy++;
					}
				}
			}
		}
		for (int i = columnCount - 1; i >= 2; i--) {
			for (int j = 1; j >= 0; j--) {
				int cx = -1;
				int cy = -1;
				for (int k = 0; k < i && cx == -1; k++) {
					for (int l = 0; l < 2; l++) {
						if (start[l][k] == target[j][i] && (l != sx || k != sy)) {
							cx = l;
							cy = k;
						}
					}
				}
				if (cx == -1) {
					for (int k = 0; k <= j; k++) {
						if (start[k][i] == target[j][i] && (k != sx || i != sy)) {
							cx = k;
							cy = i;
						}
					}
					if (cx == -1) {
						out.printLine(-1);
						return;
					}
				}
				if (cx == j && cy == i) {
					continue;
				}
				while (cy - sy > 1) {
					go(sx, sy + 1);
				}
				while (sy - cy > 1) {
					go(sx, sy - 1);
				}
				if (sx != (cx ^ 1) || cy != sy) {
					go(cx ^ 1, cy);
				}
				if (cx != j) {
					go(cx, cy);
					cx ^= 1;
				}
				if (cy < i) {
					go(cx, cy + 1);
					go(cx, cy);
					cy++;
					while (cy < i) {
						go(sx ^ 1, sy + 1);
						go(sx ^ 1, sy + 1);
						go(sx, sy - 1);
						cy++;
					}
				}
			}
		}
		if (sx != 0 || sy != 0) {
			go(0, 0);
		}
		if (start[1][1] != target[1][1]) {
			if (start[0][1] == target[1][1]) {
				go(0, 1);
				go(1, 1);
				go(0, 0);
			} else if (start[1][0] == target[1][1]) {
				go(1, 0);
				go(1, 1);
				go(0, 0);
			} else {
				out.printLine(-1);
				return;
			}
		}
		if (start[0][1] != target[0][1]) {
			if (start[1][0] == target[0][1]) {
				go(1, 0);
				go(0, 1);
				go(0, 0);
			} else {
				out.printLine(-1);
				return;
			}
		}
		if (start[1][0] != target[1][0]) {
			out.printLine(-1);
			return;
		}
		out.printLine(answer.size() - 1);
		for (IntPair pair : answer) {
			out.printLine(pair.first + 1, pair.second + 1);
		}
    }

	private void go(int nx, int ny) {
		int temp = start[sx][sy];
		start[sx][sy] = start[nx][ny];
		start[nx][ny] = temp;
		sx = nx;
		sy = ny;
		answer.add(new IntPair(nx, ny));
	}
}

class IntPair implements Comparable<IntPair> {
	public final int first, second;

	public IntPair(int first, int second) {
		this.first = first;
		this.second = second;
	}

	public String toString() {
		return "(" + first + "," + second + ")";
	}

	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		IntPair intPair = (IntPair) o;

		return first == intPair.first && second == intPair.second;

	}

	public int hashCode() {
		int result = first;
		result = 31 * result + second;
		return result;
	}

	public int compareTo(IntPair o) {
		if (first < o.first)
			return -1;
		if (first > o.first)
			return 1;
		if (second < o.second)
			return -1;
		if (second > o.second)
			return 1;
		return 0;
	}
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void print(Object...objects) {
		for (int i = 0; i < objects.length; i++) {
			if (i != 0)
				writer.print(' ');
			writer.print(objects[i]);
		}
	}

	public void printLine(Object...objects) {
		print(objects);
		writer.println();
	}

	public void close() {
		writer.close();
	}

	public void printLine(int i) {
		writer.println(i);
	}
}

class IOUtils {

	public static int[] readIntArray(InputReader in, int size) {
		int[] array = new int[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readInt();
		return array;
	}

	public static int[][] readIntTable(InputReader in, int rowCount, int columnCount) {
		int[][] table = new int[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readIntArray(in, columnCount);
		return table;
	}

}


import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Egor Kulikov (egor@egork.net)
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
	int sx, sy;
	int[][] start;
	List<IntPair> answer;

    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int rowCount = in.readInt();
		int columnCount = in.readInt();
		start = IOUtils.readIntTable(in, rowCount, columnCount);
		int[][] target = IOUtils.readIntTable(in, rowCount, columnCount);
		if (rowCount == 1) {
			int from = 0;
			int to = columnCount - 1;
			while (start[0][from] == target[0][from]) {
				from++;
			}
			while (start[0][to] == target[0][to]) {
				to--;
			}
			if (start[0][from] == target[0][to]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[0][j + 1] != target[0][j]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = from; j <= to; j++) {
						out.printLine(1, j + 1);
					}
					return;
				}
			}
			if (start[0][to] == target[0][from]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[0][j] != target[0][j + 1]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = to; j >= from; j--) {
						out.printLine(1, j + 1);
					}
					return;
				}
			}
			out.printLine(-1);
			return;
		}
		if (columnCount == 1) {
			int from = 0;
			int to = rowCount - 1;
			while (start[from][0] == target[from][0]) {
				from++;
			}
			while (start[to][0] == target[to][0]) {
				to--;
			}
			if (start[from][0] == target[to][0]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[j + 1][0] != target[j][0]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = from; j <= to; j++) {
						out.printLine(j + 1, 1);
					}
					return;
				}
			}
			if (start[to][0] == target[from][0]) {
				boolean good = true;
				for (int j = from; j < to; j++) {
					if (start[j][0] != target[j + 1][0]) {
						good = false;
						break;
					}
				}
				if (good) {
					out.printLine(to - from);
					for (int j = to; j >= from; j--) {
						out.printLine(j + 1, 1);
					}
					return;
				}
			}
			out.printLine(-1);
			return;
		}
		sx = -1;
		sy = -1;
		answer = new ArrayList<>();
		for (int i = 0; i < rowCount && sx == -1; i++) {
			for (int j = 0; j < columnCount; j++) {
				if (start[i][j] == target[0][0]) {
					sx = i;
					sy = j;
					break;
				}
			}
		}
		if (sx == -1) {
			out.printLine(-1);
			return;
		}
		answer.add(new IntPair(sx, sy));
		for (int i = rowCount - 1; i >= 2; i--) {
			for (int j = columnCount - 1; j >= 0; j--) {
				int cx = -1;
				int cy = -1;
				for (int k = 0; k < i && cx == -1; k++) {
					for (int l = 0; l < columnCount; l++) {
						if (start[k][l] == target[i][j] && (k != sx || l != sy)) {
							cx = k;
							cy = l;
							break;
						}
					}
				}
				if (cx == -1) {
					for (int k = 0; k <= j; k++) {
						if (start[i][k] == target[i][j] && (i != sx || k != sy)) {
							cx = i;
							cy = k;
							break;
						}
					}
					if (cx == -1) {
						out.printLine(-1);
						return;
					}
				}
				if (cx == i && cy == j) {
					continue;
				}
				if (cy != 0) {
					if (cx == sx) {
						if (sx == 0) {
							go(sx + 1, sy);
						} else {
							go(sx - 1, sy);
						}
					}
					for (int k = sy - 1; k >= 0; k--) {
						go(sx, k);
					}
					for (int k = sx + 1; k <= cx; k++) {
						go(k, sy);
					}
					for (int k = sx - 1; k >= cx; k--) {
						go(k, sy);
					}
					for (int k = 1; k <= cy; k++) {
						go(sx, k);
					}
					cy--;
					while (cy > 0) {
						if (sx == 0) {
							go(sx + 1, sy - 1);
							go(sx - 1, sy - 1);
							go(sx, sy + 1);
						} else {
							go(sx - 1, sy - 1);
							go(sx + 1, sy - 1);
							go(sx, sy + 1);
						}
						cy--;
					}
				} else {
					while (sy > 1) {
						go(sx, sy - 1);
					}
					if (cx != sx && sy != 0) {
						go(sx, sy - 1);
					}
					while (sx + 1 < cx) {
						go(sx + 1, sy);
					}
					while (sx - 1 > cx) {
						go(sx - 1, sy);
					}
					if (sy == 0) {
						go(cx, 1);
					}
				}
				if (cx < i) {
					go(sx + 1, sy - 1);
					go(sx - 1, sy);
					cx++;
					while (cx < i) {
						go(sx + 1, sy + 1);
						go(sx + 1, sy - 1);
						go(sx - 1, sy);
						cx++;
					}
				} else {
					go(sx - 1, sy - 1);
				}
				if (cy < j) {
					go(sx + 1, sy + 1);
					go(sx, sy - 1);
					cy++;
					while (cy < j) {
						go(sx - 1, sy + 1);
						go(sx + 1, sy + 1);
						go(sx, sy - 1);
						cy++;
					}
				}
			}
		}
		for (int i = columnCount - 1; i >= 2; i--) {
			for (int j = 1; j >= 0; j--) {
				int cx = -1;
				int cy = -1;
				for (int k = 0; k < i && cx == -1; k++) {
					for (int l = 0; l < 2; l++) {
						if (start[l][k] == target[j][i] && (l != sx || k != sy)) {
							cx = l;
							cy = k;
						}
					}
				}
				if (cx == -1) {
					for (int k = 0; k <= j; k++) {
						if (start[k][i] == target[j][i] && (k != sx || i != sy)) {
							cx = k;
							cy = i;
						}
					}
					if (cx == -1) {
						out.printLine(-1);
						return;
					}
				}
				if (cx == j && cy == i) {
					continue;
				}
				while (cy - sy > 1) {
					go(sx, sy + 1);
				}
				while (sy - cy > 1) {
					go(sx, sy - 1);
				}
				go(cx ^ 1, cy);
				if (cx != j) {
					go(cx, cy);
					cx ^= 1;
				}
				if (cy < i) {
					go(cx, cy + 1);
					go(cx, cy);
					cy++;
					while (cy < i) {
						go(sx ^ 1, sy + 1);
						go(sx ^ 1, sy + 1);
						go(sx, sy - 1);
						cy++;
					}
				}
			}
		}
		if (sx != 0 || sy != 0) {
			go(0, 0);
		}
		if (start[1][1] != target[1][1]) {
			if (start[0][1] == target[1][1]) {
				go(0, 1);
				go(1, 1);
				go(0, 0);
			} else if (start[1][0] == target[1][1]) {
				go(1, 0);
				go(1, 1);
				go(0, 0);
			} else {
				out.printLine(-1);
				return;
			}
		}
		if (start[0][1] != target[0][1]) {
			if (start[1][0] == target[0][1]) {
				go(1, 0);
				go(0, 1);
				go(0, 0);
			} else {
				out.printLine(-1);
				return;
			}
		}
		if (start[1][0] != target[1][0]) {
			out.printLine(-1);
			return;
		}
		out.printLine(answer.size() - 1);
		for (IntPair pair : answer) {
			out.printLine(pair.first + 1, pair.second + 1);
		}
    }

	private void go(int nx, int ny) {
		int temp = start[sx][sy];
		start[sx][sy] = start[nx][ny];
		start[nx][ny] = temp;
		sx = nx;
		sy = ny;
		answer.add(new IntPair(nx, ny));
	}
}

class IntPair implements Comparable<IntPair> {
	public final int first, second;

	public IntPair(int first, int second) {
		this.first = first;
		this.second = second;
	}

	public String toString() {
		return "(" + first + "," + second + ")";
	}

	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		IntPair intPair = (IntPair) o;

		return first == intPair.first && second == intPair.second;

	}

	public int hashCode() {
		int result = first;
		result = 31 * result + second;
		return result;
	}

	public int compareTo(IntPair o) {
		if (first < o.first)
			return -1;
		if (first > o.first)
			return 1;
		if (second < o.second)
			return -1;
		if (second > o.second)
			return 1;
		return 0;
	}
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void print(Object...objects) {
		for (int i = 0; i < objects.length; i++) {
			if (i != 0)
				writer.print(' ');
			writer.print(objects[i]);
		}
	}

	public void printLine(Object...objects) {
		print(objects);
		writer.println();
	}

	public void close() {
		writer.close();
	}

	public void printLine(int i) {
		writer.println(i);
	}
}

class IOUtils {

	public static int[] readIntArray(InputReader in, int size) {
		int[] array = new int[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readInt();
		return array;
	}

	public static int[][] readIntTable(InputReader in, int rowCount, int columnCount) {
		int[][] table = new int[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readIntArray(in, columnCount);
		return table;
	}

}