require 'set'

module Graph
	def add_node(data = nil)
		Node.new(data)
	end

	def add_edge(u, v, label = nil)
		e = Edge.new(u, v, label)
		u.outgoings << e
		v.incomings << e
		e
	end
	
	def del_edge(e)
		u, v = e.from, e.to
		u.outgoings.delete(e)
		v.incomings.delete(e)
		e
	end

	class Node
		def initialize(data)
			@data = data
			@outgoings = Set.new
			@incomings = Set.new
		end

		def to_nodes
			@outgoings.map(&:to)
		end

		def from_nodes
			@incomings.map(&:from)
		end
		
		def to_s
			@label
		end

		attr_accessor :incomings, :outgoings
		attr_reader :data
	end

	class Edge
		def initialize(u, v, label = nil)
			@from = u	
			@to = v
			@label = label
		end
		attr_reader :from, :to, :label
	end

	def get_path(s, t, reached = Set.new)
		return [s] if s == t
		reached << s	
		s.outgoings.each{|e|
			v = e.to
			next if reached.include?(v)
			path = get_path(v, t, reached) 
			return [e] + path if path
		}
		nil
	end
end

extend Graph

loop {
	w, h = gets.split.map(&:to_i)
	break if w == 0
	a = (1..h).map{ gets.split.map(&:to_i) }
	nodes = (0..h-1).map{|i| (0..w-1).map{|j| add_node} }

	(0..h-1).each{|i|
		(0..w-1).each{|j|
			next if a[i][j] == 1
			u = nodes[i][j]
			if j < w-1 && a[i][j+1] != 1
				v = nodes[i][j+1]
				add_edge(u, v, :right)
				add_edge(v, u, :left)
			end
			if i < h-1 && a[i+1][j] != 1
				v = nodes[i+1][j]
				add_edge(u, v, :down)
				add_edge(v, u, :up)
			end
		}
	}

	goal_node = cargo_node = pusher_node = nil
	(0..h-1).each{|i|
		(0..w-1).each{|j|
			goal_node = nodes[i][j] if a[i][j] == 3
			cargo_node = nodes[i][j] if a[i][j] == 2
			pusher_node = nodes[i][j] if a[i][j] == 4
		}
	}
	
	movable_dir = -> pushee, pusher {
		dirs = []
		pushee.outgoings.each{|to_edge|
			dir = to_edge.label
			in_edge = pushee.incomings.find{|e| e.label == dir}
			next unless in_edge
			tmp = pushee.outgoings
			pushee.outgoings = []
			dirs << dir if get_path(pusher, in_edge.from)
			pushee.outgoings = tmp
		}
		dirs.sort
	}

	state = [cargo_node, movable_dir[cargo_node, pusher_node]]
	queue = [state]
	push = 0
	reached = Set[state]

	success = false
	loop {
		next_queue = []
		until queue.empty?
			u, dirs = queue.pop
			if u == goal_node
				success = true
				break
			end
			dirs.each{|dir|
				e = u.outgoings.find{|e| e.label == dir}
				v = e.to
				state = [v, movable_dir[v, u]]
				next if reached.include?(state)
				reached << state
				next_queue << state
			}
		end

		break if success
		if next_queue.empty?
			push = -1
			break
		end

		queue = next_queue
		push += 1
	}
	p push
}