#include <iostream>
#include <iomanip>
#include <vector>
#include <array>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <tuple>
#include <cmath>
#include <algorithm>
#include <functional>
#include <numeric>
#include <cfloat>
#include <climits>
#include <cassert>
#include <random>
#include <fstream>
struct Coordinate {
	int x, y;
	Coordinate operator-(const Coordinate that) const {
		return Coordinate{ x - that.x, y - that.y };
	}
	Coordinate operator+(const Coordinate that) const {
		return Coordinate{ x + that.x, y + that.y };
	}
	bool operator==(const Coordinate that) const {
		return x == that.x && y == that.y;
	}
	bool operator!=(const Coordinate that) const {
		return !(*this == that);
	}
	std::vector<Coordinate> neighbors() const {
		return { {x + 1, y}, {x - 1, y}, {x, y + 1}, {x, y - 1} };
	}
};

std::vector<Coordinate> cargo_neighbor(const Coordinate current, const Coordinate cargo, const std::vector<std::vector<int>>& state) {
	std::vector<std::vector<bool>> is_reach(state.size(), std::vector<bool>(state.front().size(), false)); is_reach[current.y][current.x] = true;
	std::stack<Coordinate> stack; stack.push(current);
	std::vector<Coordinate> result;
	while (!stack.empty()) {
		const auto top = stack.top(); stack.pop();
		for (const auto n : top.neighbors()) {
			if (cargo == n) {
				result.push_back(top); continue;
			}
			if (n.y < 0 || state.size() <= n.y || n.x < 0 || state[n.y].size() <= n.x) continue;
			if (state[n.y][n.x] == 1) continue;
			if (is_reach[n.y][n.x]) continue;
			is_reach[n.y][n.x] = true;
			stack.push(n);
		}
	}
	return result;
}
int main() {
	while (true) {
		int w, h; std::cin >> w >> h; if (w == 0 && h == 0) break;
		std::vector<std::vector<int>> state(h, std::vector<int>(w));
		for (auto& line : state) for (auto& c : line) std::cin >> c;
		Coordinate man, cargo, goal;
		for (auto i = 0; i < h; ++i) for (auto j = 0; j < w; ++j) {
			switch (state[i][j]) {
			case 2: cargo = Coordinate{ j, i }; break;
			case 3: goal = Coordinate{ j, i }; break;
			case 4: man = Coordinate{ j, i }; break;
			default:;
			}
		}
		std::vector<bool> min_step(h * h * w * w, false);
		std::queue<std::pair<Coordinate, Coordinate>> queue;
		min_step[(man.y * h + man.x) * h * w + cargo.y * h + cargo.x] = true;
		queue.emplace(man, cargo);
		int min = -1;
		for (auto count = 1; min == -1 && !queue.empty(); ++count) {
			for (auto s = queue.size(); min == -1 && s > 0; --s) {
				const auto top = queue.front(); queue.pop();
				for (const auto next : cargo_neighbor(top.first, top.second, state)) {
					const auto pushed = top.second + top.second - next;
					if (0 <= pushed.x && pushed.x < w && 0 <= pushed.y && pushed.y < h) {
						if (state[pushed.y][pushed.x] == 1) continue;
						if (min_step[(top.second.y * h + top.second.x) * h * w + pushed.y * h + pushed.x]) continue;
						if (pushed == goal) {
							min = count;
							break;
						}
						min_step[(top.second.y * h + top.second.x) * h * w + pushed.y * h + pushed.x] = true;
						queue.emplace(top.second, pushed);
					}
				}
			}
		}
		std::cout << min << '\n';
	}
}

