#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

class Cell {
	int type;

	Cell(int type) : type(type) {}

public:
	bool is_normal() {
		return type == 0;
	}

	bool is_block() {
		return type >= 2;
	}

	bool is_goal() {
		return type == 1;
	}

	int block_id() {
		return type - 2;
	}

	static Cell create_normal() {
		return 0;
	}

	static Cell create_block(int block_id) {
		return block_id + 2;
	}

	static Cell create_goal() {
		return 1;
	}
};

// ???????????????????¨??¨?
struct OriginalBoard {
	int width;
	int height;
	std::vector<Cell> cells;
	int start_x;
	int start_y;
	int num_blocks;

	OriginalBoard() {
		cells.reserve(400);
	}

	void create_new(int width, int height) {
		this->width = width;
		this->height = height;
		cells.clear();
		num_blocks = 0;
	}

	void add_cell(int type) {
		switch (type) {
		case 0:
			cells.push_back(Cell::create_normal());
			break;
		case 1:
			cells.push_back(Cell::create_block(num_blocks++));
			break;
		case 2: {
			int index = cells.size();
			start_x = index % width;
			start_y = index / width;
			cells.push_back(Cell::create_normal());
			break;
		}
		case 3:
			cells.push_back(Cell::create_goal());
			break;
		default:
			assert(false);
		}
	}
};

class Board {
	OriginalBoard& original_board;
	std::vector<bool> block_dead_flags; // bool ??????????????????

	Board(Board& base_board, int dead_block_id)
		: original_board(base_board.original_board),
		block_dead_flags(base_board.block_dead_flags) // ??????????????????????????????
	{
		block_dead_flags[dead_block_id] = true;
	}

	int get_index(int x, int y) {
		return original_board.width * y + x;
	}

public:
	Board(OriginalBoard& original_board)
		: original_board(original_board),
		block_dead_flags(original_board.num_blocks, false)
	{}

	int width() {
		return original_board.width;
	}

	int height() {
		return original_board.height;
	}

	Cell get_cell(int x, int y) {
		Cell& cell = original_board.cells[get_index(x, y)];
		return cell.is_block() && block_dead_flags[cell.block_id()]
			? Cell::create_normal()
			: cell;
	}

	Board destroy_block(int block_id) {
		return Board(*this, block_id);
	}
};

int search(Board board, int start_x, int start_y, int count) {
	if (count >= 10) return -1;
	count++;

	int result = -1;
	if (start_y > 0 && !board.get_cell(start_x, start_y - 1).is_block()) {
		for (int y = start_y - 1; y >= 0; y--) {
			Cell cell = board.get_cell(start_x, y);
			if (cell.is_goal()) return count;
			if (cell.is_block()) {
				result = search(board.destroy_block(cell.block_id()), start_x, y + 1, count);
				break;
			}
		}
	}

	if (start_y + 1 < board.height() && !board.get_cell(start_x, start_y + 1).is_block()) {
		for (int y = start_y + 1; y < board.height(); y++) {
			Cell cell = board.get_cell(start_x, y);
			if (cell.is_goal()) return count;
			if (cell.is_block()) {
				int r = search(board.destroy_block(cell.block_id()), start_x, y - 1, count);
				if (r != -1 && (result == -1 || r < result))
					result = r;
				break;
			}
		}
	}

	if (start_x > 0 && !board.get_cell(start_x - 1, start_y).is_block()) {
		for (int x = start_x - 1; x >= 0; x--) {
			Cell cell = board.get_cell(x, start_y);
			if (cell.is_goal()) return count;
			if (cell.is_block()) {
				int r = search(board.destroy_block(cell.block_id()), x + 1, start_y, count);
				if (r != -1 && (result == -1 || r < result))
					result = r;
				break;
			}
		}
	}

	if (start_x + 1 < board.width() && !board.get_cell(start_x + 1, start_y).is_block()) {
		for (int x = start_x + 1; x < board.width(); x++) {
			Cell cell = board.get_cell(x, start_y);
			if (cell.is_goal()) return count;
			if (cell.is_block()) {
				int r = search(board.destroy_block(cell.block_id()), x - 1, start_y, count);
				if (r != -1 && (result == -1 || r < result))
					result = r;
				break;
			}
		}
	}

	return result;
}

int main()
{
	OriginalBoard original_board;

	while (true) {
		{
			int w, h;
			std::cin >> w >> h;

			if (w == 0) return 0;

			original_board.create_new(w, h);

			int size = w * h;
			for (int i = 0; i < size; i++) {
				int c;
				std::cin >> c;
				original_board.add_cell(c);
			}
		}

		int result = search(Board(original_board), original_board.start_x, original_board.start_y, 0);

		std::cout << result << std::endl;
	}
}

Measured memory_bytes: 3008