////////////////////////////////////////
///  tu3 pro-con template            ///
////////////////////////////////////////
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <functional>
#include <vector>
#include <queue>
#include <string>
#include <complex>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <regex>
using namespace std;

//// MACRO ////
#define countof(a) (sizeof(a)/sizeof(a[0]))

#define REP(i,n) for (int i = 0; i < (n); i++)
#define RREP(i,n) for (int i = (n)-1; i >= 0; i--)
#define FOR(i,s,n) for (int i = (s); i < (n); i++)
#define RFOR(i,s,n) for (int i = (n)-1; i >= (s); i--)
#define pos(c,i) c.being() + (i)
#define allof(c) c.begin(), c.end()
#define aallof(a) a, countof(a)
#define partof(c,i,n) c.begin() + (i), c.begin() + (i) + (n)
#define apartof(a,i,n) a + (i), a + (i) + (n)
#define long long long

#define EPS 1e-9
#define INF 100000000

#define PREDICATE(t,a) (const t & a) -> bool
#define COMPARISON_T(t) bool(*)(const t &, const t &)
#define COMPARISON(t,a,b) (const t & a, const t & b) -> bool
#define CONVERTER(TSrc,t,TDest) (const TSrc &t)->TDest
//// algorithm ////

// compare
template <class InIt1, class InIt2>
int partial_compare(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2)
{
	return lexicographical_compare(first1, last1, first2, last2) ? -1
		: lexicographical_compare(first2, last2, first1, last1) ? 1
		: 0;
}

// index_of
template <class InIt, class T>
inline int index_of(InIt first1, InIt last1, const T &val)
{
	InIt f = find(first1, last1, val);
	return f != last1 ? distance(f, first1) : -1;
}

// C# BinarySearch風のindex_of
template <class InIt, class T>
inline int bindex_of(InIt first1, InIt last1, const T &val)
{
	auto it = lower_bound(first1, last1, val);
	if (it != last1 && *it == val) { return distance(it, first1); }
	return ~distance(it, first1);
}

// iota vector 
vector<int> iotav(int begin, int end)
{
	vector<int> r(end - begin);
	iota(allof(r), begin);
	return r;
}

// iota イテレータ
struct iotait
{
	int n;
	iotait(int n = 0) : n(n) { }
	iotait &operator ++() { ++n; return *this; }
	int operator *() { return n; }
};

// 文字列の置換
void inplaceReplace(string &target, const string &from, const string &to, bool global = false)
{
	do
	{
		string::size_type pos = target.find(from);
		if (pos == target.npos) { break; }
		target.replace(pos, from.length(), to);
	} while (true);
}

inline bool contains(int x, int min, int max) { return x >= min && x < max; }
inline bool contains(int x, int y, int W, int H) { return x >= 0 && x < W && y >= 0 && y < H; }

// 最大公約数
long gcd(long a, long b) { return b ? gcd(b, a%b) : a; }

// 最小公倍数
long lcm(long a, long b) { return a / gcd(a, b) * b; }

// 拡張ユークリッド互除法
void exgcd(long a, long b, long& x, long& y) {
	if (b != 0) { exgcd(b, a%b, y, x); y -= a / b*x; }
	else { x = 1; y = 0; }
}

//// data structure ////

/// 2分セグメント木。RMQとかが解ける。
template<class T = int, class TParentFunc = const T& (*)(const T&, const T&)>
struct SegTree
{
	int count;
	vector<T> tree;
	TParentFunc parent;

	SegTree(int size, TParentFunc parentBuilder = std::min, T initialFill = INF)
		: count((size | size - 1) + 1)
		, tree(count * 2)
		, parent(parentBuilder)
	{
		fill(partof(tree, count, count), initialFill);
		rebuild();
	}

	// []を使うと更新されないのでrebuildすること。数が少なければupdateの方がよい。
	T& operator[](int i) { return tree[i + count]; }
	void rebuild() { RREP(i, count) { tree[i] = parent(tree[i * 2], tree[i * 2 + 1]); } }

	void update(int index, T value)
	{
		tree[index + count] = value;
		for (int i = (index + count) / 2; i > 0; i /= 2)
			tree[i] = parent(tree[i * 2], tree[i * 2 + 1]);
	}

	T query(int s, int e, int i, int l, int r, T value)
	{
		if (r <= s || e <= l) return value;
		if (s <= l && r <= e) return parent(value, tree[i]);
		value = query(s, e, i * 2, l, (l + r) / 2, value);
		value = query(s, e, i * 2 + 1, (l + r) / 2, r, value);
		return value;
	}

	T query(int start, int count, T initialValue)
	{
		return query(start, start + count, 1, 0, count, initialValue);
	}
};


//// prime ////
vector<unsigned char> isPrime;
vector<int> primes;
void initPrimes(int n)
{
	isPrime = vector<unsigned char>(n + 1, true);
	isPrime[0] = isPrime[1] = false;
	FOR(i, 2, n + 1)
	{
		if (!isPrime[i]) continue;
		primes.push_back(i);
		for (int j = i * 2; j <= n; j += i)
			isPrime[j] = false;
	}
}

//// Probability ////

// パスカルの三角形(二項定理) 2種類の並べ替えにつかう。
vector<vector<double>> makePascalTriangle(int n, bool probability = false)
{
	typedef vector<double> VD;
	vector<VD> t;
	if (!t.size()) { t.push_back(VD(1, 1)); }
	FOR(i, t.size(), n + 1)
	{
		t.push_back(VD(i + 1));
		REP(j, i)
		{
			double x = t[i - 1][j] * (probability ? 0.5 : 1);
			t[i][j] += x;
			t[i][j + 1] += x;
		}
	}
	return t;
}



//// geo ////

/// 3次元
struct P3
{
	double x, y, z;
	P3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) { }
	P3 operator +() const { return *this; }
	P3 operator +(const P3 &_) const { return P3(x + _.x, y + _.y, z + _.z); }
	P3 operator -() const { return P3(-x, -y, -z); }
	P3 operator -(const P3 &_) const { return *this + -_; }
	P3 operator *(double _) const { return P3(x*_, y*_, z*_); }
	P3 operator /(double _) const { return P3(x / _, y / _, z / _); }
	double dot(const P3 &_) const { return x*_.x + y*_.y + z*_.z; } // 内積
	P3 cross(const P3 &_) const { return P3(y*_.z - z*_.y, z*_.x - x*_.z, x*_.y - y*_.x); } // 外積
	double sqlength() const { return x*x + y*y + z*z; } // 二乗長さ
	double length() const { return sqrt(sqlength()); } // 長さ
	P3 direction() const { return *this / length(); } // 方向ベクトル
};
inline istream & operator>>(istream & in, P3 & p) { in >> p.x >> p.y >> p.z; return in; }
inline double abs(P3 p) { return p.length(); }

struct Sphere
{
	P3 c;
	double r;
	Sphere(double x, double y, double z, double r) : c(x, y, z), r(r) { }
	Sphere(P3 c, double r) : c(c), r(r) { }
	bool IntersectWith(const Sphere &rhs) const { return abs(c - rhs.c) - (r + rhs.r) < EPS; } // 接してても真。
};
inline istream & operator>>(istream & in, Sphere & c) { in >> c.c >> c.r; return in; }

/// 2次元
struct P2
{
	double x, y;
	P2(double x = 0, double y = 0) : x(x), y(y) { }
	P2(complex<double> c) : x(c.real()), y(c.imag()) { }
	P2 operator +() const { return *this; }
	P2 operator +(const P2 &_) const { return P2(x + _.x, y + _.y); }
	P2 operator -() const { return P2(-x, -y); }
	P2 operator -(const P2 &_) const { return *this + -_; }
	P2 operator *(double _) const { return P2(x*_, y*_); }
	P2 operator /(double _) const { return P2(x / _, y / _); }
	double dot(const P2 &_) const { return x*_.x + y*_.y; } // 内積
	double cross(const P2 &_) const { return x*_.y - y*_.x; } // 外積
	double sqlength() const { return x*x + y*y; } // 二乗長さ
	double length() const { return sqrt(sqlength()); } // 長さ
	P2 orthogonal() const { return P2(y, -x); }
	P2 direction() const { return *this / length(); } // 方向ベクトル
};
inline istream & operator>>(istream & in, P2 & p) { in >> p.x >> p.y; return in; }
inline ostream & operator<<(ostream & out, const P2 & p) { out << p.x << ' ' << p.y; return out; }
inline double abs(P2 p2) { return p2.length(); }
inline P2 orthogonal(P2 p) { return p.orthogonal(); }
inline complex<double> orthogonal(complex<double> c) { return  c * complex<double>(0, 1); }

// a,b から ちょうど d だけ離れた点。aとbを円周に持つ円の半径。
inline pair<P2, P2> get_same_distance_points(P2 a, P2 b, double d)
{
	assert(abs(a - b) <= 2 * d + EPS);
	auto v = (a + b) / 2.0 - a; // a から aとbの中点
	auto vl = abs(v);
	auto wl = sqrt(d*d - vl*vl); // 直行Vの大きさ
	auto w = orthogonal(v) * (wl / vl); // 直行V
	return make_pair(a + v + w, a + v - w);
}

struct Circle
{
	P2 c;
	double r;
	Circle() : c(), r() { }
	Circle(double x, double y, double r) : c(x, y), r(r) { }
	Circle(P2 c, double r) : c(c), r(r) { }
	bool IntersectWith(const Circle &rhs) const { return abs(c - rhs.c) - (r + rhs.r) < EPS; } // 接してても真。
	bool Contains(const P2 &p) const { return abs(p - c) - r < EPS; } // 接してても真。
};
inline istream & operator>>(istream & in, Circle & c) { in >> c.c >> c.r; return in; }

// 交差している2円の交点を求める。角度の小さい方から出る(右下方向が正なら時計回り)
inline pair<P2, P2> crossPoint(Circle A, Circle B)
{
	P2 v = B.c - A.c;
	P2 dir = v.direction(); // 他方の中心への方向
	double d = v.length(); // 他方の中心への距離
	double lh = (A.r*A.r + d*d - B.r*B.r) / (2 * d); // 垂線の足までの距離
	P2 h = A.c + dir * lh; // 垂線の足
	double lp = sqrt(A.r*A.r - lh*lh); // 垂線の足から交点までの距離
	P2 p = dir.orthogonal() * lp; // 垂線の足から交点へのベクトル
	return make_pair(h + p, h - p); // 交点の組。
}

inline int clockwise(P2 a, P2 b, P2 c)
{
	const P2 u = b - a, v = c - a;
	if (u.cross(v) > EPS) { return 1; }
	if (u.cross(v) < -EPS) { return -1; }
	if (u.dot(v) < -EPS) { return -1; }
	if (abs(u) - abs(v) < EPS) { return 1; }
	return 0;
}

//// bit ////
#ifdef _MSC_VER
#pragma push_macro("long")
#undef long
inline unsigned __builtin_ctz(unsigned x) { unsigned long r; _BitScanForward(&r, x); return r; }
#  define __builtin_popcount __popcnt
#pragma pop_macro("long")
#endif

inline int next_bit_permutation(int x)
{
	int t = x | (x - 1);
	return (t + 1) | (unsigned)((~t & -~t) - 1) >> (__builtin_ctz(x) + 1);
}

// x の p1からlen bitと p2 から len bit を入れ替える
template<class T>
int bit_swap(T x, size_t p1, size_t p2, size_t len)
{
	T mask = (1ul << len) - 1;
	T ope = (x >> p1 ^ x >> p2) & mask; // 入れ替える場所のxorを求める
	return x ^ (ope << p1 | ope << p2); // 入れ替える場所をxor。
}

//// graph ////

template <class TCost = double>
struct Path
{
	typedef TCost COST;
	int from;
	int to;
	TCost cost;
	Path(int from = 0, int to = 0, TCost cost = 0)
		: from(from), to(to), cost(cost) { }
	bool operator < (const Path &rhs) const { return cost < rhs.cost; }
	bool operator >(const Path &rhs) const { return cost > rhs.cost; }
};

// prim //
template <class COST>
pair<COST, vector<int>> prim(const vector<vector<COST>> &costTable)
{
	typedef Path<COST> P;
	int N = costTable.size();
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(P(0, 0, 0));
	vector<int> parent(N, -1);
	COST totalCost = 0;
	while (!q.empty())
	{
		P cur = q.top(); q.pop();
		int i = cur.to;
		if (parent[i] != -1) continue;
		parent[i] = cur.from;
		totalCost += cur.cost;
		REP(j, N) if (parent[j] == -1) q.push(P(i, j, costTable[i][j]));
	}
	return make_pair(totalCost, parent);
}

// dijkstra //
template <class COST>
pair<vector<COST>, vector<int>> dijkstra(const vector<vector<Path<COST>>> &routes, int start = 0, int goal = -1)
{
	typedef Path<COST> P;
	int N = routes.size();
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(P(start, start, 0));

	vector<int> prev(N, -1);
	vector<COST> cost(N, INF);
	while (!q.empty())
	{
		P cur = q.top(); q.pop();
		int i = cur.to;
		if (prev[i] != -1) continue;
		prev[i] = cur.from;
		cost[i] = cur.cost;
		if (i == goal) { break; }
		REP(j, routes[i].size())
		{
			P next = P(i, routes[i][j].to, cur.cost + routes[i][j].cost);
			if (prev[next.to] == -1)
				q.push(next);
		}
	}
	return make_pair(cost, prev);
}

// warshall_floyd //
template <class COST>
void warshall_floyd(vector<vector<COST>> &cost)
{
	int n = cost.size();
	REP(k, n) REP(i, n) REP(j, n) cost[i][j] = min(cost[i][j], cost[i][k] + cost[k][j]);
}


//// dice ////

// さいころ
template<class T>
struct Die
{
	/* v as 天一地六東五西二南三北四
	|3|
	|1|0|4|5|
	|2|
	*/
	T v[6];

	void rt(int x, int y, int z, int w) { swap(v[x], v[y]); swap(v[x], v[z]); swap(v[x], v[w]); }
	void rotateLeft() { rt(0, 4, 5, 1); }
	void rotateRight() { rt(1, 5, 4, 0); }
	void rotateDown() { rt(0, 3, 5, 2); }
	void rotateUp() { rt(2, 5, 3, 0); }
	void rotateCw() { rt(3, 1, 2, 4); }
	void rotateCcw() { rt(4, 2, 1, 3); }
	bool operator < (const Die &rhs) const { return lexicographical_compare(aallof(v), aallof(rhs.v)); }
	bool operator == (const Die &rhs) const { return equal(aallof(v), rhs.v); }
	bool operator != (const Die &rhs) const { return !equal(aallof(v), rhs.v); }
};

// 8面体
template<class T>
struct Octahedra
{
	/* v as
	/0\/1\/2\/3\
	\4/\5/\6/\7/
	*/
	T v[8];

	void rt(int x, int y, int z, int w) { swap(v[x], v[y]); swap(v[x], v[z]); swap(v[x], v[w]); }
	void rotateLeft() { rt(0, 1, 2, 3); rt(4, 5, 6, 7); }
	void rotateRight() { rt(3, 2, 1, 0); rt(7, 6, 5, 4); }
	void rotateDown() { rt(0, 4, 7, 3); rt(1, 5, 6, 2); }
	void rotateUp() { rt(3, 7, 4, 0); rt(2, 6, 5, 2); }
	void rotateCw() { rt(0, 1, 5, 4); rt(3, 2, 6, 7); }
	void rotateCcw() { rt(4, 5, 1, 0); rt(7, 6, 1, 3); }
	bool operator < (const Octahedra &rhs) const { return lexicographical_compare(aallof(v), aallof(rhs.v)); }
	bool operator == (const Octahedra &rhs) const { return equal(aallof(v), rhs.v); }
	bool operator != (const Octahedra &rhs) const { return !equal(aallof(v), rhs.v); }
};


//// i/o ////
template <class T> class vevector : public vector<vector<T>> {
public: vevector(int n = 0, int m = 0, const T &initial = T()) : vector<vector<T>>(n, vector<T>(m, initial)) { }
};
template <class T> class vevevector : public vector<vevector<T>> {
public: vevevector(int n = 0, int m = 0, int l = 0, const T &initial = T()) : vector<vevector<T>>(n, vevector<T>(m, l, initial)) { }
};
template <class T> class vevevevector : public vector<vevevector<T>> {
public: vevevevector(int n = 0, int m = 0, int l = 0, int k = 0, const T &initial = T()) : vector<vevevector<T>>(n, vevevector<T>(m, l, k, initial)) { }
};

template <class T1, class T2>
inline istream & operator>>(istream & in, pair<T1, T2> &p) { in >> p.first >> p.second; return in; }

template <class T> T read() { T t; cin >> t; return t; }
template <class T> vector<T> read(int n) { vector<T> v; REP(i, n) { v.push_back(read<T>()); } return v; }
template <class T> vevector<T> read(int n, int m) { vevector<T> v; REP(i, n) v.push_back(read<T>(m)); return v; }
template <class T> vevector<T> readjag() { return read<T>(read<int>()); }
template <class T> vevector<T> readjag(int n) { vevector<T> v; REP(i, n) v.push_back(readjag<T>()); return v; }
struct _Reader { template <class T> _Reader operator ,(T &rhs) { cin >> rhs; return *this; } };
#define READ(t,...) t __VA_ARGS__; _Reader(), __VA_ARGS__

template <class T> void write(const T &t) { cout << t << endl; }
template <class T, class T2> void write(const T &t, const T2 &t2) { cout << t; write(t2); }
template <class T> void write(const vector<T> &v)
{
	ostringstream ss;
	for (auto x : v) ss << x << ' ';
	auto s = ss.str();
	cout << s.substr(0, s.length() - 1) << endl;
}


//// start up ////
void solve();
int main()
{
	solve();
	return 0;
}


////////////////////
/// template end ///
////////////////////

void solve()
{
	int testcases = 1;
	REP(testcase, testcases)
	{
		READ(int, sx, sy, gx, gy, n);
		auto furnitures = read<P2>(n);
		READ(int, lx, ly);

		int W = lx * 2 + 1, H = ly * 2 + 1;
		vevector<bool> field(W, H);
		sx += lx; sy += ly;
		gx += lx; gy += ly;
		for (auto f : furnitures) { field[f.x + lx][f.y + ly] = true; }

		// field ok.

		struct R { int x, y, c, t; bool operator > (const R&r) const { return c > r.c; } };
		priority_queue<R, vector<R>, greater<R>> q;
		q.push({ sx, sy, 0, 0, });

		int result = -1;
		vevevector<bool> visited(W, H, 6);
		int dx[2][7] = { { 0, 1, 1, 0, -1, -1, 0 }, { 0, 1, 1, 0, -1, -1, 0 } };
		int dy[2][7] = { { 1, 0, -1, -1, -1, 0, 0 }, { 1, 1, 0, -1, 0, 1, 0 }, };
		while (!q.empty())
		{
			R r = q.top(); q.pop();
			if (visited[r.x][r.y][r.t]) continue;
			visited[r.x][r.y][r.t] = true;

			if (r.x == gx && r.y == gy) { result = r.c; break; }

			REP(i, 7)
			{
				int nx = r.x + dx[r.x - lx & 1][i];
				int ny = r.y + dy[r.x - lx & 1][i];

				if (!contains(nx, ny, W, H)) { continue; }
				if (field[nx][ny]) { continue; }

				int fop = abs((r.x - lx) * (r.y - ly) * r.t) % 6;
				int nc = r.c + (i != fop);
				int nt = (r.t + 1) % 6;
				if (!visited[nx][ny][nt])
				{
					q.push({ nx, ny, nc, nt });
				}
			}
		}
		write(result);
	}
}
### Prompt

Your challenge is to write a CPP solution to the following problem:

The full exploration sister is a very talented woman. Your sister can easily count the number of routes in a grid pattern if it is in the thousands. You and your exploration sister are now in a room lined with hexagonal tiles. The older sister seems to be very excited about the hexagon she sees for the first time. The older sister, who is unfamiliar with expressing the arrangement of hexagons in coordinates, represented the room in the coordinate system shown in Fig. 1.

<image> Figure 1

You want to move from one point on this coordinate system to another. But every minute your sister tells you the direction you want to move. Your usual sister will instruct you to move so that you don't go through locations with the same coordinates. However, an older sister who is unfamiliar with this coordinate system corresponds to the remainder of | x × y × t | (x: x coordinate, y: y coordinate, t: elapsed time [minutes] from the first instruction) divided by 6. Simply indicate the direction (corresponding to the number shown in the figure) and it will guide you in a completely random direction.

<image> Figure 2

If you don't want to hurt your sister, you want to reach your destination while observing your sister's instructions as much as possible. You are allowed to do the following seven actions.

* Move 1 tile to direction 0
* Move 1 tile to direction 1
* Move 1 tile in direction 2
* Move 1 tile in direction 3
* Move 1 tile in direction 4
* Move 1 tile in direction 5
* Stay on the spot



You always do one of these actions immediately after your sister gives instructions. The room is furnished and cannot be moved into the tiles where the furniture is placed. Also, movements where the absolute value of the y coordinate exceeds ly or the absolute value of the x coordinate exceeds lx are not allowed. However, the older sister may instruct such a move. Ignoring instructions means moving in a different direction than your sister indicated, or staying there. Output the minimum number of times you should ignore the instructions to get to your destination. Output -1 if it is not possible to reach your destination.

Constraints

* All inputs are integers
* -lx ≤ sx, gx ≤ lx
* -ly ≤ sy, gy ≤ ly
* (sx, sy) ≠ (gx, gy)
* (xi, yi) ≠ (sx, sy) (1 ≤ i ≤ n)
* (xi, yi) ≠ (gx, gy) (1 ≤ i ≤ n)
* (xi, yi) ≠ (xj, yj) (i ≠ j)
* 0 ≤ n ≤ 1000
* -lx ≤ xi ≤ lx (1 ≤ i ≤ n)
* -ly ≤ yi ≤ ly (1 ≤ i ≤ n)
* 0 <lx, ly ≤ 100

Input

The input is given in the following format.

> sx sy gx gy
> n
> x1 y1
> ...
> xi yi
> ...
> xn yn
> lx ly
>

here,

* sx, sy are the coordinates of the starting point
* gx, gy are the coordinates of the destination
* n is the number of furniture placed in the room
* xi, yi are the coordinates of the tile with furniture
* lx, ly are the upper limits of the absolute values ​​of the movable X and Y coordinates.

Output

Output in one line containing one integer. If you can reach your destination, print the number of times you ignore the minimum instructions. Output -1 if it is not possible to reach your destination.

Examples

Input

0 0 0 2
0
2 2


Output

0


Input

0 0 0 2
6
0 1
1 0
1 -1
0 -1
-1 -1
-1 0
2 2


Output

-1


Input

0 0 0 2
1
0 1
2 2


Output

1

### Response

```cpp
////////////////////////////////////////
///  tu3 pro-con template            ///
////////////////////////////////////////
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <functional>
#include <vector>
#include <queue>
#include <string>
#include <complex>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <regex>
using namespace std;

//// MACRO ////
#define countof(a) (sizeof(a)/sizeof(a[0]))

#define REP(i,n) for (int i = 0; i < (n); i++)
#define RREP(i,n) for (int i = (n)-1; i >= 0; i--)
#define FOR(i,s,n) for (int i = (s); i < (n); i++)
#define RFOR(i,s,n) for (int i = (n)-1; i >= (s); i--)
#define pos(c,i) c.being() + (i)
#define allof(c) c.begin(), c.end()
#define aallof(a) a, countof(a)
#define partof(c,i,n) c.begin() + (i), c.begin() + (i) + (n)
#define apartof(a,i,n) a + (i), a + (i) + (n)
#define long long long

#define EPS 1e-9
#define INF 100000000

#define PREDICATE(t,a) (const t & a) -> bool
#define COMPARISON_T(t) bool(*)(const t &, const t &)
#define COMPARISON(t,a,b) (const t & a, const t & b) -> bool
#define CONVERTER(TSrc,t,TDest) (const TSrc &t)->TDest
//// algorithm ////

// compare
template <class InIt1, class InIt2>
int partial_compare(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2)
{
	return lexicographical_compare(first1, last1, first2, last2) ? -1
		: lexicographical_compare(first2, last2, first1, last1) ? 1
		: 0;
}

// index_of
template <class InIt, class T>
inline int index_of(InIt first1, InIt last1, const T &val)
{
	InIt f = find(first1, last1, val);
	return f != last1 ? distance(f, first1) : -1;
}

// C# BinarySearch風のindex_of
template <class InIt, class T>
inline int bindex_of(InIt first1, InIt last1, const T &val)
{
	auto it = lower_bound(first1, last1, val);
	if (it != last1 && *it == val) { return distance(it, first1); }
	return ~distance(it, first1);
}

// iota vector 
vector<int> iotav(int begin, int end)
{
	vector<int> r(end - begin);
	iota(allof(r), begin);
	return r;
}

// iota イテレータ
struct iotait
{
	int n;
	iotait(int n = 0) : n(n) { }
	iotait &operator ++() { ++n; return *this; }
	int operator *() { return n; }
};

// 文字列の置換
void inplaceReplace(string &target, const string &from, const string &to, bool global = false)
{
	do
	{
		string::size_type pos = target.find(from);
		if (pos == target.npos) { break; }
		target.replace(pos, from.length(), to);
	} while (true);
}

inline bool contains(int x, int min, int max) { return x >= min && x < max; }
inline bool contains(int x, int y, int W, int H) { return x >= 0 && x < W && y >= 0 && y < H; }

// 最大公約数
long gcd(long a, long b) { return b ? gcd(b, a%b) : a; }

// 最小公倍数
long lcm(long a, long b) { return a / gcd(a, b) * b; }

// 拡張ユークリッド互除法
void exgcd(long a, long b, long& x, long& y) {
	if (b != 0) { exgcd(b, a%b, y, x); y -= a / b*x; }
	else { x = 1; y = 0; }
}

//// data structure ////

/// 2分セグメント木。RMQとかが解ける。
template<class T = int, class TParentFunc = const T& (*)(const T&, const T&)>
struct SegTree
{
	int count;
	vector<T> tree;
	TParentFunc parent;

	SegTree(int size, TParentFunc parentBuilder = std::min, T initialFill = INF)
		: count((size | size - 1) + 1)
		, tree(count * 2)
		, parent(parentBuilder)
	{
		fill(partof(tree, count, count), initialFill);
		rebuild();
	}

	// []を使うと更新されないのでrebuildすること。数が少なければupdateの方がよい。
	T& operator[](int i) { return tree[i + count]; }
	void rebuild() { RREP(i, count) { tree[i] = parent(tree[i * 2], tree[i * 2 + 1]); } }

	void update(int index, T value)
	{
		tree[index + count] = value;
		for (int i = (index + count) / 2; i > 0; i /= 2)
			tree[i] = parent(tree[i * 2], tree[i * 2 + 1]);
	}

	T query(int s, int e, int i, int l, int r, T value)
	{
		if (r <= s || e <= l) return value;
		if (s <= l && r <= e) return parent(value, tree[i]);
		value = query(s, e, i * 2, l, (l + r) / 2, value);
		value = query(s, e, i * 2 + 1, (l + r) / 2, r, value);
		return value;
	}

	T query(int start, int count, T initialValue)
	{
		return query(start, start + count, 1, 0, count, initialValue);
	}
};


//// prime ////
vector<unsigned char> isPrime;
vector<int> primes;
void initPrimes(int n)
{
	isPrime = vector<unsigned char>(n + 1, true);
	isPrime[0] = isPrime[1] = false;
	FOR(i, 2, n + 1)
	{
		if (!isPrime[i]) continue;
		primes.push_back(i);
		for (int j = i * 2; j <= n; j += i)
			isPrime[j] = false;
	}
}

//// Probability ////

// パスカルの三角形(二項定理) 2種類の並べ替えにつかう。
vector<vector<double>> makePascalTriangle(int n, bool probability = false)
{
	typedef vector<double> VD;
	vector<VD> t;
	if (!t.size()) { t.push_back(VD(1, 1)); }
	FOR(i, t.size(), n + 1)
	{
		t.push_back(VD(i + 1));
		REP(j, i)
		{
			double x = t[i - 1][j] * (probability ? 0.5 : 1);
			t[i][j] += x;
			t[i][j + 1] += x;
		}
	}
	return t;
}



//// geo ////

/// 3次元
struct P3
{
	double x, y, z;
	P3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) { }
	P3 operator +() const { return *this; }
	P3 operator +(const P3 &_) const { return P3(x + _.x, y + _.y, z + _.z); }
	P3 operator -() const { return P3(-x, -y, -z); }
	P3 operator -(const P3 &_) const { return *this + -_; }
	P3 operator *(double _) const { return P3(x*_, y*_, z*_); }
	P3 operator /(double _) const { return P3(x / _, y / _, z / _); }
	double dot(const P3 &_) const { return x*_.x + y*_.y + z*_.z; } // 内積
	P3 cross(const P3 &_) const { return P3(y*_.z - z*_.y, z*_.x - x*_.z, x*_.y - y*_.x); } // 外積
	double sqlength() const { return x*x + y*y + z*z; } // 二乗長さ
	double length() const { return sqrt(sqlength()); } // 長さ
	P3 direction() const { return *this / length(); } // 方向ベクトル
};
inline istream & operator>>(istream & in, P3 & p) { in >> p.x >> p.y >> p.z; return in; }
inline double abs(P3 p) { return p.length(); }

struct Sphere
{
	P3 c;
	double r;
	Sphere(double x, double y, double z, double r) : c(x, y, z), r(r) { }
	Sphere(P3 c, double r) : c(c), r(r) { }
	bool IntersectWith(const Sphere &rhs) const { return abs(c - rhs.c) - (r + rhs.r) < EPS; } // 接してても真。
};
inline istream & operator>>(istream & in, Sphere & c) { in >> c.c >> c.r; return in; }

/// 2次元
struct P2
{
	double x, y;
	P2(double x = 0, double y = 0) : x(x), y(y) { }
	P2(complex<double> c) : x(c.real()), y(c.imag()) { }
	P2 operator +() const { return *this; }
	P2 operator +(const P2 &_) const { return P2(x + _.x, y + _.y); }
	P2 operator -() const { return P2(-x, -y); }
	P2 operator -(const P2 &_) const { return *this + -_; }
	P2 operator *(double _) const { return P2(x*_, y*_); }
	P2 operator /(double _) const { return P2(x / _, y / _); }
	double dot(const P2 &_) const { return x*_.x + y*_.y; } // 内積
	double cross(const P2 &_) const { return x*_.y - y*_.x; } // 外積
	double sqlength() const { return x*x + y*y; } // 二乗長さ
	double length() const { return sqrt(sqlength()); } // 長さ
	P2 orthogonal() const { return P2(y, -x); }
	P2 direction() const { return *this / length(); } // 方向ベクトル
};
inline istream & operator>>(istream & in, P2 & p) { in >> p.x >> p.y; return in; }
inline ostream & operator<<(ostream & out, const P2 & p) { out << p.x << ' ' << p.y; return out; }
inline double abs(P2 p2) { return p2.length(); }
inline P2 orthogonal(P2 p) { return p.orthogonal(); }
inline complex<double> orthogonal(complex<double> c) { return  c * complex<double>(0, 1); }

// a,b から ちょうど d だけ離れた点。aとbを円周に持つ円の半径。
inline pair<P2, P2> get_same_distance_points(P2 a, P2 b, double d)
{
	assert(abs(a - b) <= 2 * d + EPS);
	auto v = (a + b) / 2.0 - a; // a から aとbの中点
	auto vl = abs(v);
	auto wl = sqrt(d*d - vl*vl); // 直行Vの大きさ
	auto w = orthogonal(v) * (wl / vl); // 直行V
	return make_pair(a + v + w, a + v - w);
}

struct Circle
{
	P2 c;
	double r;
	Circle() : c(), r() { }
	Circle(double x, double y, double r) : c(x, y), r(r) { }
	Circle(P2 c, double r) : c(c), r(r) { }
	bool IntersectWith(const Circle &rhs) const { return abs(c - rhs.c) - (r + rhs.r) < EPS; } // 接してても真。
	bool Contains(const P2 &p) const { return abs(p - c) - r < EPS; } // 接してても真。
};
inline istream & operator>>(istream & in, Circle & c) { in >> c.c >> c.r; return in; }

// 交差している2円の交点を求める。角度の小さい方から出る(右下方向が正なら時計回り)
inline pair<P2, P2> crossPoint(Circle A, Circle B)
{
	P2 v = B.c - A.c;
	P2 dir = v.direction(); // 他方の中心への方向
	double d = v.length(); // 他方の中心への距離
	double lh = (A.r*A.r + d*d - B.r*B.r) / (2 * d); // 垂線の足までの距離
	P2 h = A.c + dir * lh; // 垂線の足
	double lp = sqrt(A.r*A.r - lh*lh); // 垂線の足から交点までの距離
	P2 p = dir.orthogonal() * lp; // 垂線の足から交点へのベクトル
	return make_pair(h + p, h - p); // 交点の組。
}

inline int clockwise(P2 a, P2 b, P2 c)
{
	const P2 u = b - a, v = c - a;
	if (u.cross(v) > EPS) { return 1; }
	if (u.cross(v) < -EPS) { return -1; }
	if (u.dot(v) < -EPS) { return -1; }
	if (abs(u) - abs(v) < EPS) { return 1; }
	return 0;
}

//// bit ////
#ifdef _MSC_VER
#pragma push_macro("long")
#undef long
inline unsigned __builtin_ctz(unsigned x) { unsigned long r; _BitScanForward(&r, x); return r; }
#  define __builtin_popcount __popcnt
#pragma pop_macro("long")
#endif

inline int next_bit_permutation(int x)
{
	int t = x | (x - 1);
	return (t + 1) | (unsigned)((~t & -~t) - 1) >> (__builtin_ctz(x) + 1);
}

// x の p1からlen bitと p2 から len bit を入れ替える
template<class T>
int bit_swap(T x, size_t p1, size_t p2, size_t len)
{
	T mask = (1ul << len) - 1;
	T ope = (x >> p1 ^ x >> p2) & mask; // 入れ替える場所のxorを求める
	return x ^ (ope << p1 | ope << p2); // 入れ替える場所をxor。
}

//// graph ////

template <class TCost = double>
struct Path
{
	typedef TCost COST;
	int from;
	int to;
	TCost cost;
	Path(int from = 0, int to = 0, TCost cost = 0)
		: from(from), to(to), cost(cost) { }
	bool operator < (const Path &rhs) const { return cost < rhs.cost; }
	bool operator >(const Path &rhs) const { return cost > rhs.cost; }
};

// prim //
template <class COST>
pair<COST, vector<int>> prim(const vector<vector<COST>> &costTable)
{
	typedef Path<COST> P;
	int N = costTable.size();
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(P(0, 0, 0));
	vector<int> parent(N, -1);
	COST totalCost = 0;
	while (!q.empty())
	{
		P cur = q.top(); q.pop();
		int i = cur.to;
		if (parent[i] != -1) continue;
		parent[i] = cur.from;
		totalCost += cur.cost;
		REP(j, N) if (parent[j] == -1) q.push(P(i, j, costTable[i][j]));
	}
	return make_pair(totalCost, parent);
}

// dijkstra //
template <class COST>
pair<vector<COST>, vector<int>> dijkstra(const vector<vector<Path<COST>>> &routes, int start = 0, int goal = -1)
{
	typedef Path<COST> P;
	int N = routes.size();
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(P(start, start, 0));

	vector<int> prev(N, -1);
	vector<COST> cost(N, INF);
	while (!q.empty())
	{
		P cur = q.top(); q.pop();
		int i = cur.to;
		if (prev[i] != -1) continue;
		prev[i] = cur.from;
		cost[i] = cur.cost;
		if (i == goal) { break; }
		REP(j, routes[i].size())
		{
			P next = P(i, routes[i][j].to, cur.cost + routes[i][j].cost);
			if (prev[next.to] == -1)
				q.push(next);
		}
	}
	return make_pair(cost, prev);
}

// warshall_floyd //
template <class COST>
void warshall_floyd(vector<vector<COST>> &cost)
{
	int n = cost.size();
	REP(k, n) REP(i, n) REP(j, n) cost[i][j] = min(cost[i][j], cost[i][k] + cost[k][j]);
}


//// dice ////

// さいころ
template<class T>
struct Die
{
	/* v as 天一地六東五西二南三北四
	|3|
	|1|0|4|5|
	|2|
	*/
	T v[6];

	void rt(int x, int y, int z, int w) { swap(v[x], v[y]); swap(v[x], v[z]); swap(v[x], v[w]); }
	void rotateLeft() { rt(0, 4, 5, 1); }
	void rotateRight() { rt(1, 5, 4, 0); }
	void rotateDown() { rt(0, 3, 5, 2); }
	void rotateUp() { rt(2, 5, 3, 0); }
	void rotateCw() { rt(3, 1, 2, 4); }
	void rotateCcw() { rt(4, 2, 1, 3); }
	bool operator < (const Die &rhs) const { return lexicographical_compare(aallof(v), aallof(rhs.v)); }
	bool operator == (const Die &rhs) const { return equal(aallof(v), rhs.v); }
	bool operator != (const Die &rhs) const { return !equal(aallof(v), rhs.v); }
};

// 8面体
template<class T>
struct Octahedra
{
	/* v as
	/0\/1\/2\/3\
	\4/\5/\6/\7/
	*/
	T v[8];

	void rt(int x, int y, int z, int w) { swap(v[x], v[y]); swap(v[x], v[z]); swap(v[x], v[w]); }
	void rotateLeft() { rt(0, 1, 2, 3); rt(4, 5, 6, 7); }
	void rotateRight() { rt(3, 2, 1, 0); rt(7, 6, 5, 4); }
	void rotateDown() { rt(0, 4, 7, 3); rt(1, 5, 6, 2); }
	void rotateUp() { rt(3, 7, 4, 0); rt(2, 6, 5, 2); }
	void rotateCw() { rt(0, 1, 5, 4); rt(3, 2, 6, 7); }
	void rotateCcw() { rt(4, 5, 1, 0); rt(7, 6, 1, 3); }
	bool operator < (const Octahedra &rhs) const { return lexicographical_compare(aallof(v), aallof(rhs.v)); }
	bool operator == (const Octahedra &rhs) const { return equal(aallof(v), rhs.v); }
	bool operator != (const Octahedra &rhs) const { return !equal(aallof(v), rhs.v); }
};


//// i/o ////
template <class T> class vevector : public vector<vector<T>> {
public: vevector(int n = 0, int m = 0, const T &initial = T()) : vector<vector<T>>(n, vector<T>(m, initial)) { }
};
template <class T> class vevevector : public vector<vevector<T>> {
public: vevevector(int n = 0, int m = 0, int l = 0, const T &initial = T()) : vector<vevector<T>>(n, vevector<T>(m, l, initial)) { }
};
template <class T> class vevevevector : public vector<vevevector<T>> {
public: vevevevector(int n = 0, int m = 0, int l = 0, int k = 0, const T &initial = T()) : vector<vevevector<T>>(n, vevevector<T>(m, l, k, initial)) { }
};

template <class T1, class T2>
inline istream & operator>>(istream & in, pair<T1, T2> &p) { in >> p.first >> p.second; return in; }

template <class T> T read() { T t; cin >> t; return t; }
template <class T> vector<T> read(int n) { vector<T> v; REP(i, n) { v.push_back(read<T>()); } return v; }
template <class T> vevector<T> read(int n, int m) { vevector<T> v; REP(i, n) v.push_back(read<T>(m)); return v; }
template <class T> vevector<T> readjag() { return read<T>(read<int>()); }
template <class T> vevector<T> readjag(int n) { vevector<T> v; REP(i, n) v.push_back(readjag<T>()); return v; }
struct _Reader { template <class T> _Reader operator ,(T &rhs) { cin >> rhs; return *this; } };
#define READ(t,...) t __VA_ARGS__; _Reader(), __VA_ARGS__

template <class T> void write(const T &t) { cout << t << endl; }
template <class T, class T2> void write(const T &t, const T2 &t2) { cout << t; write(t2); }
template <class T> void write(const vector<T> &v)
{
	ostringstream ss;
	for (auto x : v) ss << x << ' ';
	auto s = ss.str();
	cout << s.substr(0, s.length() - 1) << endl;
}


//// start up ////
void solve();
int main()
{
	solve();
	return 0;
}


////////////////////
/// template end ///
////////////////////

void solve()
{
	int testcases = 1;
	REP(testcase, testcases)
	{
		READ(int, sx, sy, gx, gy, n);
		auto furnitures = read<P2>(n);
		READ(int, lx, ly);

		int W = lx * 2 + 1, H = ly * 2 + 1;
		vevector<bool> field(W, H);
		sx += lx; sy += ly;
		gx += lx; gy += ly;
		for (auto f : furnitures) { field[f.x + lx][f.y + ly] = true; }

		// field ok.

		struct R { int x, y, c, t; bool operator > (const R&r) const { return c > r.c; } };
		priority_queue<R, vector<R>, greater<R>> q;
		q.push({ sx, sy, 0, 0, });

		int result = -1;
		vevevector<bool> visited(W, H, 6);
		int dx[2][7] = { { 0, 1, 1, 0, -1, -1, 0 }, { 0, 1, 1, 0, -1, -1, 0 } };
		int dy[2][7] = { { 1, 0, -1, -1, -1, 0, 0 }, { 1, 1, 0, -1, 0, 1, 0 }, };
		while (!q.empty())
		{
			R r = q.top(); q.pop();
			if (visited[r.x][r.y][r.t]) continue;
			visited[r.x][r.y][r.t] = true;

			if (r.x == gx && r.y == gy) { result = r.c; break; }

			REP(i, 7)
			{
				int nx = r.x + dx[r.x - lx & 1][i];
				int ny = r.y + dy[r.x - lx & 1][i];

				if (!contains(nx, ny, W, H)) { continue; }
				if (field[nx][ny]) { continue; }

				int fop = abs((r.x - lx) * (r.y - ly) * r.t) % 6;
				int nc = r.c + (i != fop);
				int nt = (r.t + 1) % 6;
				if (!visited[nx][ny][nt])
				{
					q.push({ nx, ny, nc, nt });
				}
			}
		}
		write(result);
	}
}
```