import std.stdio, std.conv, std.array, std.string, std.container, std.algorithm, std.container.util, std.traits, std.range;

struct Point {
  ulong y;
  ulong x;
  this( ulong y, ulong x ) {
	this.y = y;
	this.x = x;
  }
}

immutable Point NONE = Point( -1, -1 );

immutable int EMPTY = 0;
immutable int BLOCK = 1;
immutable int START = 2;
immutable int GOAL = 3;
immutable int WALL = 4;

struct State {
  Point s;
  Point[ 10 ] remove;
  ulong noPoint;
  int turn;
  
  this( Point s ){
	this.s = s;
	foreach ( i; 0 .. 10 ) {
	  remove[ i ] = NONE;
	}
	noPoint = 0;
	turn = 0;
  }
  void apply( int[][] table, Point origStart ) {
	table[ origStart.y ][ origStart.x ] = EMPTY;
	table[ s.y ][ s.x ] = START;
	foreach ( i; 0 .. noPoint ) {
	  table[ remove[ i ].y ][ remove[ i ].x ] = EMPTY;
	}
  }

  void put( Point p ) {
	remove[ noPoint++ ] = p;
  }
}

Point findStart( int[][] table ) {
  foreach ( i, ary; table ) {
	foreach ( j, v; ary ) {
	  if ( v == START ) {
		return Point( i, j );
	  }
	}
  }
  return NONE;
}

Point findGoal( int[][] table ) {
  foreach ( i, ary; table ) {
	foreach ( j, v; ary ) {
	  if ( v == GOAL ) {
		return Point( i, j );
	  }
	}
  }
  return NONE;
}

void main()
{
  while ( true ) {
	auto token = split( strip( readln ) );
	int width = to!int( token[ 0 ] );
	int height = to!int( token[ 1 ] );
	if ( width == 0 && height == 0 ) break;

	int[][] table = new int[][]( height + 2, width + 2 );
	foreach ( ary; table ) {
	  ary[] = WALL;
	}
	foreach ( i; 1 .. height + 1 ) {
	  auto line = split( strip( readln ) );
	  foreach ( j; 1 .. width + 1 ) {
		table[ i ][ j ] = to!int( line[ j - 1 ] );
	  }
	}
	writeln( solve( table ) );
  }
}

int solve ( int[][] table ) {
  immutable Point start = findStart( table );
  immutable Point goal = findGoal( table );
  auto queue = SList!State( State( start ) );

  long[ 4 ] dx = [ -1, 0, 1, 0 ];
  long[ 4 ] dy = [ 0, 1, 0, -1 ];

  immutable ulong height = table.length;
  immutable ulong width = table[ 0 ].length;
  int[][] table2 = new int[][]( height, width );

  while ( !queue.empty ) {
	// stderr.writeln( walkLength( queue[] ) );
	auto s = queue.front;
	queue.removeFront;
	if ( s.turn == 11 ) break;
	
	if ( s.s == goal ) {
	  return s.turn;
	} else {
	  foreach ( i; 0 .. height ) {
		table2[ i ][] = table[ i ][];
	  }
	  foreach ( i; 0 .. 4 ) {
		s.apply( table2, start );
		auto nx = s.s.x + dx[ i ];
		auto ny = s.s.y + dy[ i ];
		if ( table2[ ny ][ nx ] != WALL && table2[ ny ][ nx ] != BLOCK ) {
		  while ( table2[ ny ][ nx ] != WALL && table2[ ny ][ nx ] != BLOCK ) {
			ny += dy[ i ];
			nx += dx[ i ];
		  }
		  auto ns = s;
		  if ( table2[ ny ][ nx ] == BLOCK ) {
			ns.put( Point( ny, nx ) );
		  }
		  ns.turn++;
		  ns.s = Point( ny - dy[ i ], nx - dx[ i ] );
		  queue = queue ~ ns;
		}
	  }
	}	
  }
  return -1;
}