#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
void fileIO()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
freopen("raydist.in", "r", stdin);
freopen("raydist.out", "w", stdout);
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
}
typedef double T;
typedef complex<T> pt;
#define x real()
#define y imag()
#define vec(a, b) (pt)(b - a)
#define M_PI 3.14159265358979323846
#define eps 1e-9
#define dot(a, b) ((conj(a) * (b)).real())
#define cross(a, b) ((conj(a) * (b)).imag())
#define perp(p) \
(pt) { -p.y, p.x } // the rotation by 90◦
#define sq(a) a.x *a.x + a.y *a.y
#define orient(a, b, c) cross(b - a, c - a)
struct Line
{
pt v;
T c;
// from vector and offset
Line(pt v, T c) : v(v), c(c) {}
// ax + by = c
Line(T a, T b, T c) : v({-b, a}), c(c) {}
// from two points
Line(pt a, pt b) : v(b - a), c(cross(v, a)) {}
// left if positive, right if negative, on the line otherwise
T side(pt p) { return cross(v, p) - c; }
// distance from p to the line
double dist(pt p) { return abs(side(p)) / abs(v); }
double sqDist(pt p) { return side(p) * side(p) / (double)sq(v); }
Line perpThrough(pt p) { return {p, p + perp(v)}; }
// sort points on line
bool cmpProj(pt p, pt q) { return dot(v, p) < dot(v, q); }
// translate a line by direction vector t, only c changes
Line translate(pt t) { return {v, c + cross(v, t)}; }
// shift the line left by distance dist, direction vector t is (dist / abs(v)) * perp(v)
Line shiftLeft(double dist) { return {v, c + dist * abs(v)}; }
// intersection point between two lines
bool inter(Line l, pt &out)
{
T d = cross(v, l.v);
if (d == 0)
return false;
out = (l.v * c - v * l.c) / d; // requires floating-point coordinates
return true;
}
// projection of a point P on a line l is the point on l that is closest to P.
pt proj(pt p) { return p - perp(v) * side(p) / sq(v); }
// The reflection of point P by line l is the point on the other side of l that is at the same distance and has the same orthogonal projection.
pt refl(pt p) { return p - perp(v) * (2.0 * side(p) / sq(v)); }
/*
l_ext(l1,l2)▲
│
│
│ l2
xx │ xxxxxxxx
xxxx │ xxxxxxx
xxx │ xxxxxx
xxx │ xxx x
xx │ xxx
xxx │ xxx l_int(l1,l2)
─────────────────xxxxx─────────────────►
xxxxxxxxx
xxx │ xx
xxx │ xxx
xxx │ xxxx xx
│ xxxxxxx
│ xxxxxxx
│ xxxxxxxxxx
│ xxxxxxxxxxx
l1
*/
Line bisector(Line l, bool interior)
{
assert(cross(v, l.v) != 0); // l1 and l2 cannot be parallel!
double sign = interior ? 1 : -1;
return {l.v / abs(l.v) + v / abs(v) * sign,
l.c / abs(l.v) + c / abs(v) * sign};
}
};
// checks if a point lies on disk formed by diameter [a,b]
static bool inDisk(pt a, pt b, pt p) { return dot(a - p, b - p) <= 0; }
// check if point is on the segment [a,b]
static bool onSegment(pt a, pt b, pt p) { return orient(a, b, p) == 0 && inDisk(a, b, p); }
// one point intersection of two segments
bool properInter(pt a, pt b, pt c, pt d, pt &out)
{
double oa = orient(c, d, a),
ob = orient(c, d, b),
oc = orient(a, b, c),
od = orient(a, b, d);
// Proper intersection exists if opposite signs
if (oa * ob < 0 && oc * od < 0)
{
out = (a * ob - b * oa) / (ob - oa);
return true;
}
return false;
}
// comparable to create set of points
struct cmpX
{
bool operator()(pt a, pt b) const
{
return make_pair(a.x, a.y) < make_pair(b.x, b.y);
}
};
// the intersection between two points
set<pt, cmpX> intersections(pt a, pt b, pt c, pt d)
{
pt out;
if (properInter(a, b, c, d, out))
return {out}; // only one intersection
set<pt, cmpX> s;
if (onSegment(c, d, a))
s.insert(a);
if (onSegment(c, d, b))
s.insert(b);
if (onSegment(a, b, c))
s.insert(c);
if (onSegment(a, b, d))
s.insert(d);
return s;
}
double segmentPointDistance(pt a, pt b, pt p)
{
if (a != b)
{
Line l(a, b);
if (l.cmpProj(a, p) && l.cmpProj(p, b)) // if closest to projection
return l.dist(p); // output distance to Line
}
return min(abs(p - a), abs(p - b)); // otherwise distance to A or B
}
double segmentSegmentDistance(pt a, pt b, pt c, pt d)
{
pt dummy;
if (properInter(a, b, c, d, dummy))
return 0;
return min({segmentPointDistance(a, b, c), segmentPointDistance(a, b, d),
segmentPointDistance(c, d, a), segmentPointDistance(c, d, b)});
}
double rayPointDistance(pt a, pt b, pt p)
{
if (a != b)
{
Line l(a, b);
if (l.cmpProj(a, p)) // if closest to projection
return l.dist(p); // output distance to Line
}
return abs(p - a); // otherwise distance to A
}
bool intersectSegments(pt a, pt b, pt c, pt d, pt &intersect)
{
double d1 = cross(vec(b, a), vec(c, d)), d2 = cross(vec(c, a), vec(c, d)), d3 = cross(vec(b, a), vec(c, a));
if (fabs(d1) < eps)
return false; /// parllel or identical
double t1 = d2 / d1, t2 = d3 / d1;
intersect = a + (b - a) * t1;
/// segment: [0, 1]
/// ray: [0, INF]
/// line: [-INF, INF]
/// make sure that eps is not too accurate
if (t1 < -eps or t2 < -eps)
return false;
return true;
}
double rayRayDistance(pt a, pt b, pt c, pt d)
{
pt dummy;
if (intersectSegments(a, b, c, d, dummy))
return 0;
return min(rayPointDistance(a, b, c), rayPointDistance(c, d, a));
}
void Striker()
{
int a, b;
cin >> a >> b;
pt p1(a, b);
cin >> a >> b;
pt p2(a, b);
cin >> a >> b;
pt p3(a, b);
cin >> a >> b;
pt p4(a, b);
cout << fixed << setprecision(12) << rayRayDistance(p1, p2, p3, p4);
}
signed main()
{
fileIO();
int _t = 1;
// cin >> _t;
for (int i = 0; i < _t; ++i)
{
Striker();
}
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgojZGVmaW5lIGxsIGxvbmcgbG9uZwojZGVmaW5lIGRvdWJsZSBsb25nIGRvdWJsZQp2b2lkIGZpbGVJTygpCnsKICAgIGlvc19iYXNlOjpzeW5jX3dpdGhfc3RkaW8oMCk7CiAgICBjaW4udGllKDApOwogICAgY291dC50aWUoMCk7CiAgICBmcmVvcGVuKCJyYXlkaXN0LmluIiwgInIiLCBzdGRpbik7CiAgICBmcmVvcGVuKCJyYXlkaXN0Lm91dCIsICJ3Iiwgc3Rkb3V0KTsKI2lmbmRlZiBPTkxJTkVfSlVER0UKICAgIGZyZW9wZW4oImlucHV0LnR4dCIsICJyIiwgc3RkaW4pOwogICAgZnJlb3Blbigib3V0cHV0LnR4dCIsICJ3Iiwgc3Rkb3V0KTsKI2VuZGlmCn0KCnR5cGVkZWYgZG91YmxlIFQ7CnR5cGVkZWYgY29tcGxleDxUPiBwdDsKI2RlZmluZSB4IHJlYWwoKQojZGVmaW5lIHkgaW1hZygpCiNkZWZpbmUgdmVjKGEsIGIpIChwdCkoYiAtIGEpCiNkZWZpbmUgTV9QSSAzLjE0MTU5MjY1MzU4OTc5MzIzODQ2CiNkZWZpbmUgZXBzIDFlLTkKI2RlZmluZSBkb3QoYSwgYikgKChjb25qKGEpICogKGIpKS5yZWFsKCkpCiNkZWZpbmUgY3Jvc3MoYSwgYikgKChjb25qKGEpICogKGIpKS5pbWFnKCkpCiNkZWZpbmUgcGVycChwKSBcCiAgICAocHQpIHsgLXAueSwgcC54IH0gLy8gdGhlIHJvdGF0aW9uIGJ5IDkw4pemCiNkZWZpbmUgc3EoYSkgYS54ICphLnggKyBhLnkgKmEueQojZGVmaW5lIG9yaWVudChhLCBiLCBjKSBjcm9zcyhiIC0gYSwgYyAtIGEpCnN0cnVjdCBMaW5lCnsKICAgIHB0IHY7CiAgICBUIGM7CgogICAgLy8gZnJvbSB2ZWN0b3IgYW5kIG9mZnNldAogICAgTGluZShwdCB2LCBUIGMpIDogdih2KSwgYyhjKSB7fQogICAgLy8gYXggKyBieSA9IGMKICAgIExpbmUoVCBhLCBUIGIsIFQgYykgOiB2KHstYiwgYX0pLCBjKGMpIHt9CiAgICAvLyBmcm9tIHR3byBwb2ludHMKICAgIExpbmUocHQgYSwgcHQgYikgOiB2KGIgLSBhKSwgYyhjcm9zcyh2LCBhKSkge30KICAgIC8vIGxlZnQgaWYgcG9zaXRpdmUsIHJpZ2h0IGlmIG5lZ2F0aXZlLCBvbiB0aGUgbGluZSBvdGhlcndpc2UKICAgIFQgc2lkZShwdCBwKSB7IHJldHVybiBjcm9zcyh2LCBwKSAtIGM7IH0KICAgIC8vIGRpc3RhbmNlIGZyb20gcCB0byB0aGUgbGluZQogICAgZG91YmxlIGRpc3QocHQgcCkgeyByZXR1cm4gYWJzKHNpZGUocCkpIC8gYWJzKHYpOyB9CiAgICBkb3VibGUgc3FEaXN0KHB0IHApIHsgcmV0dXJuIHNpZGUocCkgKiBzaWRlKHApIC8gKGRvdWJsZSlzcSh2KTsgfQogICAgTGluZSBwZXJwVGhyb3VnaChwdCBwKSB7IHJldHVybiB7cCwgcCArIHBlcnAodil9OyB9CiAgICAvLyBzb3J0IHBvaW50cyBvbiBsaW5lCiAgICBib29sIGNtcFByb2oocHQgcCwgcHQgcSkgeyByZXR1cm4gZG90KHYsIHApIDwgZG90KHYsIHEpOyB9CiAgICAvLyB0cmFuc2xhdGUgYSBsaW5lIGJ5IGRpcmVjdGlvbiB2ZWN0b3IgdCwgb25seSBjIGNoYW5nZXMKICAgIExpbmUgdHJhbnNsYXRlKHB0IHQpIHsgcmV0dXJuIHt2LCBjICsgY3Jvc3ModiwgdCl9OyB9CiAgICAvLyBzaGlmdCB0aGUgbGluZSBsZWZ0IGJ5IGRpc3RhbmNlIGRpc3QsIGRpcmVjdGlvbiB2ZWN0b3IgdCBpcyAoZGlzdCAvIGFicyh2KSkgKiBwZXJwKHYpCiAgICBMaW5lIHNoaWZ0TGVmdChkb3VibGUgZGlzdCkgeyByZXR1cm4ge3YsIGMgKyBkaXN0ICogYWJzKHYpfTsgfQogICAgLy8gaW50ZXJzZWN0aW9uIHBvaW50IGJldHdlZW4gdHdvIGxpbmVzCiAgICBib29sIGludGVyKExpbmUgbCwgcHQgJm91dCkKICAgIHsKICAgICAgICBUIGQgPSBjcm9zcyh2LCBsLnYpOwogICAgICAgIGlmIChkID09IDApCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICBvdXQgPSAobC52ICogYyAtIHYgKiBsLmMpIC8gZDsgLy8gcmVxdWlyZXMgZmxvYXRpbmctcG9pbnQgY29vcmRpbmF0ZXMKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIC8vIHByb2plY3Rpb24gb2YgYSBwb2ludCBQIG9uIGEgbGluZSBsIGlzIHRoZSBwb2ludCBvbiBsIHRoYXQgaXMgY2xvc2VzdCB0byBQLgogICAgcHQgcHJvaihwdCBwKSB7IHJldHVybiBwIC0gcGVycCh2KSAqIHNpZGUocCkgLyBzcSh2KTsgfQogICAgLy8gVGhlIHJlZmxlY3Rpb24gb2YgcG9pbnQgUCBieSBsaW5lIGwgaXMgdGhlIHBvaW50IG9uIHRoZSBvdGhlciBzaWRlIG9mIGwgdGhhdCBpcyBhdCB0aGUgc2FtZSBkaXN0YW5jZSBhbmQgaGFzIHRoZSBzYW1lIG9ydGhvZ29uYWwgcHJvamVjdGlvbi4KICAgIHB0IHJlZmwocHQgcCkgeyByZXR1cm4gcCAtIHBlcnAodikgKiAoMi4wICogc2lkZShwKSAvIHNxKHYpKTsgfQoKICAgIC8qCiAgICAgICAgbF9leHQobDEsbDIp4payCiAgICAgICAgICAgICAgICAgICDilIIKICAgICAgICAgICAgICAgICAgIOKUggogICAgICAgICAgICAgICAgICAg4pSCICAgICAgICAgICAgICAgbDIKICAgICB4eCAgICAgICAgICAgIOKUgiAgICAgICAgeHh4eHh4eHgKICAgICAgeHh4eCAgICAgICAgIOKUgiAgICAgICAgeHh4eHh4eAogICAgICAgICAgeHh4ICAgICAg4pSCICAgICAgICB4eHh4eHgKICAgICAgICAgICAgeHh4ICAgIOKUgiAgICAgeHh4ICAgeAogICAgICAgICAgICAgIHh4ICAg4pSCICAgeHh4CiAgICAgICAgICAgICAgIHh4eCDilIIgeHh4ICAgICAgICAgICAgICAgICBsX2ludChsMSxsMikK4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAeHh4eHjilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilroKICAgICAgICAgICAgICAgeHh4eHh4eHh4CiAgICAgICAgICAgICB4eHggICDilIIgICAgeHgKICAgICAgICAgICB4eHggICAgIOKUgiAgICAgIHh4eAogICAgICAgICB4eHggICAgICAg4pSCICAgICAgICB4eHh4ICAgeHgKICAgICAgICAgICAgICAgICAgIOKUgiAgICAgICAgICAgeHh4eHh4eAogICAgICAgICAgICAgICAgICAg4pSCICAgICAgICAgICAgeHh4eHh4eAogICAgICAgICAgICAgICAgICAg4pSCICAgICAgICAgIHh4eHh4eHh4eHgKICAgICAgICAgICAgICAgICAgIOKUgiAgICAgICAgICB4eHh4eHh4eHh4eAoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbDEKICAgICovCgogICAgTGluZSBiaXNlY3RvcihMaW5lIGwsIGJvb2wgaW50ZXJpb3IpCiAgICB7CiAgICAgICAgYXNzZXJ0KGNyb3NzKHYsIGwudikgIT0gMCk7IC8vIGwxIGFuZCBsMiBjYW5ub3QgYmUgcGFyYWxsZWwhCiAgICAgICAgZG91YmxlIHNpZ24gPSBpbnRlcmlvciA/IDEgOiAtMTsKICAgICAgICByZXR1cm4ge2wudiAvIGFicyhsLnYpICsgdiAvIGFicyh2KSAqIHNpZ24sCiAgICAgICAgICAgICAgICBsLmMgLyBhYnMobC52KSArIGMgLyBhYnModikgKiBzaWdufTsKICAgIH0KfTsKCi8vIGNoZWNrcyBpZiBhIHBvaW50IGxpZXMgb24gZGlzayBmb3JtZWQgYnkgZGlhbWV0ZXIgW2EsYl0Kc3RhdGljIGJvb2wgaW5EaXNrKHB0IGEsIHB0IGIsIHB0IHApIHsgcmV0dXJuIGRvdChhIC0gcCwgYiAtIHApIDw9IDA7IH0KLy8gY2hlY2sgaWYgcG9pbnQgaXMgb24gdGhlIHNlZ21lbnQgW2EsYl0Kc3RhdGljIGJvb2wgb25TZWdtZW50KHB0IGEsIHB0IGIsIHB0IHApIHsgcmV0dXJuIG9yaWVudChhLCBiLCBwKSA9PSAwICYmIGluRGlzayhhLCBiLCBwKTsgfQoKLy8gb25lIHBvaW50IGludGVyc2VjdGlvbiBvZiB0d28gc2VnbWVudHMKYm9vbCBwcm9wZXJJbnRlcihwdCBhLCBwdCBiLCBwdCBjLCBwdCBkLCBwdCAmb3V0KQp7CiAgICBkb3VibGUgb2EgPSBvcmllbnQoYywgZCwgYSksCiAgICAgICAgICAgb2IgPSBvcmllbnQoYywgZCwgYiksCiAgICAgICAgICAgb2MgPSBvcmllbnQoYSwgYiwgYyksCiAgICAgICAgICAgb2QgPSBvcmllbnQoYSwgYiwgZCk7CiAgICAvLyBQcm9wZXIgaW50ZXJzZWN0aW9uIGV4aXN0cyBpZiBvcHBvc2l0ZSBzaWducwogICAgaWYgKG9hICogb2IgPCAwICYmIG9jICogb2QgPCAwKQogICAgewogICAgICAgIG91dCA9IChhICogb2IgLSBiICogb2EpIC8gKG9iIC0gb2EpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwp9CgovLyBjb21wYXJhYmxlIHRvIGNyZWF0ZSBzZXQgb2YgcG9pbnRzCnN0cnVjdCBjbXBYCnsKICAgIGJvb2wgb3BlcmF0b3IoKShwdCBhLCBwdCBiKSBjb25zdAogICAgewogICAgICAgIHJldHVybiBtYWtlX3BhaXIoYS54LCBhLnkpIDwgbWFrZV9wYWlyKGIueCwgYi55KTsKICAgIH0KfTsKCi8vIHRoZSBpbnRlcnNlY3Rpb24gYmV0d2VlbiB0d28gcG9pbnRzCnNldDxwdCwgY21wWD4gaW50ZXJzZWN0aW9ucyhwdCBhLCBwdCBiLCBwdCBjLCBwdCBkKQp7CiAgICBwdCBvdXQ7CiAgICBpZiAocHJvcGVySW50ZXIoYSwgYiwgYywgZCwgb3V0KSkKICAgICAgICByZXR1cm4ge291dH07IC8vIG9ubHkgb25lIGludGVyc2VjdGlvbgogICAgc2V0PHB0LCBjbXBYPiBzOwogICAgaWYgKG9uU2VnbWVudChjLCBkLCBhKSkKICAgICAgICBzLmluc2VydChhKTsKICAgIGlmIChvblNlZ21lbnQoYywgZCwgYikpCiAgICAgICAgcy5pbnNlcnQoYik7CiAgICBpZiAob25TZWdtZW50KGEsIGIsIGMpKQogICAgICAgIHMuaW5zZXJ0KGMpOwogICAgaWYgKG9uU2VnbWVudChhLCBiLCBkKSkKICAgICAgICBzLmluc2VydChkKTsKICAgIHJldHVybiBzOwp9Cgpkb3VibGUgc2VnbWVudFBvaW50RGlzdGFuY2UocHQgYSwgcHQgYiwgcHQgcCkKewogICAgaWYgKGEgIT0gYikKICAgIHsKICAgICAgICBMaW5lIGwoYSwgYik7CiAgICAgICAgaWYgKGwuY21wUHJvaihhLCBwKSAmJiBsLmNtcFByb2oocCwgYikpIC8vIGlmIGNsb3Nlc3QgdG8gcHJvamVjdGlvbgogICAgICAgICAgICByZXR1cm4gbC5kaXN0KHApOyAgICAgICAgICAgICAgICAgICAvLyBvdXRwdXQgZGlzdGFuY2UgdG8gTGluZQogICAgfQogICAgcmV0dXJuIG1pbihhYnMocCAtIGEpLCBhYnMocCAtIGIpKTsgLy8gb3RoZXJ3aXNlIGRpc3RhbmNlIHRvIEEgb3IgQgp9Cgpkb3VibGUgc2VnbWVudFNlZ21lbnREaXN0YW5jZShwdCBhLCBwdCBiLCBwdCBjLCBwdCBkKQp7CiAgICBwdCBkdW1teTsKICAgIGlmIChwcm9wZXJJbnRlcihhLCBiLCBjLCBkLCBkdW1teSkpCiAgICAgICAgcmV0dXJuIDA7CiAgICByZXR1cm4gbWluKHtzZWdtZW50UG9pbnREaXN0YW5jZShhLCBiLCBjKSwgc2VnbWVudFBvaW50RGlzdGFuY2UoYSwgYiwgZCksCiAgICAgICAgICAgICAgICBzZWdtZW50UG9pbnREaXN0YW5jZShjLCBkLCBhKSwgc2VnbWVudFBvaW50RGlzdGFuY2UoYywgZCwgYil9KTsKfQpkb3VibGUgcmF5UG9pbnREaXN0YW5jZShwdCBhLCBwdCBiLCBwdCBwKQp7CiAgICBpZiAoYSAhPSBiKQogICAgewogICAgICAgIExpbmUgbChhLCBiKTsKICAgICAgICBpZiAobC5jbXBQcm9qKGEsIHApKSAgLy8gaWYgY2xvc2VzdCB0byBwcm9qZWN0aW9uCiAgICAgICAgICAgIHJldHVybiBsLmRpc3QocCk7IC8vIG91dHB1dCBkaXN0YW5jZSB0byBMaW5lCiAgICB9CiAgICByZXR1cm4gYWJzKHAgLSBhKTsgLy8gb3RoZXJ3aXNlIGRpc3RhbmNlIHRvIEEKfQoKYm9vbCBpbnRlcnNlY3RTZWdtZW50cyhwdCBhLCBwdCBiLCBwdCBjLCBwdCBkLCBwdCAmaW50ZXJzZWN0KQp7CiAgICBkb3VibGUgZDEgPSBjcm9zcyh2ZWMoYiwgYSksIHZlYyhjLCBkKSksIGQyID0gY3Jvc3ModmVjKGMsIGEpLCB2ZWMoYywgZCkpLCBkMyA9IGNyb3NzKHZlYyhiLCBhKSwgdmVjKGMsIGEpKTsKCiAgICBpZiAoZmFicyhkMSkgPCBlcHMpCiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLy8gcGFybGxlbCBvciBpZGVudGljYWwKCiAgICBkb3VibGUgdDEgPSBkMiAvIGQxLCB0MiA9IGQzIC8gZDE7CiAgICBpbnRlcnNlY3QgPSBhICsgKGIgLSBhKSAqIHQxOwoKICAgIC8vLyBzZWdtZW50OiBbMCwgMV0KICAgIC8vLyByYXk6IFswLCBJTkZdCiAgICAvLy8gbGluZTogWy1JTkYsIElORl0KCiAgICAvLy8gbWFrZSBzdXJlIHRoYXQgZXBzIGlzIG5vdCB0b28gYWNjdXJhdGUKICAgIGlmICh0MSA8IC1lcHMgb3IgdDIgPCAtZXBzKQogICAgICAgIHJldHVybiBmYWxzZTsKCiAgICByZXR1cm4gdHJ1ZTsKfQoKZG91YmxlIHJheVJheURpc3RhbmNlKHB0IGEsIHB0IGIsIHB0IGMsIHB0IGQpCnsKICAgIHB0IGR1bW15OwogICAgaWYgKGludGVyc2VjdFNlZ21lbnRzKGEsIGIsIGMsIGQsIGR1bW15KSkKICAgICAgICByZXR1cm4gMDsKICAgIHJldHVybiBtaW4ocmF5UG9pbnREaXN0YW5jZShhLCBiLCBjKSwgcmF5UG9pbnREaXN0YW5jZShjLCBkLCBhKSk7Cn0KCnZvaWQgU3RyaWtlcigpCnsKICAgIGludCBhLCBiOwogICAgY2luID4+IGEgPj4gYjsKICAgIHB0IHAxKGEsIGIpOwogICAgY2luID4+IGEgPj4gYjsKICAgIHB0IHAyKGEsIGIpOwogICAgY2luID4+IGEgPj4gYjsKICAgIHB0IHAzKGEsIGIpOwogICAgY2luID4+IGEgPj4gYjsKICAgIHB0IHA0KGEsIGIpOwogICAgY291dCA8PCBmaXhlZCA8PCBzZXRwcmVjaXNpb24oMTIpIDw8IHJheVJheURpc3RhbmNlKHAxLCBwMiwgcDMsIHA0KTsKfQoKc2lnbmVkIG1haW4oKQp7CiAgICBmaWxlSU8oKTsKICAgIGludCBfdCA9IDE7CiAgICAvLyBjaW4gPj4gX3Q7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IF90OyArK2kpCiAgICB7CiAgICAgICAgU3RyaWtlcigpOwogICAgfQp9Cg==