#include<iostream>
#include<algorithm>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)

const int N = 9;
const int inf = (1 <<21);

int dx[]={0,1, 0,-1};
int dy[]={1,0,-1,0};
int op[]={2,3, 0,1};
int m[N][N];
bool vis2[N][N];

bool isok(int r,int c,int y,int x,int last){
  rep(i,4){
    if (op[i] == last)continue;
    int nex=x+dx[i],ney=y+dy[i];
    if (nex==-1||ney==-1||nex==c||ney==r)continue;
    if (vis2[ney][nex])return false;
  }
  return true;
}

int ans;
bool isgoal;
int md;
bool bfs(int r,int c,int cnt,bool goal2){
  static int q[N*N];
  static int cost[N][N];
  int sy3=-1,sx3=-1,gy3=-1,gx3=-1;
  rep(i,r){
    rep(j,c){
      if (m[i][j] == 3){
	if (sy3==-1)sy3=i,sx3=j;
	else gy3=i,gx3=j;
      }
      cost[i][j]=inf;
    }
  }
  int tail=0,head=0;
  q[tail++]=sx3+sy3*c;
  cost[sy3][sx3]=0;
  while(head != tail){
    int now = q[head++];
    int x = now%c,y=now/c;
    if (cnt+cost[y][x] >= ans)return false;
    if (x == gx3 && y == gy3){
      if (goal2)return true;
      isgoal=true;
      ans =min(ans,cnt+cost[y][x]);
      return true;
    }
    rep(i,4){
      int nex=x+dx[i],ney=y+dy[i];
      if (nex==-1||ney==-1||nex==c||ney==r||vis2[ney][nex])continue;
      if (m[ney][nex]==1||m[ney][nex] == 2)continue;
      if (cost[ney][nex] != inf)continue;
      cost[ney][nex]=cost[y][x]+1;
      q[tail++]=ney*c+nex;
    }
  }
  return false;
}

int path[N*N];
int pattern[8][4]={
  {2,1,1,0,},
  {1,0,0,3,},
  {0,3,3,2,},
  {3,2,2,1,},
  {2,3,3,0,},
  {1,2,2,3,},
  {0,1,1,2,},
  {3,0,0,1,},
};

int cx[]={-1, 0,1, 0, 1, 0,-1, 0};
int cy[]={ 0,-1,0, 1, 0, 1, 0,-1};

bool isok2(int r,int c,int y,int x,int p){
  if (p <4)return true;
  rep(i,8){
    bool ismatch=true;
    rep(j,4){
      if (pattern[i][j] == path[p-(4-j)]);
      else ismatch=false;
    }
    if (!ismatch)continue;
    int nex=x+cx[i],ney=y+cy[i];
    if (nex==-1||ney==-1||nex==c||ney==r)continue;
    if (m[ney][nex] == 0 && !vis2[ney][nex])return false;

  }
  return true;
}

void dfs(int r,int c,int y,int x,int cnt,int last,int gy2,int gx2){
  if (!isok(r,c,y,x,last)){
    return;
  }
  if (!isok2(r,c,y,x,cnt))return;

  if (cnt+md >= ans)return;
  //  if (!bfs(r,c,cnt,true))return;

  if (x == gx2 && y == gy2){
    vis2[y][x]=true;
    bfs(r,c,cnt,false);
    vis2[y][x]=false;
    return;
  }

  vis2[y][x]=true;
  rep(i,4){
    if (op[i] == last)continue;
    int nex=x+dx[i],ney=y+dy[i];
    if (nex==-1||ney==-1||nex==c||ney==r||vis2[ney][nex])continue;
    if (m[ney][nex] == 3 || m[ney][nex] == 1)continue;
    path[cnt]=i;
    dfs(r,c,ney,nex,cnt+1,i,gy2,gx2);
  }
  vis2[y][x]=false;
}

int bfs2(int r,int c,int tar,int utar){
  static int q[N*N];
  static int cost[N][N];
  int sy3=-1,sx3=-1,gy3=-1,gx3=-1;
  rep(i,r){
    rep(j,c){
      if (m[i][j] == tar){
	if (sy3==-1)sy3=i,sx3=j;
	else gy3=i,gx3=j;
      }
      cost[i][j]=inf;
    }
  }
  int tail=0,head=0;
  q[tail++]=sx3+sy3*c;
  cost[sy3][sx3]=0;
  while(head != tail){
    int now = q[head++];
    int x = now%c,y=now/c;
    if (x == gx3 && y == gy3){
      return cost[y][x];
    }
    rep(i,4){
      int nex=x+dx[i],ney=y+dy[i];
      if (nex==-1||ney==-1||nex==c||ney==r||vis2[ney][nex])continue;
      if (m[ney][nex]==1||m[ney][nex] == utar)continue;
      if (cost[ney][nex] != inf)continue;
      cost[ney][nex]=cost[y][x]+1;
      q[tail++]=ney*c+nex;
    }
  }
  return false;
}

main(){
  int r,c;
  while(cin>>r>>c && r){
    ans = r*c;
    isgoal=false;
    rep(i,r)rep(j,c)cin>>m[i][j];
    rep(i,r)rep(j,c)vis2[i][j]=false;
   
    int sx2=-1,sy2=-1;
    int gx2=-1,gy2=-1;
    rep(i,r){
      rep(j,c){
	if (m[i][j] == 2){
	  if (sx2 == -1)sx2=j,sy2=i;
	  else gx2=j,gy2=i;
	}
      }
    }
    
    int sx3=-1,sy3=-1,gx3=-1,gy3=-1;
    rep(i,r){
      rep(j,c){
	if (m[i][j] == 3){
	  if (sx3 == -1)sx3=j,sy3=i;
	  else gx3=j,gy3=i;
	}
      }
    }

    md=bfs2(r,c,3,2);
    
    dfs(r,c,sy2,sx2,0,-1,gy2,gx2);
    
    if (isgoal)cout << ans << endl;
    else cout << 0 << endl;
  }
  return false;
}

Measured memory_bytes: 868