#ifndef VS
#include<bits/stdc++.h>
#endif

using namespace std;
typedef long long LL;

#ifdef BTK
#define DEBUG if(1)
#else
#define CIN_ONLY if(1)
struct cww {cww() {CIN_ONLY{ios::sync_with_stdio(false); cin.tie(0);}}
}star;
#define DEBUG if(0)
#endif

#define ALL(v) (v).begin(),(v).end()
#define REC(ret, ...) std::function<ret (__VA_ARGS__)>
template <typename T>inline bool chmin(T &l, T r){bool a = l>r; if (a)l = r; return a;}
template <typename T>inline bool chmax(T &l, T r){bool a = l<r; if (a)l = r; return a;}
template <typename T>istream& operator>>(istream &is, vector<T> &v){for (auto &it : v)is >> it;return is;}

class range {private: struct I { int x; int operator*() { return x; }bool operator!=(I& lhs) { return x<lhs.x; }void operator++() { ++x; } }; I i, n;public:range(int n) :i({ 0 }), n({ n }) {}range(int i, int n) :i({ i }), n({ n }) {}I& begin() { return i; }I& end() { return n; }};

constexpr int MAX_N = 812345;
struct P{
	int r, c;
};
istream& operator>>(istream &is, P &v) { is >> v.r >> v.c; return is; }

P S, T;
int N;
P in[MAX_N];
namespace Z{
	int latte[MAX_N];
	int id;
	void init() {
		id = 0;
	}
	inline void set(int v) {
		latte[id++] = v;
	}
	inline void build() {
		sort(latte, latte + id);
		id = unique(latte, latte + id) - latte;
	}
	inline int ItoZ(int v) {
		return lower_bound(latte, latte + id, v) - latte;
	}
	inline int ZtoI(int v) {
		return latte[v];
	}
}

bool input() {
	if(cin >> S >> T);
	else return false;
	cin >> N;
	Z::init();
	for (int j : {-1, 0, 1}) {
		Z::set(S.r + j);
		Z::set(S.c + j);
		Z::set(T.r + j);
		Z::set(T.c + j);
	}
	for (int i : range(N)) {
		cin >> in[i];
		for (int j : {-1, 0, 1}) {
			Z::set(in[i].r + j);
			Z::set(in[i].c + j);
		}
	}
	Z::build();
	S.r = Z::ItoZ(S.r);	S.c = Z::ItoZ(S.c);
	T.r = Z::ItoZ(T.r);	T.c = Z::ItoZ(T.c);
	for (int i : range(N)) {
		in[i].r = Z::ItoZ(in[i].r);
		in[i].c = Z::ItoZ(in[i].c);
	}
#ifdef BTK
	cout << S.r << " " << S.c << endl;
	cout << T.r << " " << T.c << endl;
	cout << N << endl;
	for (int i : range(N)) {
		cout << in[i].r << " " << in[i].c << endl;
	}
#endif
	return true;
}
typedef vector<int> V;
typedef vector<V> VV;
typedef vector<VV> VVV;
constexpr int dr[4] = { 1,0,0,-1 };
constexpr int dc[4] = { 0,1,-1,0 };
const string ds = { "DRLU" };
struct Tate {
	static constexpr int index = 0;
	static inline bool comp(const int lr, const int lc, const int rr, const int rc) {
		return lr == rr ? lc < rc : lr < rr;
	}
};
struct Yoko {
	static constexpr int index = 1;
	static inline bool comp(const int lr, const int lc, const int rr, const int rc) {
		return lc == rc ? lr < rr : lc < rc;
	}
};

namespace pts {
	int pt[2][MAX_N];
	int cr[MAX_N];
	template<typename dir>
	inline bool ice_comp(const int li, const int ri) {
		return dir::comp(in[li].r, in[li].c, in[ri].r, in[ri].c);
	}
	void build() {
		iota(pt[Yoko::index], pt[Yoko::index] + N, 0);
		iota(pt[Tate::index], pt[Tate::index] + N, 0);
		sort(pt[Yoko::index], pt[Yoko::index] + N, ice_comp<Yoko>);
		sort(pt[Tate::index], pt[Tate::index] + N, ice_comp<Tate>);
	}
	template<typename dir>
	inline int lower_bound(int r, int c) {
		int lb = -1, ub = N;
		while (ub - lb > 1) {
			const int mid = (lb + ub) / 2;
			(!dir::comp(r, c, in[pt[dir::index][mid]].r, in[pt[dir::index][mid]].c) ? lb : ub) = mid;
		}
		return ub;
	}
	inline bool isIce(int r, int c) {
		int id = lower_bound<Yoko>(r, c);
		return id != N && in[pt[Yoko::index][id]].r == r && in[pt[Yoko::index][id]].c == c;
	}
}

struct Down {
	static constexpr int index = 0;
	static inline int getIce(int r, int c) {
		int id = pts::lower_bound<Yoko>(r, c);
		if (id != N && in[pts::pt[Yoko::index][id]].c == c)
			return pts::pt[Yoko::index][id];
		else return -1;
	}
};

struct Right {
	static constexpr int index = 1;
	static inline int getIce(int r, int c) {
		int id = pts::lower_bound<Tate>(r, c);
		if (id != N && in[pts::pt[Tate::index][id]].r == r)
			return pts::pt[Tate::index][id];
		else return -1;
	}
};
struct Left {
	static constexpr int index = 2;
	static inline int getIce(int r, int c) {
		int id = pts::lower_bound<Tate>(r, c) - 1;
		if (id != -1 && in[pts::pt[Tate::index][id]].r == r)
			return pts::pt[Tate::index][id];
		else return -1;
	}
};
struct Up {
	static constexpr int index = 3;
	static inline int getIce(int r, int c) {
		int id = pts::lower_bound<Yoko>(r, c) - 1;
		if (id != -1 && in[pts::pt[Yoko::index][id]].c == c)
			return pts::pt[Yoko::index][id];
		else return -1;
	}
};
		
inline bool isReachable(int r,int c,int nr,int nc) {
	if (r == nr) {
		if (c < nc) {
			const int id = Right::getIce(r, c);
			return id == -1 || nc < in[id].c;
		}
		else if (nc < c) {
			const int id = Left::getIce(r, c);
			return id == -1 || in[id].c < nc;
		}
		else return true;
	}
	else if (c == nc) {
		if (r < nr) {
			const int id = Down::getIce(r, c);
			return id == -1 || nr < in[id].r;
		}
		else if (nr < r) {
			const int id = Up::getIce(r, c);
			return id == -1 || in[id].r < nr;
		}
		else return true;
	}
	else return false;
}


vector<P> g[MAX_N][4];
vector<P> rg[MAX_N][4];

int dist[MAX_N][4];
int rdist[MAX_N][4];
template<typename dir> 
inline void addArc(const int i, const int j, const int r,const int c) {
	const int id = dir::getIce(r, c);
	if (id != -1) {
		g[i][j].push_back(P{ id,3 - dir::index });
		rg[id][3 - dir::index].push_back(P{ i,j });
	}
}
void buildGraph(){
	for (int i : range(N)) {
		for (int d : range(4)) {
			int r = in[i].r + dr[d];
			int c = in[i].c + dc[d];
			if (pts::isIce(r, c))continue;
			addArc<Down>(i, d, r, c);
			addArc<Up>(i, d, r, c);
			addArc<Left>(i, d, r, c);
			addArc<Right>(i, d, r, c);
		}
	}
}
template<typename dir>
void uku(){
	int id = dir::getIce(S.r, S.c);
	if (id != -1) {
		const int r = in[id].r + dr[3 - dir::index];
		const int c = in[id].c + dc[3 - dir::index];
		dist[id][3 - dir::index] = (S.r != r || S.c != c);
	}
}
constexpr int INF = 1e7;
queue<P> que;
void bfs() {
	uku<Down>();
	uku<Left>();
	uku<Right>();
	uku<Up>();
	for (int i : range(N)) {
		for (int d : range(4)) {
			if (dist[i][d] == 0)que.push(P{ i,d });
		}
	}
	for (int i : range(N)) {
		for (int d : range(4)) {
			if (dist[i][d] == 1)que.push(P{ i,d });
		}
	}
	while (!que.empty()) {
		int i = que.front().r;
		int j = que.front().c;
		que.pop();
		for (auto &it : g[i][j]) {
			int ni = it.r;
			int nj = it.c;
			if (chmin(dist[ni][nj], dist[i][j] + 1)) {
				que.push(it);
			}
		}
	}
	for (int i : range(N)) {
		for (int d : range(4)) {
			const int r = in[i].r + dr[d];
			const int c = in[i].c + dc[d];
			if (isReachable(r, c, T.r, T.c)) {
				rdist[i][d] = 0;
				que.push(P{ i,d });
			}
		}
	}
	while (!que.empty()) {
		int i = que.front().r;
		int j = que.front().c;
		que.pop();
		for (auto &it : rg[i][j]) {
			int ni = it.r;
			int nj = it.c;
			if (chmin(rdist[ni][nj], rdist[i][j] + 1)) {
				que.push(it);
			}
		}
	}
}
typedef int A;
struct node {A a;};
A mg(node& v, int l, int r) {return v.a;}
A mg(A l, A r) {
	return min(l, r);
}
namespace ST {
	node mem[4123456];
	int cnt = 0;
	node* get() { return mem; }
}
struct seg_tree {
	int size;
	node *seg;
	void init(int l, int r, int k = 0) {
		auto &v = seg[k];
		//flag関連の処理
		if (r - l == 1) {
			//葉の時の処理
			v.a = INF;
		}
		else if (r - l>1) {
			int m = (l + r) / 2;
			init(l, m, k * 2 + 1); 
			init(m, r, k * 2 + 2);
			v.a = mg(mg(seg[k * 2 + 1], l, m), mg(seg[k * 2 + 2], m, r));
		}
	}
	seg_tree(int n) {
		size = 1;
		while (size<n)size *= 2;
		seg = ST::get();
		init(0, size);
	}
#define LQ a,b,k*2+1,l,m
#define RQ a,b,k*2+2,m,r
	A get(int a, int b, int k, int l, int r) {
		if (a <= l && r <= b)return mg(seg[k], l, r);
		int m = (l + r) / 2;
		bool ll = !(m <= a || b <= l);
		bool rr = !(r <= a || b <= m);
		A ret;
		if (ll&&rr)ret = mg(get(LQ), get(RQ));
		else if (ll)ret = get(LQ);
		else ret = get(RQ);
		seg[k].a = mg(mg(seg[k * 2 + 1], l, m), mg(seg[k * 2 + 2], m, r));
		return ret;
	}
	A get(int a, int b) { 
		if (a >= b)return INF;
		return get(a, b, 0, 0, size);
	}
	void update(int a, int b, int k, int l, int r, int v) {
		if (r <= a || b <= l)return;
		if (a <= l && r <= b) {
			seg[k].a = v;
		}
		else {
			int m = (l + r) / 2;
			update(LQ, v);
			update(RQ, v);
			seg[k].a = mg(mg(seg[k * 2 + 1], l, m), mg(seg[k * 2 + 2], m, r));
		}
	}
	void update(int a, A v) {
		update(a, a+1, 0, 0, size, v);
	}
	void weak_update(int a, int b, int k, int l, int r, int v) {
		if (r <= a || b <= l)return;
		if (a <= l && r <= b) {
			chmin(seg[k].a, v);
		}
		else {
			int m = (l + r) / 2;
			weak_update(LQ, v);
			weak_update(RQ, v);
			seg[k].a = mg(mg(seg[k * 2 + 1], l, m), mg(seg[k * 2 + 2], m, r));
		}
	}
	void weak_update(int a, A v) {
		weak_update(a, a + 1, 0, 0, size, v);
	}

};

int ret = INF;
void solve_down() {
	constexpr int dir = Down::index;
	constexpr int s = Left::index;
	seg_tree st(Z::id);
	for (int lb = 0; lb < N;) {
		int ub = lb;
		int* pt = pts::pt[Tate::index];
		while (ub < N&&
			in[pt[lb]].r == in[pt[ub]].r) {
			ub++;
		}
		chmin(ret, rdist[pt[lb]][s] + st.get(0, in[pt[lb]].c) + 1);
		for (int i : range(lb, ub-1)) {
			const int seg_cost = st.get(in[pt[i]].c + 1, in[pt[i + 1]].c);
			chmin(ret, rdist[pt[i]][3 - s] + seg_cost + 1);
			chmin(ret, rdist[pt[i + 1]][s] + seg_cost + 1);
		}
		chmin(ret, rdist[pt[ub - 1]][3 - s] + st.get(in[pt[ub - 1]].c + 1, Z::id) + 1);
		for (int i : range(lb, ub)) {
			st.update(in[pt[i]].c, dist[pt[i]][dir]);
			st.weak_update(in[pt[i]].c + dc[s], dist[pt[i]][s]);
			st.weak_update(in[pt[i]].c + dc[3 - s], dist[pt[i]][3 - s]);
		}
		lb = ub;
	}
}

void solve_right() {
	constexpr int dir = Right::index;
	constexpr int s = Up::index;
	seg_tree st(Z::id);
	for (int lb = 0; lb < N;) {
		int ub = lb;
		int* pt = pts::pt[Yoko::index];
		while (ub < N&&
			in[pt[lb]].c == in[pt[ub]].c) {
			ub++;
		}
		chmin(ret, rdist[pt[lb]][s] + st.get(0, in[pt[lb]].r) + 1);
		for (int i : range(lb, ub - 1)) {
			const int seg_cost = st.get(in[pt[i]].r + 1, in[pt[i + 1]].r);
			chmin(ret, rdist[pt[i]][3 - s] + seg_cost + 1);
			chmin(ret, rdist[pt[i + 1]][s] + seg_cost + 1);
		}
		chmin(ret, rdist[pt[ub - 1]][3 - s] + st.get(in[pt[ub - 1]].r + 1, Z::id) + 1);
		for (int i : range(lb, ub)) {
			st.update(in[pt[i]].r, dist[pt[i]][dir]);
			st.weak_update(in[pt[i]].r + dr[s], dist[pt[i]][s]);
			st.weak_update(in[pt[i]].r + dr[3 - s], dist[pt[i]][3 - s]);
		}
		lb = ub;
	}
}

void solve_up() {
	constexpr int dir = Up::index;
	constexpr int s = Left::index;
	seg_tree st(Z::id);
	for (int lb = N-1; lb >= 0;) {
		int ub = lb;
		int* pt = pts::pt[Tate::index];
		while (ub >=0 &&
			in[pt[lb]].r == in[pt[ub]].r) {
			ub--;
		}
		chmin(ret, rdist[pt[ub+1]][s] + st.get(0, in[pt[ub+1]].c) + 1);
		for (int i : range(ub+1, lb)) {
			const int seg_cost = st.get(in[pt[i]].c + 1, in[pt[i + 1]].c);
			chmin(ret, rdist[pt[i]][3 - s] + seg_cost + 1);
			chmin(ret, rdist[pt[i + 1]][s] + seg_cost + 1);
		}
		chmin(ret, rdist[pt[lb]][3 - s] + st.get(in[pt[lb]].c + 1, Z::id) + 1);
		for (int i : range(ub+1, lb+1)) {
			st.update(in[pt[i]].c, dist[pt[i]][dir]);
			st.weak_update(in[pt[i]].c + dc[s], dist[pt[i]][s]);
			st.weak_update(in[pt[i]].c + dc[3 - s], dist[pt[i]][3 - s]);
		}
		lb = ub;
	}
}

void solve_left() {
	constexpr int dir = Left::index;
	constexpr int s = Up::index;
	seg_tree st(Z::id);
	for (int lb = N-1; lb >= 0;) {
		int ub = lb;
		int* pt = pts::pt[Yoko::index];
		while (ub >=0&&
			in[pt[lb]].c == in[pt[ub]].c) {
			ub--;
		}
		chmin(ret, rdist[pt[ub+1]][s] + st.get(0, in[pt[ub+1]].r) + 1);
		for (int i : range(ub+1, lb)) {
			const int seg_cost = st.get(in[pt[i]].r + 1, in[pt[i + 1]].r);
			chmin(ret, rdist[pt[i]][3 - s] + seg_cost + 1);
			chmin(ret, rdist[pt[i + 1]][s] + seg_cost + 1);
		}
		chmin(ret, rdist[pt[lb]][3 - s] + st.get(in[pt[lb]].r + 1, Z::id) + 1);
		for (int i : range(ub+1, lb+1)) {
			st.update(in[pt[i]].r, dist[pt[i]][dir]);
			st.weak_update(in[pt[i]].r + dr[s], dist[pt[i]][s]);
			st.weak_update(in[pt[i]].r + dr[3 - s], dist[pt[i]][3 - s]);
		}
		lb = ub;
	}
}
inline bool isReachableWithHop(int r,int c) {
	return (isReachable(r, c, r, T.c) &&
		isReachable(r, T.c, T.r, T.c)) ||
		(isReachable(r, c, T.r, c) &&
			isReachable(T.r, c, T.r, T.c));
}

int main() {
	while (input()) {
		pts::build();
		if (isReachableWithHop(S.r, S.c)) {
			cout << 0 << endl; continue;
		}
		for (int i : range(N)) {
			for (int j : range(4)) {
				g[i][j].clear();
				rg[i][j].clear();
				dist[i][j] = INF;
				rdist[i][j] = INF;
			}
		}
		buildGraph();
		bfs();
		
		for (int i : range(N)) {
			for (int j : range(4)) {
				const int r = in[i].r + dr[j];
				const int c = in[i].c + dc[j];
				if (isReachableWithHop(r, c)) {
					chmin(ret, dist[i][j]);
					isReachableWithHop(r, c);
				}
			}
		}
		DEBUG cout << ret << endl;

		for (int i : range(N)) {
			if (isReachable(S.r,S.c,S.r,in[i].c)) {
				const int r = S.r;
				const int c = in[i].c;
				if (Down::getIce(r, c) == i)
					chmin(ret, rdist[i][3 - Down::index] + 1);
				if (Left::getIce(r, c) == i)
					chmin(ret, rdist[i][3 - Left::index] + 1);

				if (Right::getIce(r, c) == i)
					chmin(ret, rdist[i][3 - Right::index] + 1);
				if (Up::getIce(r, c) == i)
					chmin(ret, rdist[i][3 - Up::index] + 1);
			}
			if (isReachable(S.r, S.c, in[i].r, S.c)) {
				const int r = in[i].r;
				const int c = S.c;
				if (Down::getIce(r, c) == i)
					chmin(ret, rdist[i][3 - Down::index] + 1);
				if (Left::getIce(r, c) == i)
					chmin(ret, rdist[i][3 - Left::index] + 1);
				if (Right::getIce(r, c) == i)
					chmin(ret, rdist[i][3 - Right::index] + 1);
				if (Up::getIce(r, c) == i)
					chmin(ret, rdist[i][3 - Up::index] + 1);
			}
		}
		DEBUG cout << ret << endl;
		solve_down();
		solve_up();
		solve_left();
		solve_right();
		if (ret == INF)cout << -1 << endl;
		else cout << ret << endl;
	}
	return 0;
}



Measured memory_bytes: 201164