// Arup Guha
// 5/26/2016
// Solution to USACO Gold December Problem: Bessie's Dream

import java.util.*;
import java.io.*;

public class dream {

	final public static int[] DX = {-1,0,0,1};
	final public static int[] DY = {0,-1,1,0};
	public static int r;
	public static int c;
	public static int[][] grid;
	public static int[] dist;

	public static void main(String[] args) throws Exception {

		// Read in data.
		BufferedReader stdin = new BufferedReader(new FileReader("dream.in"));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());
		r = Integer.parseInt(tok.nextToken());
		c = Integer.parseInt(tok.nextToken());
		grid = new int[r][c];
		for (int i=0; i<r; i++) {
			tok = new StringTokenizer(stdin.readLine());
			for (int j=0; j<c; j++)
				grid[i][j] = Integer.parseInt(tok.nextToken());
		}

		// Write result.
		PrintWriter out = new PrintWriter(new FileWriter("dream.out"));
		out.println(bfs());
		out.close();
		stdin.close();
	}

	public static int bfs() {

		// 0 = can't go, 1 = normal, 2 = add smell, 3 = need smell, 4 = slide+erase smell
		// State: location, smell(0/1), direction(0/1/2/3 - up, left, right, down)

		LinkedList<Integer> q = new LinkedList<Integer>();
		q.offer(2);
		q.offer(3);

		// Stores distances to each possible state.
		dist = new int[r*c*8];
		Arrays.fill(dist, -1);
		dist[2] = 0;
		dist[3] = 0;

		// Run BFS.
		while (q.size() > 0) {

			int cur = q.poll();
			int dir = (cur & 3);
			int smell = (cur & 4);
			int loc = cur >> 3;
			int curX = loc/c;
			int curY = loc%c;

			// Got to the end!
			if (loc == r*c-1) return dist[cur];

			// Next spot on grid.
			int nextX = curX + DX[dir];
			int nextY = curY + DY[dir];

			// Must be inbounds, passable.
			if (!inbounds(nextX, nextY)) continue;
			if (grid[nextX][nextY] == 0) continue;
		
			// Piranas will eat us, so we can't go here.
			if (grid[nextX][nextY] == 3 && smell != 4) continue;

			// Can go in any direction.
			if (grid[nextX][nextY] < 4) {
				int thisSmell = grid[nextX][nextY] == 2 ? 4 : smell;
				for (int dirIndex=0; dirIndex<4; dirIndex++) {
					int index = 8*(nextX*c + nextY)+thisSmell+dirIndex;
					if (dist[index] == -1) {
						q.offer(index);
						dist[index] = dist[cur]+1;
					}
				}
			}

			// Purple rules - only go in one direction (old direction), and no smell.
			if (grid[nextX][nextY] == 4) {

				if (dist[8*(nextX*c + nextY)+dir] == -1) {
					q.offer(8*(nextX*c + nextY)+dir);
					dist[8*(nextX*c + nextY)+dir] = dist[cur]+1;
				}

				
				// If that one way doesn't work, then we can try the rest...
				if (bad(nextX, nextY, dir)) {
					for (int i=0; i<4; i++) {
						if (i == dir) continue;
						int index = 8*(nextX*c + nextY)+i;
						if (dist[index] == -1) {
							q.offer(index);
							dist[index] = dist[cur]+1;
						}
					}
				}
			}			
		}

		// Never made it.
		return -1;
	}

	public static boolean bad(int x, int y, int dir) {
		int nextX = x + DX[dir];
		int nextY = y + DY[dir];
		if (!inbounds(nextX, nextY)) return true;
		if (grid[nextX][nextY] == 0 || grid[nextX][nextY] == 3) return true;
		return false;
	}

	public static boolean inbounds(int x, int y) {
		return x >= 0 && x < r && y >= 0 && y < c;
	}
}