Problem:
Equivalent Deformation
Two triangles
T
1
and
T
2
with the same area are on a plane.
Your task is to perform the following operation to
T
1
several times so that it is exactly superposed on
T
2
.
Here, vertices of
T
1
can be on any of the vertices of
T
2
.
Compute the minimum number of operations required to superpose
T
1
on
T
2
.
(Operation): Choose one vertex of the triangle and move it to an arbitrary point on a line passing through the vertex and parallel to the opposite side.
An operation example
The following figure shows a possible sequence of the operations for the first dataset of the sample input.
Input
The input consists of at most 2000 datasets, each in the following format.
x
11
y
11
x
12
y
12
x
13
y
13
x
21
y
21
x
22
y
22
x
23
y
23
x
ij
and
y
ij
are the
x-
and
y-
coordinate of the
j
-th vertex of
T
i
.
The following holds for the dataset.
All the coordinate values are integers with at most 1000 of absolute values.
T
1
and
T
2
have the same positive area size.
The given six vertices are all distinct points.
An empty line is placed between datasets.
The end of the input is indicated by EOF.
Output
For each dataset, output the minimum number of operations required in one line.
If five or more operations are required, output
Many
instead.
Note that, vertices may have non-integral values after they are moved.
You can prove that, for any input satisfying the above constraints, the number of operations required is bounded by some constant.
Sample Input
0 1
2 2
1 0
1 3
5 2
4 3

0 0
0 1
1 0
0 3
0 2
1 -1

-5 -4
0 1
0 15
-10 14
-5 10
0 -8

-110 221
-731 525
-555 -258
511 -83
-1000 -737
66 -562

533 -45
-525 -450
-282 -667
-439 823
-196 606
-768 -233

0 0
0 1
1 0
99 1
100 1
55 2

354 -289
89 -79
256 -166
131 -196
-774 -809
-519 -623

-990 688
-38 601
-360 712
384 759
-241 140
-59 196

629 -591
360 -847
936 -265
109 -990
-456 -913
-787 -884

-1000 -1000
-999 -999
-1000 -998
1000 1000
999 999
1000 998

-386 -83
404 -83
-408 -117
-162 -348
128 -88
296 -30

-521 -245
-613 -250
797 451
-642 239
646 309
-907 180

-909 -544
-394 10
-296 260
-833 268
-875 882
-907 -423
Output for the Sample Input
4
3
3
3
3
4
4
4
4
Many
Many
Many
Many

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rrep(i, a, b) for (ll i = (ll)(b)-1; i >= (ll)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

using T = double;
const T eps = 1e-6;
using Point = complex<T>;
using Poly = vector<Point>;
#define X real()
#define Y imag()
template <typename T> inline bool eq(const T &a, const T &b) {
    return fabs(a - b) < eps;
}
bool cmp(const Point &a, const Point &b) {
    auto sub = [&](Point a) {
        return (a.Y < 0 ? -1 : (a.Y == 0 && a.X >= 0 ? 0 : 1));
    };
    if (sub(a) != sub(b))
        return sub(a) < sub(b);
    return a.Y * b.X < a.X * b.Y;
}
struct Line {
    Point a, b, dir;
    Line() {}
    Line(Point _a, Point _b) : a(_a), b(_b), dir(b - a) {}
    Line(T A, T B, T C) {
        if (eq(A, .0)) {
            a = Point(0, C / B), b = Point(1 / C / B);
        } else if (eq(B, .0)) {
            a = Point(C / A, 0), b = Point(C / A, 1);
        } else {
            a = Point(0, C / B), b = Point(C / A, 0);
        }
    }
};
struct Segment : Line {
    Segment() {}
    Segment(Point _a, Point _b) : Line(_a, _b) {}
};
struct Circle {
    Point p;
    T r;
    Circle() {}
    Circle(Point _p, T _r) : p(_p), r(_r) {}
};

istream &operator>>(istream &is, Point &p) {
    T x, y;
    is >> x >> y;
    p = Point(x, y);
    return is;
}
ostream &operator<<(ostream &os, Point &p) {
    os << fixed << setprecision(12) << p.X << ' ' << p.Y;
    return os;
}
Point unit(const Point &a) {
    return a / abs(a);
}
T dot(const Point &a, const Point &b) {
    return a.X * b.X + a.Y * b.Y;
}
T cross(const Point &a, const Point &b) {
    return a.X * b.Y - a.Y * b.X;
}
Point rot(const Point &a, const T &theta) {
    return Point(cos(theta) * a.X - sin(theta) * a.Y,
                 sin(theta) * a.X + cos(theta) * a.Y);
}
Point rot90(const Point &a) {
    return Point(-a.Y, a.X);
}
T arg(const Point &a, const Point &b, const Point &c) {
    double ret = acos(dot(a - b, c - b) / abs(a - b) / abs(c - b));
    if (cross(a - b, c - b) < 0)
        ret = -ret;
    return ret;
}

Point Projection(const Line &l, const Point &p) {
    T t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
Point Projection(const Segment &l, const Point &p) {
    T t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
Point Reflection(const Line &l, const Point &p) {
    return p + (Projection(l, p) - p) * 2.;
}
int ccw(const Point &a, Point b, Point c) {
    b -= a;
    c -= a;
    if (cross(b, c) > eps)
        return 1; // ccw

    if (cross(b, c) < -eps)
        return -1; // cw

    if (dot(b, c) < 0)
        return 2; // c,a,b

    if (norm(b) < norm(c))
        return -2; // a,b,c

    return 0;      // a,c,b

}
bool isOrthogonal(const Line &a, const Line &b) {
    return eq(dot(a.b - a.a, b.b - b.a), .0);
}
bool isParallel(const Line &a, const Line &b) {
    return eq(cross(a.b - a.a, b.b - b.a), .0);
}
bool isIntersect(const Segment &a, const Segment &b) {
    return ccw(a.a, a.b, b.a) * ccw(a.a, a.b, b.b) <= 0 and
           ccw(b.a, b.b, a.a) * ccw(b.a, b.b, a.b) <= 0;
}
int isIntersect(const Circle &a, const Circle &b) {
    T d = abs(a.p - b.p);
    if (d > a.r + b.r + eps)
        return 4;
    if (eq(d, a.r + b.r))
        return 3;
    if (eq(d, abs(a.r - b.r)))
        return 1;
    if (d < abs(a.r - b.r) - eps)
        return 0;
    return 2;
}
T Dist(const Line &a, const Point &b) {
    Point c = Projection(a, b);
    return abs(c - b);
}
T Dist(const Segment &a, const Point &b) {
    if (dot(a.b - a.a, b - a.a) < eps)
        return abs(b - a.a);
    if (dot(a.a - a.b, b - a.b) < eps)
        return abs(b - a.b);
    return abs(cross(a.b - a.a, b - a.a)) / abs(a.b - a.a);
}
T Dist(const Segment &a, const Segment &b) {
    if (isIntersect(a, b))
        return .0;
    T res = min({Dist(a, b.a), Dist(a, b.b), Dist(b, a.a), Dist(b, a.b)});
    return res;
}
Point Intersection(const Line &a, const Line &b) {
    T d1 = cross(a.b - a.a, b.b - b.a);
    T d2 = cross(a.b - a.a, a.b - b.a);
    if (eq(d1, 0.) and eq(d2, 0.))
        return b.a;
    return b.a + (b.b - b.a) * (d2 / d1);
}
Poly Intersection(const Circle &a, const Line &b) {
    Poly res;
    T d = Dist(b, a.p);
    if (d > a.r + eps)
        return res;
    Point h = Projection(b, a.p);
    if (eq(d, a.r)) {
        res.push_back(h);
        return res;
    }
    Point e = unit(b.b - b.a);
    T ph = sqrt(a.r * a.r - d * d);
    res.push_back(h - e * ph);
    res.push_back(h + e * ph);
    return res;
}
Poly Intersection(const Circle &a, const Segment &b) {
    Line c(b.a, b.b);
    Poly sub = Intersection(a, c);
    double xmi = min(b.a.X, b.b.X), xma = max(b.a.X, b.b.X);
    double ymi = min(b.a.Y, b.b.Y), yma = max(b.a.Y, b.b.Y);
    Poly res;
    rep(i, 0, sub.size()) {
        if (xmi <= sub[i].X + eps and sub[i].X - eps <= xma and
            ymi <= sub[i].Y + eps and sub[i].Y - eps <= yma) {
            res.push_back(sub[i]);
        }
    }
    return res;
}
Poly Intersection(const Circle &a, const Circle &b) {
    Poly res;
    int mode = isIntersect(a, b);
    T d = abs(a.p - b.p);
    if (mode == 4 or mode == 0)
        return res;
    if (mode == 3) {
        T t = a.r / (a.r + b.r);
        res.push_back(a.p + (b.p - a.p) * t);
        return res;
    }
    if (mode == 1) {
        if (b.r < a.r - eps) {
            res.push_back(a.p + (b.p - a.p) * (a.r / d));
        } else {
            res.push_back(b.p + (a.p - b.p) * (b.r / d));
        }
        return res;
    }
    T rc = (a.r * a.r + d * d - b.r * b.r) / d / 2.;
    T rs = sqrt(a.r * a.r - rc * rc);
    if (a.r - abs(rc) < eps)
        rs = 0;
    Point e = unit(b.p - a.p);
    res.push_back(a.p + rc * e + rs * e * Point(0, 1));
    res.push_back(a.p + rc * e + rs * e * Point(0, -1));
    return res;
}
Poly HalfplaneIntersection(vector<Line> &H) {
    sort(ALL(H), [&](Line &l1, Line &l2) { return cmp(l1.dir, l2.dir); });
    auto outside = [&](Line &L, Point p) -> bool {
        return cross(L.dir, p - L.a) < -eps;
    };
    deque<Line> deq;
    int sz = 0;
    rep(i, 0, SZ(H)) {
        while (sz > 1 and
               outside(H[i], Intersection(deq[sz - 1], deq[sz - 2]))) {
            deq.pop_back();
            sz--;
        }
        while (sz > 1 and outside(H[i], Intersection(deq[0], deq[1]))) {
            deq.pop_front();
            sz--;
        }
        if (sz > 0 and fabs(cross(H[i].dir, deq[sz - 1].dir)) < eps) {
            if (dot(H[i].dir, deq[sz - 1].dir) < 0) {
                return {};
            }
            if (outside(H[i], deq[sz - 1].a)) {
                deq.pop_back();
                sz--;
            } else
                continue;
        }
        deq.push_back(H[i]);
        sz++;
    }

    while (sz > 2 and outside(deq[0], Intersection(deq[sz - 1], deq[sz - 2]))) {
        deq.pop_back();
        sz--;
    }
    while (sz > 2 and outside(deq[sz - 1], Intersection(deq[0], deq[1]))) {
        deq.pop_front();
        sz--;
    }
    if (sz < 3)
        return {};
    deq.push_back(deq.front());
    Poly ret;
    rep(i, 0, sz) ret.push_back(Intersection(deq[i], deq[i + 1]));
    return ret;
}

T Area(const Poly &a) {
    T res = 0;
    int n = a.size();
    rep(i, 0, n) res += cross(a[i], a[(i + 1) % n]);
    return fabs(res / 2.);
}
T Area(const Poly &a, const Circle &b) {
    int n = a.size();
    if (n < 3)
        return .0;
    auto rec = [&](auto self, const Circle &c, const Point &p1,
                   const Point &p2) {
        Point va = c.p - p1, vb = c.p - p2;
        T f = cross(va, vb), res = .0;
        if (eq(f, .0))
            return res;
        if (max(abs(va), abs(vb)) < c.r + eps)
            return f;
        if (Dist(Segment(p1, p2), c.p) > c.r - eps)
            return c.r * c.r * arg(vb * conj(va));
        auto u = Intersection(c, Segment(p1, p2));
        Poly sub;
        sub.push_back(p1);
        for (auto &x : u)
            sub.push_back(x);
        sub.push_back(p2);
        rep(i, 0, sub.size() - 1) res += self(self, c, sub[i], sub[i + 1]);
        return res;
    };
    T res = .0;
    rep(i, 0, n) res += rec(rec, b, a[i], a[(i + 1) % n]);
    return fabs(res / 2.);
}
T Area(const Circle &a, const Circle &b) {
    T d = abs(a.p - b.p);
    if (d >= a.r + b.r - eps)
        return .0;
    if (d <= abs(a.r - b.r) + eps) {
        T r = min(a.r, b.r);
        return M_PI * r * r;
    }
    T ath = acos((a.r * a.r + d * d - b.r * b.r) / d / a.r / 2.);
    T res = a.r * a.r * (ath - sin(ath * 2) / 2.);
    T bth = acos((b.r * b.r + d * d - a.r * a.r) / d / b.r / 2.);
    res += b.r * b.r * (bth - sin(bth * 2) / 2.);
    return fabs(res);
}
bool isConvex(const Poly &a) {
    int n = a.size();
    int cur, pre, nxt;
    rep(i, 0, n) {
        pre = (i - 1 + n) % n;
        nxt = (i + 1) % n;
        cur = i;
        if (ccw(a[pre], a[cur], a[nxt]) == -1)
            return 0;
    }
    return 1;
}
int isContained(const Poly &a,
                const Point &b) { // 0:not contain,1:on edge,2:contain

    bool res = 0;
    int n = a.size();
    rep(i, 0, n) {
        Point p = a[i] - b, q = a[(i + 1) % n] - b;
        if (p.Y > q.Y)
            swap(p, q);
        if (p.Y < eps and eps < q.Y and cross(p, q) > eps)
            res ^= 1;
        if (eq(cross(p, q), .0) and dot(p, q) < eps)
            return 1;
    }
    return (res ? 2 : 0);
}
Poly ConvexHull(Poly &a) {
    sort(ALL(a), [](const Point &p, const Point &q) {
        return (eq(p.Y, q.Y) ? p.X < q.X : p.Y < q.Y);
    });
    a.erase(unique(ALL(a)), a.end());
    int n = a.size(), k = 0;
    Poly res(n * 2);
    for (int i = 0; i < n; res[k++] = a[i++]) {
        while (k >= 2 and
               cross(res[k - 1] - res[k - 2], a[i] - res[k - 1]) < eps)
            k--;
    }
    for (int i = n - 2, t = k + 1; i >= 0; res[k++] = a[i--]) {
        while (k >= t and
               cross(res[k - 1] - res[k - 2], a[i] - res[k - 1]) < eps)
            k--;
    }
    res.resize(k - 1);
    return res;
}
T Diam(const Poly &a) {
    int n = a.size();
    int x = 0, y = 0;
    rep(i, 1, n) {
        if (a[i].Y > a[x].Y)
            x = i;
        if (a[i].Y < a[y].Y)
            y = i;
    }
    T res = abs(a[x] - a[y]);
    int i = x, j = y;
    do {
        if (cross(a[(i + 1) % n] - a[i], a[(j + 1) % n] - a[j]) < 0)
            i = (i + 1) % n;
        else
            j = (j + 1) % n;
        chmax(res, abs(a[i] - a[j]));
    } while (i != x or j != y);
    return res;
}
Poly Cut(const Poly &a, const Line &l) {
    int n = a.size();
    Poly res;
    rep(i, 0, n) {
        Point p = a[i], q = a[(i + 1) % n];
        if (ccw(l.a, l.b, p) != -1)
            res.push_back(p);
        if (ccw(l.a, l.b, p) * ccw(l.a, l.b, q) < 0)
            res.push_back(Intersection(Line(p, q), l));
    }
    return res;
}

T Closest(Poly &a) {
    int n = a.size();
    if (n <= 1)
        return 0;
    sort(ALL(a), [&](Point a, Point b) {
        return (eq(a.X, b.X) ? a.Y < b.Y : a.X < b.X);
    });
    Poly buf(n);
    auto rec = [&](auto self, int lb, int rb) -> T {
        if (rb - lb <= 1)
            return (T)INF;
        int mid = (lb + rb) >> 1;
        auto x = a[mid].X;
        T res = min(self(self, lb, mid), self(self, mid, rb));
        inplace_merge(a.begin() + lb, a.begin() + mid, a.begin() + rb,
                      [&](auto p, auto q) { return p.Y < q.Y; });
        int ptr = 0;
        rep(i, lb, rb) {
            if (abs(a[i].X - x) >= res)
                continue;
            rep(j, 0, ptr) {
                auto sub = a[i] - buf[ptr - 1 - j];
                if (sub.Y >= res)
                    break;
                chmin(res, abs(sub));
            }
            buf[ptr++] = a[i];
        }
        return res;
    };
    return rec(rec, 0, n);
}

Circle Incircle(const Point &a, const Point &b, const Point &c) {
    T A = abs(b - c), B = abs(c - a), C = abs(a - b);
    Point p(A * a.X + B * b.X + C * c.X, A * a.Y + B * b.Y + C * c.Y);
    p /= (A + B + C);
    T r = Dist(Line(a, b), p);
    return Circle(p, r);
}
Circle Circumcircle(const Point &a, const Point &b, const Point &c) {
    Line l1((a + b) / 2., (a + b) / 2. + (b - a) * Point(0, 1));
    Line l2((b + c) / 2., (b + c) / 2. + (c - b) * Point(0, 1));
    Point p = Intersection(l1, l2);
    return Circle(p, abs(p - a));
}
Poly tangent(const Point &a, const Circle &b) {
    return Intersection(b, Circle(a, sqrt(norm(b.p - a) - b.r * b.r)));
}
vector<Line> tangent(const Circle &a, const Circle &b) {
    vector<Line> res;
    T d = abs(a.p - b.p);
    if (eq(d, 0.))
        return res;
    Point u = unit(b.p - a.p);
    Point v = u * Point(0, 1);
    for (int t : {-1, 1}) {
        T h = (a.r + b.r * t) / d;
        if (eq(h * h, 1.)) {
            res.push_back(Line(a.p + (h > 0 ? u : -u) * a.r,
                               a.p + (h > 0 ? u : -u) * a.r + v));
        } else if (1 > h * h) {
            Point U = u * h, V = v * sqrt(1 - h * h);
            res.push_back(Line(a.p + (U + V) * a.r, b.p - (U + V) * (b.r * t)));
            res.push_back(Line(a.p + (U - V) * a.r, b.p - (U - V) * (b.r * t)));
        }
    }
    return res;
}

/**
 * @brief Geometry
 */

int main() {
    Point P[2][3];
    double x,y;
while(cin >> x >> y) {
    P[0][0] = Point(x,y);
    rep(i,0,2) {
        rep(j,0,3) {
            if (i == 0 && j == 0) continue;
            cin >> x >> y;
            P[i][j] = Point(x,y);
        }
    }
    auto DFS = [&](auto self, vector<Point> match, vector<Point> tmp, int id, int Dep) -> int {
        if (Dep >= 5) return 5;
        if (id == 3) {
            rep(i,0,3) {
                if (!eq(tmp[i],match[i])) return 5;
            }
            return Dep;
        }
        int Ret = 5;
        Point P1 = tmp[id], P2 = tmp[(id+1)%3], P3 = tmp[(id+2)%3];
        Point Q = match[id];
        if (isParallel(Line(P1,Q),Line(P2,P3))) {
            vector<Point> next = tmp;
            next[id] = Q;
            chmin(Ret,self(self,match,next,id+1,Dep+1));
        }
        else {
            {
                vector<Point> next = tmp;
                next[id] = Q;
                next[(id+1)%3] = Intersection(Line(P2,P2+P3-P1),Line(P3,P3+P1-Q));
                chmin(Ret,self(self,match,next,id+1,Dep+2));
            }
            {
                vector<Point> next = tmp;
                next[id] = Q;
                next[(id+2)%3] = Intersection(Line(P3,P3+P2-P1),Line(P2,P2+P1-Q));
                chmin(Ret,self(self,match,next,id+1,Dep+2));
            }
        }
        return Ret;
    };
    int ANS = 5;
    vector<int> ord1(3);
    iota(ALL(ord1),0);
    do {
        vector<int> ord2(3);
        iota(ALL(ord2),0);
        do {
            vector<Point> match(3);
            rep(i,0,3) match[i] = P[0][ord1[i]];
            vector<Point> tmp(3);
            rep(i,0,3) tmp[i] = P[1][ord2[i]];
            chmin(ANS, DFS(DFS,match,tmp,0,0));
        } while(next_permutation(ALL(ord2)));
    } while(next_permutation(ALL(ord1)));
    if (ANS == 5) cout << "Many" << endl;
    else cout << ANS << endl;
}
}
accuracy: 1
time_ms: 50
memory_kb: 3488
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
#define rep(i, a, b) for(ll i = a; i < b; ++i)
#define rrep(i, a, b) for(ll i = a; i >= b; --i)
constexpr ll inf = 4e18;
using Real = long double;
const Real EPS = 1e-8, PI = acos(Real(-1.0));
int sign(const Real& r) {
    if(r <= -EPS) return -1;
    if(r >= +EPS) return +1;
    return 0;
}
bool eq(const Real& a, const Real& b) {
    return sign(a - b) == 0;
}
using Point = complex<Real>;
istream& operator>>(istream& is, Point& p) {
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}
ostream& operator<<(ostream& os, const Point& p) {
    return os << p.real() << ' ' << p.imag();
}
Real dot(const Point& p1, const Point& p2) {
    return (conj(p1) * p2).real();
}
Real cross(const Point& p1, const Point& p2) {
    return (conj(p1) * p2).imag();
}
int ccw(const Point& a, Point b, Point c) {
    b -= a;
    c -= a;
    if(sign(cross(b, c)) == 1) return 1;
    if(sign(cross(b, c)) == -1) return -1;
    if(sign(dot(b, c)) == -1) return +2;
    if(norm(b) < norm(c)) return -2;
    return 0;
}
struct Line {
    Point a, b;
    Line() = default;
    Line(const Point& a, const Point& b)
        : a(a), b(b) {}
};
using Segment = Line;
bool is_parallel(const Line& a, const Line& b) {
    return eq(cross(a.b - a.a, b.b - b.a), 0.0);
}
bool is_intersect_ll(const Line& l1, const Line& l2) {
    if(!eq(cross(l1.b - l1.a, l2.b - l2.a), 0.0)) return true;
    return eq(cross(l1.b - l1.a, l2.b - l1.a), 0.0);
}
vector<Point> intersection_ll(const Line& l1, const Line& l2) {
    vector<Point> res;
    if(!is_intersect_ll(l1, l2)) return res;
    Real a = cross(l1.b - l1.a, l2.b - l2.a);
    Real b = cross(l1.b - l1.a, l1.b - l2.a);
    if(eq(a, 0.0) and eq(b, 0.0)) {
        res.push_back(l2.a);
    } else {
        res.push_back(l2.a + (l2.b - l2.a) * b / a);
    }
    return res;
}
int main(void) {
    cin.tie(0);
    ios::sync_with_stdio(0);
    vector<Point> p1(3), p2(3);
    while(cin >> p1[0]) {
        rep(i, 1, 3) cin >> p1[i];
        rep(i, 0, 3) cin >> p2[i];
        auto is_three = [&](vector<Point> t1, vector<Point> t2, vector<int> ord) -> bool {
            rep(i, 0, 3) {
                Line l1 = Line(t1[ord[i]], t2[ord[i]]);
                Line l2 = Line(t1[ord[(i + 1) % 3]], t1[ord[(i + 2) % 3]]);
                if(!is_parallel(l1, l2)) return false;
                t1[ord[i]] = t2[ord[i]];
            }
            return true;
        };
        auto is_four = [&](vector<Point> t1, vector<Point> t2, vector<int> ord) -> bool {
            Line l1 = Line(t1[ord[0]], t2[ord[0]]);
            Line l2 = Line(t1[ord[1]], t1[ord[2]]);
            if(is_parallel(l1, l2)) {
                vector<Point> t3 = t1;
                t3[ord[0]] = t2[ord[0]];

                Point dir1 = t3[ord[1]] - t2[ord[1]];
                Line l3 = Line(t3[ord[0]], t3[ord[0]] + dir1);
                Point dir2 = t3[ord[0]] - t3[ord[1]];
                Line l4 = Line(t3[ord[2]], t3[ord[2]] + dir2);
                if(is_intersect_ll(l3, l4)) return true;

                return false;
            }

            Point dir1 = t1[ord[0]] - t1[ord[2]];
            Line l3 = Line(t1[ord[1]], t1[ord[1]] + dir1);
            Point dir2 = t1[ord[0]] - t2[ord[0]];
            Line l4 = Line(t1[ord[2]], t1[ord[2]] + dir2);
            vector<Point> cand1 = intersection_ll(l3, l4);
            if(!cand1.empty()) {
                vector<Point> t3 = t1;
                t3[ord[1]] = cand1[0];
                vector<int> ord2(3);
                rep(i, 0, 3) ord2[i] = i;
                do {
                    if(is_three(t3, t2, ord2)) return true;
                } while(next_permutation(ord2.begin(), ord2.end()));
            }

            Point dir3 = t1[ord[0]] - t1[ord[1]];
            Line l5 = Line(t1[ord[2]], t1[ord[2]] + dir3);
            Point dir4 = t1[ord[0]] - t2[ord[0]];
            Line l6 = Line(t1[ord[1]], t1[ord[1]] + dir4);
            vector<Point> cand2 = intersection_ll(l5, l6);
            if(!cand2.empty()) {
                vector<Point> t3 = t1;
                t3[ord[2]] = cand2[0];
                vector<int> ord2(3);
                rep(i, 0, 3) ord2[i] = i;
                do {
                    if(is_three(t3, t2, ord2)) return true;
                } while(next_permutation(ord2.begin(), ord2.end()));
            }

            return false;
        };
        vector<int> perm(3);
        rep(i, 0, 3) perm[i] = i;
        int ans = 5;
        do {
            vector<Point> t2 = p2;
            vector<Point> t1(3);
            rep(i, 0, 3) {
                t1[i] = p1[perm[i]];
            }
            if(ccw(t1[0], t1[1], t1[2]) != ccw(t2[0], t2[1], t2[2])) continue;
            vector<int> ord(3);
            rep(i, 0, 3) ord[i] = i;
            do {
                if(is_three(t1, t2, ord)) ans = min(ans, 3);
                if(is_four(t1, t2, ord)) ans = min(ans, 4);
            } while(next_permutation(ord.begin(), ord.end()));
        } while(next_permutation(perm.begin(), perm.end()));
        if(ans == 5) {
            cout << "Many" << '\n';
        } else {
            cout << ans << '\n';
        }
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3544
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
#define rep(i, a, b) for(ll i = a; i < b; ++i)
#define rrep(i, a, b) for(ll i = a; i >= b; --i)
constexpr ll inf = 4e18;
using Real = long double;
const Real EPS = 1e-8, PI = acos(Real(-1.0));
int sign(const Real& r) {
    if(r <= -EPS) return -1;
    if(r >= +EPS) return +1;
    return 0;
}
bool eq(const Real& a, const Real& b) {
    return sign(a - b) == 0;
}
using Point = complex<Real>;
istream& operator>>(istream& is, Point& p) {
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}
ostream& operator<<(ostream& os, const Point& p) {
    return os << p.real() << ' ' << p.imag();
}
Real dot(const Point& p1, const Point& p2) {
    return (conj(p1) * p2).real();
}
Real cross(const Point& p1, const Point& p2) {
    return (conj(p1) * p2).imag();
}
int ccw(const Point& a, Point b, Point c) {
    b -= a;
    c -= a;
    if(sign(cross(b, c)) == 1) return 1;
    if(sign(cross(b, c)) == -1) return -1;
    if(sign(dot(b, c)) == -1) return +2;
    if(norm(b) < norm(c)) return -2;
    return 0;
}
struct Line {
    Point a, b;
    Line() = default;
    Line(const Point& a, const Point& b)
        : a(a), b(b) {}
};
using Segment = Line;
bool is_parallel(const Line& a, const Line& b) {
    return eq(cross(a.b - a.a, b.b - b.a), 0.0);
}
bool is_intersect_ll(const Line& l1, const Line& l2) {
    if(!eq(cross(l1.b - l1.a, l2.b - l2.a), 0.0)) return true;
    return eq(cross(l1.b - l1.a, l2.b - l1.a), 0.0);
}
vector<Point> intersection_ll(const Line& l1, const Line& l2) {
    vector<Point> res;
    if(!is_intersect_ll(l1, l2)) return res;
    Real a = cross(l1.b - l1.a, l2.b - l2.a);
    Real b = cross(l1.b - l1.a, l1.b - l2.a);
    if(eq(a, 0.0) and eq(b, 0.0)) {
        res.push_back(l2.a);
    } else {
        res.push_back(l2.a + (l2.b - l2.a) * b / a);
    }
    return res;
}
int main(void) {
    cin.tie(0);
    ios::sync_with_stdio(0);
    while(1) {
        vector<Point> p1(3), p2(3);
        rep(i, 0, 3) cin >> p1[i];
        if(cin.eof()) break;
        rep(i, 0, 3) cin >> p2[i];
        if(cin.eof()) break;
        auto is_three = [&](vector<Point> t1, vector<Point> t2, vector<int> ord) -> bool {
            rep(i, 0, 3) {
                Line l1 = Line(t1[ord[i]], t2[ord[i]]);
                Line l2 = Line(t1[ord[(i + 1) % 3]], t1[ord[(i + 2) % 3]]);
                if(!is_parallel(l1, l2)) return false;
                t1[ord[i]] = t2[ord[i]];
            }
            return true;
        };
        auto is_four = [&](vector<Point> t1, vector<Point> t2, vector<int> ord) -> bool {
            Line l1 = Line(t1[ord[0]], t2[ord[0]]);
            Line l2 = Line(t1[ord[1]], t1[ord[2]]);
            if(is_parallel(l1, l2)) {
                vector<Point> t3 = t1;
                t3[ord[0]] = t2[ord[0]];

                Point dir1 = t3[ord[1]] - t2[ord[1]];
                Line l3 = Line(t3[ord[0]], t3[ord[0]] + dir1);
                Point dir2 = t3[ord[0]] - t3[ord[1]];
                Line l4 = Line(t3[ord[2]], t3[ord[2]] + dir2);
                if(is_intersect_ll(l3, l4)) return true;

                return false;
            }

            Point dir1 = t1[ord[0]] - t1[ord[2]];
            Line l3 = Line(t1[ord[1]], t1[ord[1]] + dir1);
            Point dir2 = t1[ord[0]] - t2[ord[0]];
            Line l4 = Line(t1[ord[2]], t1[ord[2]] + dir2);
            vector<Point> cand1 = intersection_ll(l3, l4);
            if(!cand1.empty()) {
                vector<Point> t3 = t1;
                t3[ord[1]] = cand1[0];
                vector<int> ord2(3);
                rep(i, 0, 3) ord2[i] = i;
                do {
                    if(is_three(t3, t2, ord2)) return true;
                } while(next_permutation(ord2.begin(), ord2.end()));
            }

            Point dir3 = t1[ord[0]] - t1[ord[1]];
            Line l5 = Line(t1[ord[2]], t1[ord[2]] + dir3);
            Point dir4 = t1[ord[0]] - t2[ord[0]];
            Line l6 = Line(t1[ord[1]], t1[ord[1]] + dir4);
            vector<Point> cand2 = intersection_ll(l5, l6);
            if(!cand2.empty()) {
                vector<Point> t3 = t1;
                t3[ord[2]] = cand2[0];
                vector<int> ord2(3);
                rep(i, 0, 3) ord2[i] = i;
                do {
                    if(is_three(t3, t2, ord2)) return true;
                } while(next_permutation(ord2.begin(), ord2.end()));
            }

            return false;
        };
        vector<int> perm(3);
        rep(i, 0, 3) perm[i] = i;
        int ans = 5;
        do {
            vector<Point> t2 = p2;
            vector<Point> t1(3);
            rep(i, 0, 3) {
                t1[i] = p1[perm[i]];
            }
            if(ccw(t1[0], t1[1], t1[2]) != ccw(t2[0], t2[1], t2[2])) continue;
            vector<int> ord(3);
            rep(i, 0, 3) ord[i] = i;
            do {
                if(is_three(t1, t2, ord)) ans = min(ans, 3);
                if(is_four(t1, t2, ord)) ans = min(ans, 4);
            } while(next_permutation(ord.begin(), ord.end()));
        } while(next_permutation(perm.begin(), perm.end()));
        if(ans == 5) {
            cout << "Many";
        } else {
            cout << ans;
        }
        if(cin.eof()) break;
        cout << '\n';
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3424
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
#define all(A) A.begin(),A.end()
#define rep(i, n) for (int i = 0; i < (int) (n); i++)

bool OK = 1;
bool is_diff(vll& PX, vll& PY, vll& QX, vll& QY, ll a, ll b, bool DIFF) {
    ll dx = PX[(a + 1) % 3] - PX[(a + 2) % 3];
    ll dy = PY[(a + 1) % 3] - PY[(a + 2) % 3];

    ll DX = PX[a] - QX[b];
    ll DY = PY[a] - QY[b];

    ll g = gcd(dx, dy);
    dx /= g;
    dy /= g;
    if (dx < 0) {
        dx *= -1;
        dy *= -1;
    }
    if (dx == 0 && dy <= 0)dy *= -1;

    ll G = gcd(DX, DY);
    DX /= G;
    DY /= G;
    if (DX < 0) {
        DX *= -1;
        DY *= -1;
    }
    if (DX == 0 && DY < 0)DY *= -1;
    if (dx == DX && dy == DY) {
        PX[a] = QX[b];
        PY[a] = QY[b];
        return 0;
    }




    if (DIFF)return 1;
    DX = QX[(b + 1) % 3] - QX[(b + 2) % 3];
    DY = QY[(b + 1) % 3] - QY[(b + 2) % 3];

    G = gcd(DX, DY);
    DX /= G;
    DY /= G;
    if (DX < 0) {
        DX *= -1;
        DY *= -1;
    }
    if (DX == 0 && DY < 0)DY *= -1;
    if (dx == DX && dy == DY) {
        OK = 0;
        return 1;
    }




    ll RHS = dy * DX - dx * DY;
    ll LHS = dy * DX * PX[a] - dx * DX * PY[a] - DY * dx * QX[b] + dx * DX * QY[b];
    ll GHS = gcd(RHS, LHS);
    RHS /= GHS;
    LHS /= GHS;
    // if (RHS < 0) {
    //     RHS *= -1;
    //     LHS *= -1;
    // }
    //nx=LHS/RHS
    //ny=dy/dx*(nx-PX[a])+PY[a]
    //ny=DY/DX*(nx-QX[b])+QY[b]
    if (dx != 0) {
        rep(i, 3) {
            if (i != a) {
                PX[i] *= (RHS * dx);
                PY[i] *= (RHS * dx);
            }
            if (i != b) {
                QX[i] *= (RHS * dx);
                QY[i] *= (RHS * dx);
            }
        }
        ll u = PX[a];
        ll v = PY[a];
        PX[a] = QX[b] = LHS * dx;
        //DY*(LHS-u*RHS)+v*DX*RHS;
        PY[a] = QY[b] = dy * (LHS - u * RHS) + v * dx * RHS;
    }
    else {
        rep(i, 3) {
            if (i != a) {
                PX[i] *= (RHS * DX);
                PY[i] *= (RHS * DX);
            }
            if (i != b) {
                QX[i] *= (RHS * DX);
                QY[i] *= (RHS * DX);
            }
        }
        //ny=DY/DX*(nx-QX[b])+QY[b]
        ll u = QX[b];
        ll v = QY[b];
        PX[a] = QX[b] = LHS * DX;
        PY[a] = QY[b] = DY * (LHS - u * RHS) + v * DX * RHS;
    }
    return 1;
}

bool eq(vll& PX, vll& PY, vll& QX, vll& QY) {
    vector<pair<ll, ll>> P(3), Q(3);
    rep(i, 3) {
        P[i] = { PX[i],PY[i] };
        Q[i] = { QX[i],QY[i] };
    }
    sort(all(P));
    sort(all(Q));
    return P == Q;
}

int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);



    vector<ll> X(6), Y(6);
    while (cin >> X[0] >> Y[0]) {
        rep(i, 5)cin >> X[i + 1] >> Y[i + 1];

        ll an = 5;

        rep(uu,2){
            rep(aa, 9)rep(bb, 9)rep(cc, 9)rep(dd, 9) {
            if (aa / 3 == bb / 3 || bb / 3 == cc / 3 || dd / 3 == cc / 3)continue;
            vector<ll> PX, PY, QX, QY;
            rep(i, 3) {
                PX.push_back(X[i]);
                PY.push_back(Y[i]);
                QX.push_back(X[i + 3]);
                QY.push_back(Y[i + 3]);
            }
            bool DIFF = 0;
            vll MV = { aa,bb,cc,dd };
            rep(p, 4) {
                if (aa == 0 && bb == 3 && cc <= 16) {
                    cout << "";
                }
                if (!eq(PX, PY, QX, QY)) {
                    ll a = MV[p] / 3;
                    ll b = MV[p] % 3;
                    OK = 1;
                    if (PX[a] != QX[b] || PY[a] != QY[b]) {
                        bool dif = is_diff(PX, PY, QX, QY, a, b, DIFF);
                        if (DIFF && dif)OK = 0;
                        if (dif)DIFF = 1;
                        if (!OK) {
                            continue;
                        }
                    }
                }
            }

            if (eq(PX, PY, QX, QY)) {
                // if (!DIFF)cout << aa << " " << bb << " " << cc << " " << dd << endl;
                if (!DIFF)an = min(an, 3ll);
                else an = min(an, 4ll);
            }

        }
        rep(i,3){
            swap(X[i],X[i+3]);
            swap(Y[i],Y[i+3]);
        }

        }
        if (an > 4)cout << "Many" << endl;
        else cout << an << endl;

    }



}
accuracy: 1
time_ms: 7370
memory_kb: 3460
final_rank: 20

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

template < class T > int sign(const T x) {
    T e = (is_integral_v< T > ? 1 : 1e-8);
    if(x <= -e) return -1;
    if(x >= +e) return +1;
    return 0;
}
template < class T > bool equals(const T& a, const T& b) { return sign(a - b) == 0; }
template < class T > struct point {
    T x, y;
    point() : x(0), y(0) {}
    point(T x, T y) : x(x), y(y) {}
    point(std::pair< T, T > p) : x(p.first), y(p.second) {}
    point& operator+=(const point& p) { x += p.x, y += p.y; return *this; }
    point& operator-=(const point& p) { x -= p.x, y -= p.y; return *this; }
    point& operator*=(const T r) { x *= r, y *= r; return *this; }
    point& operator/=(const T r) { x /= r, y /= r; return *this; }
    point operator+(const point& p) const { return point(*this) += p; }
    point operator-(const point& p) const { return point(*this) -= p; }
    point operator*(const T r) const { return point(*this) *= r; }
    point operator/(const T r) const { return point(*this) /= r; }
    point operator-() const { return {-x, -y}; }
    bool operator==(const point& p) const { return  equals(x, p.x) and equals(y, p.y); }
    bool operator!=(const point& p) const { return !equals(x, p.x) or !equals(y, p.y); }
    bool operator<(const point& p) const { return x == p.x ? y < p.y : x < p.x; }
    point< T > rot(double theta) {
        static_assert(is_floating_point_v< T >);
        double cos_ = std::cos(theta), sin_ = std::sin(theta);
        return {cos_ * x - sin_ * y, sin_ * x + cos_ * y};
    }
};
template < class T > istream& operator>>(istream& is, point< T >& p) { return is >> p.x >> p.y; }
template < class T > ostream& operator<<(ostream& os, point< T >& p) { return os << p.x << " " << p.y; }
template < class T > T dot(const point< T >& a, const point< T >& b) { return a.x * b.x + a.y * b.y; }
template < class T > T det(const point< T >& a, const point< T >& b) { return a.x * b.y - a.y * b.x; }
template < class T > T norm(const point< T >& p) { return p.x * p.x + p.y * p.y; }
template < class T > double abs(const point< T >& p) { return std::sqrt(norm(p)); }
template < class T > double angle(const point< T >& p) { return std::atan2(p.y, p.x); }

template < class T > int ccw(const point< T >& a, point< T > b, point< T > c) {
    b -= a, c -= a;
    if(sign(det(b, c)) == +1) return +1; // counter clockwise
    if(sign(det(b, c)) == -1) return -1; //         clockwise
    if(sign(dot(b, c)) == -1) return +2; // c-a-b
    if(norm(b) < norm(c)) return -2;     // a-b-c
    return 0;                            // a-c-b
}

template < class T > struct line {
    point< T > a, b;
    line() {}
    line(point< T > a, point< T > b) : a(a), b(b) {}
};
template < class T > point< T > projection(const line< T >& l, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
}
template < class T > point< T > reflection(const line< T >& l, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    return p + (projection(l, p) - p) * T(2);
}
template < class T > bool orthogonal(const line< T >& a, const line< T >& b) { return equals(dot(a.b - a.a, b.b - b.a), T(0)); }
template < class T > bool parallel  (const line< T >& a, const line< T >& b) { return equals(det(a.b - a.a, b.b - b.a), T(0)); }
template < class T > point< T > cross_point_ll(const line< T >& l, const line< T >& m) {
    static_assert(is_floating_point_v< T >);
    T A = det(l.b - l.a, m.b - m.a);
    T B = det(l.b - l.a, l.b - m.a);
    if(equals(abs(A), T(0)) and equals(abs(B), T(0))) return m.a;
    return m.a + (m.b - m.a) * B / A;
}

template < class T > using segment = line< T >;
template < class T > bool intersect_ss(const segment< T >& s, const segment< T >& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 and ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
template < class T > double distance_sp(const segment< T >& s, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    point r = projection(s, p);
    if(ccw(s.a, s.b, r) == 0) return abs(r - p);
    return std::min(abs(s.a - p), abs(s.b - p));
}
template < class T > double distance_ss(const segment< T >& a, const segment< T >& b) {
    if(intersect_ss(a, b)) return 0;
    return std::min({ distance_sp(a, b.a), distance_sp(a, b.b), distance_sp(b, a.a), distance_sp(b, a.b) });
}

template < class T > using polygon = std::vector< point< T > >;
template < class T > T area2(const polygon< T >& p) {
    T s = 0;
    int n = p.size();
    for(int i = 0; i < n; i++) s += det(p[i], p[(i + 1) % n]);
    return s;
}
template < class T > T area(const polygon< T >& p) { return area2(p) / T(2); }

template < class T > bool is_convex(const polygon< T >& p) {
    int n = p.size();
    for(int i = 0; i < n; i++) if(ccw(p[(i - 1 + n) % n], p[i], p[(i + 1) % n]) == -1) return false;
    return true;
}
template < class T > int contains(const polygon< T >& g, const point< T >& p) {
    int n = g.size();
    bool in = false;
    for(int i = 0; i < n; i++) {
        point a = g[i] - p, b = g[(i + 1) % n] - p;
        if(sign(a.y - b.y) == +1) std::swap(a, b);
        if(sign(a.y) <= 0 and sign(b.y) ==+1 and sign(det(a, b)) == -1) in = !in;
        if(sign(det(a, b)) == 0 and sign(dot(a, b)) <= 0) return 1; // ON
    }
    return in ? 2 : 0;
}
template < class T > polygon< T > convex_cut(const polygon< T >& p, const line< T >& l) {
    int n = p.size();
    polygon< T > res;
    for(int i = 0; i < n; i++) {
        point now = p[i], nxt = p[(i + 1) % n];
        if(ccw(l.a, l.b, now) != -1) res.push_back(now);
        if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) < 0) res.push_back(cross_point_ll(line(now, nxt), l));
    }
    return res;
}
template < class T > polygon< T > convex_hull(polygon< T >& p) {
    int n = p.size(), k = 0;
    if(n <= 2) return p;
    std::sort(p.begin(), p.end());
    polygon< T > ch(n + n);
    for(int i = 0; i < n; ch[k++] = p[i++])
        while(k >= 2 and sign(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) == -1) k--;
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
        while(k >= t and sign(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) == -1) k--;
    ch.resize(k - 1);
    return ch;
}
template < class T > T diameter2(const polygon< T >& p) {
    static_assert(is_floating_point_v< T >);
    int n = p.size(), is = 0, js = 0;
    for(int i = 1; i < n; i++) {
        if(sign(p[i].y - p[is].y) == +1) is = i;
        if(sign(p[i].y - p[js].y) == -1) js = i;
    }
    T dist_max = norm(p[is] - p[js]);
    int maxi = is, i = is, maxj = js, j = js;
    do {
        if(sign(det(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j])) >= 0) j = (j + 1) % n; else i = (i + 1) % n;
        if(norm(p[i] - p[j]) > dist_max) {
            dist_max = norm(p[i] - p[j]);
            maxi = i, maxj = j;
        }
    } while(i != is or j != js);
    return dist_max;
}
template < class T > double diameter(const polygon< T >& p) {
    static_assert(is_floating_point_v< T >);
    return std::sqrt(diameter2(p));
}

template < class T > struct circle {
    point< T > p;
    T r;
    circle() = default;
    circle(point< T > p, T r) : p(p), r(r) {}
};
template < class T > istream& operator>>(istream& is, circle< T >& c) { return is >> c.p >> c.r; }
template < class T > int intersect_cc(circle< T > c1, circle< T > c2) {
    if(c1.r < c2.r) std::swap(c1, c2);
    T d = abs(c1.p - c2.p);
    if(sign(c1.r + c2.r - d) == -1) return 4;
    if(equals(c1.r + c2.r, d)) return 3;
    if(sign(c1.r - c2.r - d) == -1) return 2;
    if(equals(c1.r - c2.r, d)) return 1;
    return 0;
}
template < class T > std::pair<point< T >, point< T >> cross_point_cc(const circle< T >& c1, const circle< T >& c2) {
    T d = abs(c1.p - c2.p);
    T a = std::acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    T t = angle(c2.p - c1.p);
    point< T > p1 = c1.p + point< T >(std::cos(t + a), std::sin(t + a)) * c1.r;
    point< T > p2 = c1.p + point< T >(std::cos(t - a), std::sin(t - a)) * c1.r;
    return {p1, p2};
}

int solve(vector<point<f64>> P_, vector<point<f64>> Q_) {
    int ans = 5;
    vector<int> I = {0, 1, 2}, J = {0, 1, 2};
    do { do {
        auto dfs = [&](auto self, vector<point<f64>> P, vector<point<f64>> Q, int i) -> int {
            if(i == 0) {
                if(P[0] == Q[0]) return 0 + self(self, P, Q, i + 1);
                if(parallel(line<f64>(P[0], Q[0]), line<f64>(P[1], P[2]))) {
                    P[0] = Q[0];
                    return 1 + self(self, P, Q, i + 1);
                } else {
                    int ans = 100;
                    for(int j : {1, 2}) {
                        const int k = 3 - j;
                        line<f64> l0(P[j], P[j] + (P[k] - P[0]));
                        line<f64> l1(P[k], P[k] + (P[0] - Q[0]));
                        if(parallel(l0, l1)) continue;
                        point<f64> p = cross_point_ll<f64>(l0, l1);
                        vector<point<f64>> nP = P;
                        nP[j] = p;
                        nP[0] = Q[0];
                        chmin(ans, 2 + self(self, nP, Q, i + 1));
                    }
                    return ans;
                }
            }

            if(i == 1) {
                if(P[1] == Q[1]) return 0 + self(self, P, Q, i + 1);
                if(parallel(line<f64>(P[1], Q[1]), line<f64>(P[0], P[2]))) {
                    P[1] = Q[1];
                    return 1 + self(self, P, Q, i + 1);
                } else {
                    line<f64> l0(P[2], P[2] + (P[0] - P[1]));
                    line<f64> l1(P[0], P[0] + (P[1] - Q[1]));
                    if(parallel(l0, l1)) return 100;
                    point<f64> p = cross_point_ll<f64>(l0, l1);
                    P[2] = p;
                    P[1] = Q[1];
                    return 2 + self(self, P, Q, i + 1);
                }
            }

            if(i == 2) {
                if(P[2] == Q[2]) return 0;
                if(parallel(line<f64>(P[2], Q[2]), line<f64>(P[0], P[1]))) {
                    return 1;
                } else {
                    return 100;
                }
            }

            assert(0);
        };

        vector<point<f64>> P(3), Q(3);
        for(int i : rep(3)) {
            P[i] = P_[I[i]];
            Q[i] = Q_[J[i]];
        }
        chmin(ans, dfs(dfs, P, Q, 0));
    } while(next_permutation(I.begin(), I.end())); } while(next_permutation(J.begin(), J.end()));
    return ans;
}

int main() {
    vector<point<f64>> P(3), Q(3);
    while(cin >> P[0].x) {
        cin >> P[0].y;
        for(int i : rep(1, 3)) cin >> P[i].x >> P[i].y;
        for(int i : rep(0, 3)) cin >> Q[i].x >> Q[i].y;
        int ans = solve(P, Q);
        print(ans == 5 ? "Many" : to_string(ans));
    }
}
accuracy: 1
time_ms: 30
memory_kb: 3452
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#define rng(i, a, b) for (int i = (a); i < (b); i++)
#define rep(i, n) rng(i, 0, (n))
#define vec vector
using namespace std;
typedef long double D;
typedef complex<D> P;
typedef pair<P, P> L;
typedef vector<P> VP;
const D EPS = 1e-9;
#define X real()
#define Y imag()
#define EQ(n, m) (abs((n) - (m)) < EPS)
D dot(P a, P b)
{
    return (conj(a) * b).X;
}
D cross(P a, P b)
{
    return (conj(a) * b).Y;
}
P crosspointLL(P a1, P a2, P b1, P b2)
{
    D d1 = cross(b2 - b1, b1 - a1);
    D d2 = cross(b2 - b1, a2 - a1);
    if (EQ(d1, 0) && EQ(d2, 0))
        return a1;
    if (EQ(d2, 0))
        return P(5000, 5000);
    return a1 + d1 / d2 * (a2 - a1);
}
VP inx, y;
int solve(VP x, int cnt)
{

    vector<bool> okx(3, false), oky(3, false);
    rep(i, 3) rep(j, 3)
    {
        if (oky[j])
            continue;
        if (EQ(x[i], y[j]))
        {
            okx[i] = true;
            oky[j] = true;
        }
    }
    bool ok = true;
    rep(i, 3)
    {
        if (okx[i] == false)
            ok = false;
    }
    if (ok)
    {
        return 0;
    }
    int res = 5;
    rep(i, 3) rep(j, 3)
    {
        if (okx[i] || oky[j])
            continue;
        // x[i]をy[j]に移動
        if (EQ(cross(x[(i + 1) % 3] - x[(i + 2) % 3], y[j] - x[i]), 0))
        {
            VP v = x;
            v[i] = y[j];
            res = min(res, 1 + solve(v, cnt));
        }
        else
        {
            if (okx[(i + 1) % 3] == false)
            {
                VP v = x;
                P z = crosspointLL(x[(i + 2) % 3], x[(i + 2) % 3] + y[j] - x[i], x[(i + 1) % 3], x[(i + 1) % 3] + x[i] - x[(i + 2) % 3]);
                v[(i + 1) % 3] = z;
                if (cnt == 0)
                    res = min(res, 1 + solve(v, cnt + 1));
            }
            if (okx[(i + 2) % 3] == false)
            {
                VP v = x;
                P z = crosspointLL(x[(i + 1) % 3], x[(i + 1) % 3] + y[j] - x[i], x[(i + 2) % 3], x[(i + 2) % 3] + x[i] - x[(i + 1) % 3]);
                v[(i + 2) % 3] = z;
                if (cnt == 0)
                    res = min(res, 1 + solve(v, cnt + 1));
            }
        }
    }
    // rep(i, 3)
    // {
    //     cout << x[i].X << " " << x[i].Y << endl;
    // }
    // cout << endl;
    // cout << res << endl;
    return res;
}

signed main()
{
    int x0;
    while (cin >> x0)
    {
        inx.clear();
        y.clear();
        for (int i = 0; i < 3; i++)
        {
            if (i == 0)
            {
                int v;
                cin >> v;
                inx.emplace_back(x0, v);
            }
            else
            {
                int u, v;
                cin >> u >> v;
                inx.emplace_back(u, v);
            }
        }
        for (int i = 0; i < 3; i++)
        {
            int u, v;
            cin >> u >> v;
            y.emplace_back(u, v);
        }
        int ans = solve(inx, 0);
        if (ans >= 5)
            cout << "Many" << endl;
        else
            cout << ans << endl;
    }
}
accuracy: 1
time_ms: 90
memory_kb: 3436
final_rank: 7

code_snippet: #include <algorithm>
#include <climits>
#include <iostream>
#include <numeric>
#include <utility>
#include <vector>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using lint = ll;
using ulint = ull;
using pii = pair<int, int>;
using pll = pair<lint, lint>;
template <class T>
using V = vector<T>;
template <class T>
using VV = V<V<T>>;
#define For(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(i, n) For(i, 0, n)
template <class T, class U>
bool chmin(T &a, const U &b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T, class U>
bool chmax(T &a, const U &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
T div_floor(T a, T b) {
    if (b < 0) a = -a, b = -b;
    return a >= 0 ? a / b : (a + 1) / b - 1;
}
template <class T>
T div_ceil(T a, T b) {
    if (b < 0) a = -a, b = -b;
    return a <= 0 ? a / b : (a - 1) / b + 1;
}

template <class T>
ostream &operator<<(ostream &os, const V<T> &v) {
    os << "[";
    for (auto d : v) os << d << ", ";
    return os << "]";
}

#include <cmath>
using re = long double;
re EPS = 1e-9;

int sgn(re x) {
    if (x < -EPS) return -1;
    if (x > EPS) return 1;
    return 0;
}
bool eq(re x, re y) { return sgn(x - y) == 0; }
bool ge(re x, re y) { return sgn(x - y) == 1; }
bool le(re x, re y) { return sgn(x - y) == -1; }
bool geq(re x, re y) { return sgn(x - y) >= 0; }
bool leq(re x, re y) { return sgn(x - y) <= 0; }

struct pt {
    re x, y;

    pt(re x = 0, re y = 0) : x(x), y(y) {}

    bool operator==(const pt &p) const { return eq(x, p.x) && eq(y, p.y); }
    bool operator<(const pt &p) const {
        if (eq(x, p.x)) {
            return le(y, p.y);
        }
        return le(x, p.x);
    }

    pt &operator+=(const pt &r) {
        this->x += r.x;
        this->y += r.y;
        return *this;
    }
    pt &operator-=(const pt &r) {
        this->x -= r.x;
        this->y -= r.y;
        return *this;
    }
    pt &operator*=(const re &r) {
        this->x *= r;
        this->y *= r;
        return *this;
    }
    pt &operator/=(const re &r) {
        this->x /= r;
        this->y /= r;
        return *this;
    }

    friend pt operator+(const pt &l, const pt &r) { return pt(l) += r; }
    friend pt operator-(const pt &l, const pt &r) { return pt(l) -= r; }
    friend pt operator*(const pt &l, const re &r) { return pt(l) *= r; }
    friend pt operator/(const pt &l, const re &r) { return pt(l) /= r; }

    friend re operator*(const pt &l, const pt &r) {
        return l.x * r.x + l.y * r.y;
    }
    friend re operator^(const pt &l, const pt &r) {
        return l.x * r.y - l.y * r.x;
    }
};
ostream &operator<<(ostream &os, const pt &p) {
    os << "(";
    os << p.x << ", " << p.y;
    return os << ")";
}

using Vec = pt;
using Pts = V<pt>;

re norm(pt p) { return p * p; }
re abs(pt p) { return sqrt(norm(p)); }
re arg(pt p) { return atan2(p.y, p.x); }
re angle(pt a, pt b) { return arg({a * b, a ^ b}); }

struct Line {
    pt a;
    Vec v;

    Line() {}
    Line(pt a, Vec v) : a(a), v(v) {}
};

pt intersection(Line l1, Line l2) {
    auto [a, v] = l1;
    auto [b, w] = l2;
    auto t = ((b - a) ^ w) / (v ^ w);
    return a + v * t;
}

int main() {
    auto dfs = [&](auto self, int cur, Pts ps, Pts qs, int num, int &ans) {
        if (cur == 3) {
            chmin(ans, num);
            return;
        }
        auto a = ps[cur], b = ps[(cur + 1) % 3], c = ps[(cur + 2) % 3];
        if (a == qs[cur]) {
            self(self, cur + 1, ps, qs, num, ans);
            return;
        }

        auto v = qs[cur] - a;
        if (eq(v ^ (b - c), 0)) {
            ps[cur] = qs[cur];
            self(self, cur + 1, ps, qs, num + 1, ans);
            return;
        }

        {
            auto vs = ps;
            auto p = intersection(Line(c, v), Line(b, c - a));
            ps[cur] = qs[cur];
            ps[(cur + 1) % 3] = p;
            self(self, cur + 1, vs, qs, num + 2, ans);
        }
        {
            auto vs = ps;
            auto p = intersection(Line(b, v), Line(c, b - a));
            ps[cur] = qs[cur];
            ps[(cur + 2) % 3] = p;
            self(self, cur + 1, vs, qs, num + 2, ans);
        }
    };

    Pts ps(3), qs(3);
    while (cin >> ps[0].x) {
        cin >> ps[0].y;
        For(i, 1, 3) cin >> ps[i].x >> ps[i].y;
        rep(i, 3) cin >> qs[i].x >> qs[i].y;

        int ans = 100;
        sort(ps.begin(), ps.end());
        do {
            sort(qs.begin(), qs.end());
            do {
                dfs(dfs, 0, ps, qs, 0, ans);

            } while (next_permutation(qs.begin(), qs.end()));
        } while (next_permutation(ps.begin(), ps.end()));

        if (ans >= 5) {
            puts("Many");
        } else {
            printf("%d\n", ans);
        }
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3536
final_rank: 15

code_snippet: #line 1 "test/geometry/base_rational.test.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1623&lang=jp"

#line 2 "template/template.hpp"

#include <bits/stdc++.h>

#define rep(i, s, n) for (int i = s; i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(), v.end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <typename T> bool chmin(T &a, const T &b) {
    if (a <= b) return false;
    a = b;
    return true;
}
template <typename T> bool chmax(T &a, const T &b) {
    if (a >= b) return false;
    a = b;
    return true;
}

namespace lib {

using namespace std;

}  // namespace lib

// using namespace lib;
#line 2 "utility/rational.hpp"

#line 4 "utility/rational.hpp"

namespace lib{

struct rational{
    rational() : p(0), q(1) {}
    rational(ll n) : p(n), q(1) {}
    rational(ll n, ll m){
        assert(m != 0);
        if (m < 0) n = -n, m = -m;
        ll g = gcd(n,m);
        p = n / g; q = m / g;
    }
    ld val(){
        return ld(p) / ld(q);
    }
    rational& operator+=(const rational& rhs){
        ll g = gcd(q,rhs.q);
        ll np = rhs.q / g * p + q / g * rhs.p;
        ll nq = q / g * rhs.q;
        ll ng = gcd(np,nq);
        p = np/ng, q = nq/ng;
        return *this; 
    }
    rational& operator-=(const rational& rhs){
        (*this) += rational(-rhs.p,rhs.q);
        return *this;
    }
    rational& operator*=(const rational& rhs){
        ll g1 = gcd(q,rhs.p), g2 = gcd(p,rhs.q);
        ll np = p / g2 * rhs.p / g1;
        ll nq = q / g1 * rhs.q / g2;
        p = np, q = nq;
        return *this;
    }
    rational& operator/=(const rational& rhs){
        (*this) *= rational(rhs.q,rhs.p);
        return *this;
    }
    rational operator+() const {return *this;}
    rational operator-() const {return rational() - *this;}
    friend rational operator+(const rational& lhs, const rational& rhs) {
        return rational(lhs) += rhs;
    }
    friend rational operator-(const rational& lhs, const rational& rhs) {
        return rational(lhs) -= rhs;
    }
    friend rational operator*(const rational& lhs, const rational& rhs) {
        return rational(lhs) *= rhs;
    }
    friend rational operator/(const rational& lhs, const rational& rhs) {
        return rational(lhs) /= rhs;
    }
    friend bool operator==(const rational& lhs, const rational& rhs) {
        return lhs.p == rhs.p && lhs.q == rhs.q;
    }
    friend bool operator!=(const rational& lhs, const rational& rhs) {
        return lhs.p != rhs.p || lhs.q != rhs.q;
    }
    friend bool operator< (const rational lhs, const rational rhs) {
        return less_than(lhs,rhs);
    }
    friend bool operator> (const rational lhs, const rational rhs) {
        return less_than(rhs,lhs);
    }
    friend bool operator<= (const rational lhs, const rational rhs) {
        return lhs == rhs || lhs < rhs;
    }
    friend bool operator>= (const rational lhs, const rational rhs) {
        return lhs == rhs || lhs > rhs;
    }
    friend std::ostream &operator<<(std::ostream &os,const rational&r) {
        return os << r.p << " / " << r.q;
    }
  private:
    ll p, q;
    static bool less_than(rational lhs, rational rhs){
        __int128_t lv = __int128_t(lhs.p) * __int128_t(rhs.q);
        __int128_t rv = __int128_t(lhs.q) * __int128_t(rhs.p);
        return lv < rv;
    }
};


} // namespace lib
#line 2 "geometry/base_arbitary.hpp"

#line 4 "geometry/base_arbitary.hpp"

namespace lib {

template<typename T>
struct Vec {
    T x, y;
    Vec (T _x = T(0), T _y = T(0)) : x(_x), y(_y) {}
    Vec& operator*=(const T& a){
        x *= a;
        y *= a;
        return *this;
    }
    Vec& operator/=(const T& a){
        x /= a;
        y /= a;
        return *this;
    }
    Vec& operator+=(const Vec& rhs) {
        x += rhs.x;
        y += rhs.y;
        return *this;
    }
    Vec& operator-=(const Vec& rhs) {
        x -= rhs.x;
        y -= rhs.y;
        return *this;
    }
    friend bool operator==(const Vec& lhs, const Vec& rhs) {
        return lhs.x == rhs.x && lhs.y == rhs.y;
    }
    friend bool operator!=(const Vec& lhs, const Vec& rhs) {
        return lhs.x != rhs.x || lhs.y != rhs.y;
    }
    friend Vec operator+(const Vec& lhs, const Vec& rhs) {
        return Vec(lhs) += rhs;
    }
    friend Vec operator-(const Vec& lhs, const Vec& rhs) {
        return Vec(lhs) -= rhs;
    }
    friend Vec operator*(const Vec& lhs, const T& rhs) {
        return Vec(lhs) *= rhs;
    }
    friend Vec operator*(const T& rhs, const Vec& lhs) {
        return Vec(lhs) *= rhs;
    }
    friend Vec operator/(const Vec& lhs, const T& rhs) {
        return Vec(lhs) /= rhs;
    }
    friend Vec operator/(const T& rhs, const Vec& lhs) {
        return Vec(lhs) /= rhs;
    }
};

template<typename T>
T dot(const Vec<T> &a, const Vec<T> &b){
    return a.x * b.x + a.y * b.y;
}

// cross > 0 : counter clockwise a -> b
template<typename T>
T cross(const Vec<T> &a, const Vec<T> &b){
    return a.x * b.y - a.y * b.x;
}

template<typename T>
ld abs(const Vec<T> &a){
    return sqrtl(a.x*a.x+a.y*a.y);
}

template<typename T>
T norm(const Vec<T> &a){
    return a.x*a.x+a.y*a.y;
}

template<typename T>
struct Line {
    Vec<T> p, q;
};

template<typename T>
int intersection(const Line<T> &a, const Line<T> &b){
    if (cross(a.p-a.q,b.p-b.q) == 0){
        if (cross(a.p-b.p,a.q-b.p) == 0) return 2;
        return 0;
    }
    return 1;
}

// intersection == 1 (cross(a.p-a.q,b.p-b.q) != 0)
template<typename T>
Vec<T> cross_point(const Line<T> &a, const Line<T> &b){
    Vec<T> va = a.p-a.q, vb = b.p-b.q;
    Vec<T> ba = b.p-a.q;
    T alpha = cross(ba,vb) / cross(va,vb);
    return alpha * a.p + (1 - alpha) * a.q;
}


} // namespace lib
#line 6 "test/geometry/base_rational.test.cpp"

using namespace lib;
using vec = Vec<rational>;
using line = Line<rational>;

const vector<vector<int>> order = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};

int main(){
    while (true){
        vector<vec> ia(3), b(3);
        rep(i,0,6){
            ll x, y; cin >> x >> y;
            if (!cin) return 0;
            (i < 3 ? ia[i] : b[i-3]) = vec(x,y);
        }
        int ans = 5;
        for (auto fid : order) for (auto tid : order) rep(j,0,2){
            auto a = ia;
            int cur = 0;
            rep(i,0,3){
                int f = fid[i], t = tid[i];
                if (a[f] == b[t]) continue;
                cur++;
                int p = (f+1)%3, q = (f+2)%3;
                if (cross(a[p]-a[q],b[t]-a[f]) == 0){
                    a[f] = b[t];
                    continue;
                }
                cur++;
                if (j == 1) swap(p,q);
                line l1({a[p],a[p]+a[f]-b[t]}), l2({a[q],a[q]+a[f]-a[p]});
                if (intersection(l1,l2) == 1){
                    a[q] = cross_point(l1,l2);
                    a[f] = b[t];
                }
                else {
                    cur = 5;
                    break;
                }
            }
            chmin(ans,cur);
        }
        if (ans == 5) cout << "Many" << endl;
        else cout << ans << endl;
    }
}
accuracy: 1
time_ms: 1530
memory_kb: 3460
final_rank: 18

code_snippet: #line 1 "test/geometry/base_rational.test.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1623&lang=jp"

#line 2 "template/template.hpp"

#include <bits/stdc++.h>

#define rep(i, s, n) for (int i = s; i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(), v.end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <typename T> bool chmin(T &a, const T &b) {
    if (a <= b) return false;
    a = b;
    return true;
}
template <typename T> bool chmax(T &a, const T &b) {
    if (a >= b) return false;
    a = b;
    return true;
}

namespace lib {

using namespace std;

}  // namespace lib

// using namespace lib;
#line 2 "utility/rational.hpp"

#line 4 "utility/rational.hpp"

namespace lib{

struct rational{
    rational() : p(0), q(1) {}
    rational(ll n) : p(n), q(1) {}
    rational(ll n, ll m){
        assert(m != 0);
        if (m < 0) n = -n, m = -m;
        ll g = gcd(n,m);
        p = n / g; q = m / g;
    }
    ld val(){
        return ld(p) / ld(q);
    }
    rational& operator+=(const rational& rhs){
        ll g = gcd(q,rhs.q);
        ll np = rhs.q / g * p + q / g * rhs.p;
        ll nq = q / g * rhs.q;
        ll ng = gcd(np,nq);
        p = np/ng, q = nq/ng;
        return *this; 
    }
    rational& operator-=(const rational& rhs){
        (*this) += rational(-rhs.p,rhs.q);
        return *this;
    }
    rational& operator*=(const rational& rhs){
        ll g1 = gcd(q,rhs.p), g2 = gcd(p,rhs.q);
        ll np = p / g2 * rhs.p / g1;
        ll nq = q / g1 * rhs.q / g2;
        p = np, q = nq;
        return *this;
    }
    rational& operator/=(const rational& rhs){
        (*this) *= rational(rhs.q,rhs.p);
        return *this;
    }
    rational operator+() const {return *this;}
    rational operator-() const {return rational() - *this;}
    friend rational operator+(const rational& lhs, const rational& rhs) {
        return rational(lhs) += rhs;
    }
    friend rational operator-(const rational& lhs, const rational& rhs) {
        return rational(lhs) -= rhs;
    }
    friend rational operator*(const rational& lhs, const rational& rhs) {
        return rational(lhs) *= rhs;
    }
    friend rational operator/(const rational& lhs, const rational& rhs) {
        return rational(lhs) /= rhs;
    }
    friend bool operator==(const rational& lhs, const rational& rhs) {
        return lhs.p == rhs.p && lhs.q == rhs.q;
    }
    friend bool operator!=(const rational& lhs, const rational& rhs) {
        return lhs.p != rhs.p || lhs.q != rhs.q;
    }
    friend bool operator< (const rational lhs, const rational rhs) {
        return less_than(lhs,rhs);
    }
    friend bool operator> (const rational lhs, const rational rhs) {
        return less_than(rhs,lhs);
    }
    friend bool operator<= (const rational lhs, const rational rhs) {
        return lhs == rhs || lhs < rhs;
    }
    friend bool operator>= (const rational lhs, const rational rhs) {
        return lhs == rhs || lhs > rhs;
    }
    friend std::ostream &operator<<(std::ostream &os,const rational&r) {
        return os << r.p << " / " << r.q;
    }
  private:
    ll p, q;
    static bool less_than(rational lhs, rational rhs){
        __int128_t lv = __int128_t(lhs.p) * __int128_t(rhs.q);
        __int128_t rv = __int128_t(lhs.q) * __int128_t(rhs.p);
        return lv < rv;
    }
};


} // namespace lib
#line 2 "geometry/base_arbitary.hpp"

#line 4 "geometry/base_arbitary.hpp"

namespace lib {

template<typename T>
struct Vec {
    T x, y;
    Vec (T _x = T(0), T _y = T(0)) : x(_x), y(_y) {}
    Vec& operator*=(const T& a){
        x *= a;
        y *= a;
        return *this;
    }
    Vec& operator/=(const T& a){
        x /= a;
        y /= a;
        return *this;
    }
    Vec& operator+=(const Vec& rhs) {
        x += rhs.x;
        y += rhs.y;
        return *this;
    }
    Vec& operator-=(const Vec& rhs) {
        x -= rhs.x;
        y -= rhs.y;
        return *this;
    }
    friend bool operator==(const Vec& lhs, const Vec& rhs) {
        return lhs.x == rhs.x && lhs.y == rhs.y;
    }
    friend bool operator!=(const Vec& lhs, const Vec& rhs) {
        return lhs.x != rhs.x || lhs.y != rhs.y;
    }
    friend Vec operator+(const Vec& lhs, const Vec& rhs) {
        return Vec(lhs) += rhs;
    }
    friend Vec operator-(const Vec& lhs, const Vec& rhs) {
        return Vec(lhs) -= rhs;
    }
    friend Vec operator*(const Vec& lhs, const T& rhs) {
        return Vec(lhs) *= rhs;
    }
    friend Vec operator*(const T& rhs, const Vec& lhs) {
        return Vec(lhs) *= rhs;
    }
    friend Vec operator/(const Vec& lhs, const T& rhs) {
        return Vec(lhs) /= rhs;
    }
    friend Vec operator/(const T& rhs, const Vec& lhs) {
        return Vec(lhs) /= rhs;
    }
};

template<typename T>
T dot(const Vec<T> &a, const Vec<T> &b){
    return a.x * b.x + a.y * b.y;
}

// cross > 0 : counter clockwise a -> b
template<typename T>
T cross(const Vec<T> &a, const Vec<T> &b){
    return a.x * b.y - a.y * b.x;
}

template<typename T>
ld abs(const Vec<T> &a){
    return sqrtl(a.x*a.x+a.y*a.y);
}

template<typename T>
T norm(const Vec<T> &a){
    return a.x*a.x+a.y*a.y;
}

template<typename T>
struct Line {
    Vec<T> p, q;
};

template<typename T>
int intersection(const Line<T> &a, const Line<T> &b){
    if (cross(a.p-a.q,b.p-b.q) == 0){
        if (cross(a.p-b.p,a.q-b.p) == 0) return 2;
        return 0;
    }
    return 1;
}

// intersection == 1
template<typename T>
Vec<T> cross_point(const Line<T> &a, const Line<T> &b){
    Vec<T> va = a.p-a.q, vb = b.p-b.q;
    Vec<T> ba = b.p-a.q;
    T alpha = cross(ba,vb) / cross(va,vb);
    return alpha * a.p + (1 - alpha) * a.q;
}


} // namespace lib
#line 6 "test/geometry/base_rational.test.cpp"

using namespace lib;
using vec = Vec<rational>;
using line = Line<rational>;

const vector<vector<int>> order = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};

int main(){
    while (true){
        vector<vec> ia(3), b(3);
        rep(i,0,6){
            ll x, y; cin >> x >> y;
            if (!cin) return 0;
            (i < 3 ? ia[i] : b[i-3]) = vec(x,y);
        }
        int ans = 5;
        for (auto fid : order) for (auto tid : order) rep(j,0,2){
            auto a = ia;
            int cur = 0;
            rep(i,0,3){
                int f = fid[i], t = tid[i];
                if (a[f] == b[t]) continue;
                cur++;
                int p = (f+1)%3, q = (f+2)%3;
                if (cross(a[p]-a[q],b[t]-a[f]) == 0){
                    a[f] = b[t];
                    continue;
                }
                cur++;
                if (j == 1) swap(p,q);
                line l1({a[p],a[p]+a[f]-b[t]}), l2({a[q],a[q]+a[f]-a[p]});
                if (intersection(l1,l2) == 1){
                    a[q] = cross_point(l1,l2);
                    a[f] = b[t];
                }
                else {
                    cur = 5;
                    break;
                }
            }
            chmin(ans,cur);
        }
        if (ans == 5) cout << "Many" << endl;
        else cout << ans << endl;
    }
}
accuracy: 1
time_ms: 1530
memory_kb: 3316
final_rank: 3

code_snippet: #line 1 "f.cpp"
#include<bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < int(n); ++i)
#define repp(i,n,m) for (int i = m; i < int(n); ++i)
#define reb(i,n) for (int i = int(n)-1; i >= 0; --i)
#define all(v) v.begin(),v.end()

using namespace std;
using ll = long long;
using ld = long double;
using P = pair<int,int>;
using PL = pair<ll,ll>;

template<class T>istream &operator>>(istream &is,vector<T> &v){for(auto &e:v)is>>e;return is;}
template<typename T1, typename T2>void print(pair<T1,T2> a);
template<typename T>void print(vector<T> v);
template<typename T>void print(vector<vector<T>> v);
void print(){ putchar(' '); }
void print(bool a){ printf("%d", a); }
void print(int a){ printf("%d", a); }
void print(long a){ printf("%ld", a); }
void print(long long a){ printf("%lld", a); }
void print(char a){ printf("%c", a); }
void print(char a[]){ printf("%s", a); }
void print(const char a[]){ printf("%s", a); }
void print(long double a){ printf("%.15Lf", a); }
void print(const string& a){ for(auto&& i : a) print(i); }
void print(unsigned int a){ printf("%u", a); }
void print(__int128_t a){print((long long)(a));}
template<class T> void print(const T& a){ cout << a;}
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
template<typename T1,typename T2>void print(pair<T1,T2> a){print(a.first);print(),print(a.second);}
template<typename T>void print(vector<T> v){for(auto ite=v.begin();ite!=v.end();){print(*ite);if(++ite!=v.end())print();}}
template<typename T>void print(vector<vector<T>> v){for(auto ite=v.begin();ite!=v.end();){print(*ite);if(++ite!=v.end())out();}}

template<typename T>bool chmin(T &a,const T &b){if(a>b){a=b;return true;}return false;}
template<typename T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}

void fast_io(){cin.tie(0); ios::sync_with_stdio(0); cout<<fixed<<setprecision(20);}

namespace noya2{

const int INF = 1001001007;
const long long mod1 = 998244353;
const long long mod2 = 1000000007;
const long long inf = 2e18;
const long double pi = 3.14159265358979323;
const long double eps = 1e-7;
vector<int> dx = {0,1,0,-1,1,1,-1,-1};
vector<int> dy = {1,0,-1,0,1,-1,-1,1};
const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string alp = "abcdefghijklmnopqrstuvwxyz";
const string NUM = "0123456789";
void o(){out("!?");}
void yn(bool f){out(f ? "Yes" : "No");}
void YN(bool F){out(F ? "YES" : "NO");}
template<typename T>bool range(T a,T b,T x){return (a<=x&&x<b);}
template<typename T>bool rrange(T a,T b,T c,T d,T x,T y){return (range(a,c,x)&&range(b,d,y));}

} // namespace noya2
using namespace noya2;

#line 2 "rational.hpp"

namespace noya2{

template<typename T>
struct rational{
    rational() : p(T(0)), q(T(1)) {}
    rational(T n) : p(n), q(T(1)) {}
    rational(T n, T m){
        assert(m != T(0));
        if (m < T(0)) n = -n, m = -m;
        T g = gcd(n,m);
        p = n / g; q = m / g;
    }
    T num(){return p;}
    T den(){return q;}
    void set_num(T n){
        p = n;
        T g = gcd(p,q);
        p /= g, q /= g;
    }
    void set_den(T n){
        assert(n != T(0));
        q = n;
        T g = gcd(p,q);
        p /= g, q /= g;
    }
    long double val(){
        return (long double)(p) / (long double)(q);
    }
    rational& operator+=(const rational& rhs){
        T g = gcd(q,rhs.q);
        T np = rhs.q / g * p + q / g * rhs.p;
        T nq = q / g * rhs.q;
        T ng = gcd(np,nq);
        p = np/ng, q = nq/ng;
        return *this; 
    }
    rational& operator-=(const rational& rhs){
        T g = gcd(q,rhs.q);
        T np = rhs.q / g * p - q / g * rhs.p;
        T nq = q / g * rhs.q;
        T ng = gcd(np,nq);
        p = np/ng, q = nq/ng;
        return *this;
    }
    rational& operator*=(const rational& rhs){
        T g1 = gcd(q,rhs.p), g2 = gcd(p,rhs.q);
        T np = p / g2 * rhs.p / g1;
        T nq = q / g1 * rhs.q / g2;
        p = np, q = nq;
        return *this;
    }
    rational& operator/=(const rational& rhs){
        assert(rhs.p != T(0));
        T g1 = gcd(q,rhs.q), g2 = gcd(p,rhs.p);
        T np = p / g2 * rhs.q / g1;
        T nq = q / g1 * rhs.p / g2;
        p = np, q = nq;
        return *this;
    }
    rational operator+() const {return *this;}
    rational operator-() const {return rational() - *this;}
    friend rational operator+(const rational& lhs, const rational& rhs) {
        return rational(lhs) += rhs;
    }
    friend rational operator-(const rational& lhs, const rational& rhs) {
        return rational(lhs) -= rhs;
    }
    friend rational operator*(const rational& lhs, const rational& rhs) {
        return rational(lhs) *= rhs;
    }
    friend rational operator/(const rational& lhs, const rational& rhs) {
        return rational(lhs) /= rhs;
    }
    friend bool operator==(const rational& lhs, const rational& rhs) {
        return lhs.p == rhs.p && lhs.q == rhs.q;
    }
    friend bool operator!=(const rational& lhs, const rational& rhs) {
        return lhs.p != rhs.p || lhs.q != rhs.q;
    }
    friend bool operator< (const rational lhs, const rational rhs) {
        return less_than(lhs,rhs);
    }
    friend bool operator> (const rational lhs, const rational rhs) {
        return less_than(rhs,lhs);
    }
    friend bool operator<= (const rational lhs, const rational rhs) {
        return lhs == rhs || lhs < rhs;
    }
    friend bool operator>= (const rational lhs, const rational rhs) {
        return lhs == rhs || lhs > rhs;
    }
    friend std::ostream &operator<<(std::ostream &os,const rational&r) {
        return os << r.p << " / " << r.q;
    }
  private:
    T p, q;
    T gcd(T a,T b){if(a<T(0))return gcd(-a,b);if(b<T(0))return gcd(a,-b);return _gcd(a,b);}
    T _gcd(T a,T b){return b?_gcd(b,a%b):a;}
    static bool less_than(rational lhs, rational rhs){
        __int128_t lv = __int128_t(lhs.p) * __int128_t(rhs.q);
        __int128_t rv = __int128_t(lhs.q) * __int128_t(rhs.p);
        return lv < rv;
    }
};

using rat = rational<long long>;

} // namespace noya2
#line 2 "geometry2D.hpp"

#line 6 "geometry2D.hpp"

#line 2 "math.hpp"

#line 6 "math.hpp"

namespace noya2{

using namespace std;
using ll = long long;

template<typename T> T sqrt_safe(T x){ // floor(sqrt(x))
    assert(x >= T(0));
    if (x <= T(1)) return x;
    T tmp = (T)(sqrtl((long double)(x))) + T(2);
    while (tmp--){
        if (tmp * tmp <= x) break;
    }
    return tmp;
}

ll mod_safe(ll a, ll m){ // m >= 1, 0 <= mod_safe(a,m) < m, mod_safe(a,m) = a (mod m)
    ll res = a % m;
    if (res < 0) res += m;
    return res;
}
ll modpow(ll x, ll n, ll mod){
    x = mod_safe(x,mod);
    if (n == 0) return 1;
    ll res = modpow(x,n/2,mod);
    res = (res * res) % mod;
    if (n % 2 == 1) res = (res * x) % mod;
    return res;
}

ll naive_gcd(ll a, ll b){ return b ? naive_gcd(b, a % b) : a; }

// gcd(N >= 0, 0) = N, especialy gcd(0, 0) = 0
ll gcd_safe(ll a, ll b){ return naive_gcd(abs(a),abs(b)); }
ll lcm_safe(ll a, ll b){ return a / gcd_safe(a,b) * b; }

void ext_gcd1_plus(ll a, ll b, ll &x, ll &y){ // gcd(a,b) = 1, a >= 0, b >= 0, ax + by = 1
    if (b == 0){ // a = 1
        x = 1, y = 0;
        return ;
    }
    ext_gcd1_plus(b, a%b, y, x);
    x = mod_safe(x,b);
    y = (1 - a * x) / b;
}
void ext_gcd1_minus(ll a, ll b, ll &x, ll &y){ // gcd(a,b) = 1, a >= 0, b >= 0, ax - by = 1
    if (b == 0){ // a = 1
        x = 1, y = 0;
        return ;
    }
    ext_gcd1_plus(b, a%b, y, x);
    x = mod_safe(x,b);
    y = (a * x - 1) / b;
}

pair<ll,ll> ext_gcd(ll a, ll b, ll c){ // ax + by = c, |a|,|b|,|c| < 1e9, x <= max(|B|,|C|), y <= max(|A|,|C|)
    if (a < 0) return ext_gcd(-a,-b,-c);
    if (c < 0){
        pair<ll,ll> res = ext_gcd(a,b,-c);
        res.first = -res.first, res.second = -res.second;
        return res;
    }
    if (c == 0) return pair<ll,ll>(0,0);
    if (a == 0 && b == 0) return pair<ll,ll>(0,0); // answer not exist
    ll g = gcd_safe(a,b);
    if (c % g != 0) return pair<ll,ll>(0,0); // answer not exist
    a /= g, b /= g, c /= g;
    ll x, y;
    if (b == 0) return pair<ll,ll>(c,0);
    if (b > 0) ext_gcd1_plus(a,b,x,y);
    else ext_gcd1_minus(a,-b,x,y);
    x = mod_safe(x*c,abs(b));
    y = (c - a * x) / b;
    return pair<ll,ll>(x,y);
}

template<typename T>
T ceil_safe(T p, T q);

template<typename T>
T floor_safe(T p, T q){
    if (q < T(0)) return floor_safe(-p,-q);
    if (p >= T(0)) return p / q;
    return -ceil_safe(-p,q);
}

template<typename T>
T ceil_safe(T p, T q){
    if (q < T(0)) return ceil_safe(-p,-q);
    if (p >= T(0)) return (p + q - 1) / q;
    return -floor_safe(-p,q);
}

struct Eratosthenes{
    static vector<int> table;
    Eratosthenes (int Nmax = -1) {init(Nmax);}
    static void init(int Nmax){
        if (!table.empty()) return ;
        table.resize(Nmax+1,0);
        table[0] = 1, table[1] = 1;
        for (int p = 2; p <= Nmax; p++){
            if (table[p] != 0) continue;
            for (int j = p; j <= Nmax; j += p){
                table[j] = p;
            }
        }
    }
};
vector<int>Eratosthenes::table = vector<int>(0);

void build_eratosthenes(const int Nmax){Eratosthenes::init(Nmax);}

vector<pair<int,int>> fast_prime_factorization(int N){
    int pre = -1, cnt = 0;
    vector<pair<int,int>> res;
    while(true) {
        if (N == 1){
            if (cnt > 0) res.emplace_back(pre,cnt);
            break;
        }
        int div = Eratosthenes::table[N];
        if (pre != div){
            if (cnt > 0) res.emplace_back(pre,cnt);
            pre = div, cnt = 1;
        }
        else cnt++;
        N /= div;
    }
    return res;
}

vector<int> fast_divisor_enumeration(int N){
    auto pes = fast_prime_factorization(N);
    vector<int> res = {1};
    for (auto pe : pes){
        vector<int> nres;
        for (auto x : res){
            for (int _t = 0; _t <= pe.second; _t++){
                nres.emplace_back(x);
                x *= pe.first;
            }
        }
        swap(res,nres);
    }
    return res;
}

bool fast_is_prime(int N){
    if (N <= 1) return false;
    return Eratosthenes::table[N] == N;
}

vector<int> mobius(int N){
    vector<int> res(N+1,0);
    res[1] = 1;
    for (int p = 2; p <= N; p++){
        if (fast_is_prime(p)){
            for (int i = N/p; i > 0; i--){
                res[i*p] = -res[i];
            }
        }
    }
    return res;
};

vector<pair<ll,int>> prime_factorization(ll N){
    vector<pair<ll,int>> res;
    ll iN = N;
    for (ll d = 2; d * d <= N; d++){
        if (iN % d != 0) continue;
        if (iN == 1) break;
        int ie = 0;
        while (iN % d == 0) iN /= d, ie++;
        res.emplace_back(d,ie);
    }
    if (iN != 1) res.emplace_back(iN,1);
    return res;
}

vector<ll> divisor_enumeration(ll N){
    vector<ll> res;
    for (ll d = 1; d * d <= N; d++){
        if (N % d != 0) continue;
        res.emplace_back(d);
        if (d * d != N) res.emplace_back(N/d);
    }
    return res;
}

bool is_prime(ll N){
    if (N <= 1) return false;
    if (N <= 3) return true;
    if (N % 2 == 0) return false;
    for (ll d = 3; d * d <= N; d += 2){
        if (N % d == 0) return false;
    }
    return true;
}

}// namespace noya2
#line 8 "geometry2D.hpp"

namespace noya2{

using namespace std;
using ld = long double;

template<typename T>
struct Vec {
    T x, y;
    Vec (T _x = T(0), T _y = T(0)) : x(_x), y(_y) {}
    Vec& operator*=(const T& a){
        x *= a;
        y *= a;
        return *this;
    }
    Vec& operator/=(const T& a){
        x /= a;
        y /= a;
        return *this;
    }
    Vec& operator+=(const Vec& rhs) {
        x += rhs.x;
        y += rhs.y;
        return *this;
    }
    Vec& operator-=(const Vec& rhs) {
        x -= rhs.x;
        y -= rhs.y;
        return *this;
    }
    friend Vec operator+(const Vec& lhs, const Vec& rhs) {
        return Vec(lhs) += rhs;
    }
    friend Vec operator-(const Vec& lhs, const Vec& rhs) {
        return Vec(lhs) -= rhs;
    }
    friend Vec operator*(const Vec& lhs, const T& rhs) {
        return Vec(lhs) *= rhs;
    }
    friend Vec operator*(const T& rhs, const Vec& lhs) {
        return Vec(lhs) *= rhs;
    }
    friend Vec operator/(const Vec& lhs, const T& rhs) {
        return Vec(lhs) /= rhs;
    }
    friend Vec operator/(const T& rhs, const Vec& lhs) {
        return Vec(lhs) /= rhs;
    }
    ld norm(){
        return sqrtl(ld(x*x+y*y));
    }
    T norm2(){
        return x*x+y*y;
    }
};

template<typename T>
T dot(const Vec<T> &a, const Vec<T> &b){
    return a.x * b.x + a.y * b.y;
}

// cross > 0 : counter clockwise a -> b
template<typename T>
T cross(const Vec<T> &a, const Vec<T> &b){
    return a.x * b.y - a.y * b.x;
}

// T = int, ll
// number of lattice points ( point(x,y) s.t. x in Z and y in Z ) on Vec a
template<typename T>
T lattice_points(const Vec<T> &a){
    return gcd_safe(a.x,a.y) + 1;
}

// e : vec(OX)
// orthant k : [ pi/2 * k, pi/2 * (k+1) ) rad
// orthant 4 is NOT expected
template<typename T>
int orthant(const Vec<T> &e, const Vec<T> &p){
    T _dot = dot(e,p), _cross = cross(e,p);
    if (_dot >  0 && _cross >= 0) return 0;
    if (_dot <= 0 && _cross >  0) return 1;
    if (_dot <  0 && _cross <= 0) return 2;
    if (_dot >= 0 && _cross <  0) return 3;
    return 4;
}

// usage : 
//   vector<Vec<ll>> vec;
//   sort(vec.begin(),vec.end(),comp_for_argument_sort<ll>);
template<typename T>
bool comp_for_argument_sort(const Vec<T> &lhs, const Vec<T> &rhs){
    int pl = orthant(Vec<T>(1,0),lhs), pr = orthant(Vec<T>(1,0),rhs);
    if (pl == pr){
        return cross(lhs,rhs) > 0;
    }
    return pl < pr;
}

// DISTINCT points are given
// ans[0] --- ans[1] --- ... --- ans[k-1] --- ans[k] --- ans[0]
// upper_hull --- lower_hull
// upper_hull : x is from small to large
// lower hull : x is from large to small
// points rearranged counter clockwise
template<typename T>
vector<Vec<T>> convex_hull(vector<Vec<T>> a){
    int n = a.size();
    if (n <= 2) return a;
    using vec = Vec<T>;
    auto comp = [&](vec lhs, vec rhs){
        if (lhs.x == rhs.x) return lhs.y < rhs.y;
        return lhs.x < rhs.x;
    };
    sort(a.begin(),a.end(),comp);
    stack<int> uid, did;
    uid.push(0);
    vec ri = a[n-1];
    for (int i = 1; i < n-1; i++){
        vec le = a[uid.top()];
        if (cross(ri-le,a[i]-le) > 0){
            while (uid.size() >= 2){
                int test = uid.top(); uid.pop();
                vec from = a[uid.top()];
                if (cross(a[i]-from,a[test]-from) > 0){
                    uid.push(test);
                    break;
                }
            }
            uid.push(i);
        }
    }
    did.push(0);
    for (int i = 1; i < n-1; i++){
        vec le = a[did.top()];
        if (cross(ri-le,a[i]-le) < 0){
            while (did.size() >= 2){
                int test = did.top(); did.pop();
                vec from = a[did.top()];
                if (cross(a[i]-from,a[test]-from) < 0){
                    did.push(test);
                    break;
                }
            }
            did.push(i);
        }
    }
    vector<int> ids(1,n-1);
    while (!did.empty()) ids.emplace_back(did.top()), did.pop();
    reverse(ids.begin(),ids.end());
    while (!uid.empty()) ids.emplace_back(uid.top()), uid.pop();
    ids.pop_back();
    vector<vec> ans(ids.size());
    for (int i = 0; i < (int)(ids.size()); i++){
        ans[i] = a[ids[i]];
    }
    return ans;
}

using ll = long long;
struct Line{
    ll a, b, c; // ax + by = c
    void norm(){ // a >= 0, if (a == 0) -> b >= 0, gcd(a,b,c) = 1
        if (a < 0) a = -a, b = -b, c = -c;
        if (a == 0) if (b < 0) b = -b, c = -c;
        ll g = gcd_safe(gcd_safe(a,b),c);
        a /= g, b /= g, c /= g;
    }
    Line (ll _a = 1, ll _b = 0, ll _c = 0) : a(_a), b(_b), c(_c) {
        assert(_a != 0 || _b != 0);
        norm();
    }
    Line (ll x1, ll y1, ll x2, ll y2){ // --- (x1,y1) --- (x2,y2) ---
        assert(x1 != x2 || y1 != y2);
        ll wx = x2 - x1, wy = y2 - y1;
        ll wg = gcd_safe(wx,wy);
        a = wy / wg, b = -wx / wg;
        c = a * x1 + b * y1;
        norm();
    }
    static Line get_Line(ll x1, ll y1, ll ex, ll ey){ // y = ey/ex (x - x1) + y1 
        return Line(ey,-ex,ey*x1-ex*y1);
    }
    static Line vertical_Line(ll x1, ll y1, ll x2, ll y2){ // perpendicular bisector
        ll ex = y2 - y1, ey = x1 - x2;
        return Line(ey*2,-ex*2,ey*(x1+x2)-ex*(y1+y2));
    }
    void slide(const Vec<ll> &v){ // ax + by = c -> a(x - vx) + b(y - vy) = c
        c += a * v.x + b * v.y;
    }
    //Vec<ll> normal_Vec(const Vec<ll> &from){}
    ld dist_from_point(const Vec<ll> &from){
        return abs(ld(a) * ld(from.x) + ld(b) * ld(from.y) - ld(c)) / sqrtl(ld(a*a+b*b));
    }
    bool operator<(const Line &rhs) const { // to use set or map for Line
        if (a == rhs.a){
            if (b == rhs.b) return c < rhs.c;
            return b < rhs.b;
        }
        return a < rhs.a;
    }
};

struct Directed_Line{
    Vec<ll> from, direct; // Line : from + k * direct
    void normalize(){
        ll g = gcd_safe(direct.x,direct.y);
        direct /= g;
    }
    Directed_Line (ll x_from = 0, ll y_from = 0, ll x_to = 1, ll y_to = 0){
        from.x = x_from, from.y = y_from;
        direct.x = x_to - x_from;
        direct.y = y_to - y_from;
        normalize();
    }
    Directed_Line (Vec<ll> _from, Vec<ll> _to){
        from = _from;
        direct = _to - _from;
        normalize();
    }
    bool in(const Vec<ll> &r, bool on){
        ll z = cross(direct,r-from);
        if (z == 0) return on;
        return z > 0;
    }
    bool slide_if_smaller(const Vec<ll> &v){
        if (in(from+v,false)){
            from += v;
            return true;
        }
        return false;
    }
    Directed_Line slide(const Vec<ll> &v){
        auto res = *this;
        res.from += v;
        return res;
    }
};


// two line segments AB and CD shared at least one point
bool check_intersection(ll ax, ll ay, ll bx, ll by, ll cx, ll cy, ll dx, ll dy){
    // both AB and CD are parallel to y-axis 
    if (ax == bx && cx == dx){
        if (ax != cx) return false;
        return (min(ay,by) <= max(cy,dy)) && (min(cy,dy) <= max(ay,by));
    }
    // change to cx != dx 
    if (cx == dx){
        swap(ax,cx), swap(ay,cy);
        swap(bx,dx), swap(by,dy);
    }
    // change to ax >= bx
    if (ax < bx){
        swap(ax,bx), swap(ay,by);
    }
    // change to cx >= dx
    if (cx < dx){
        swap(cx,dx), swap(cy,dy);
    }
    // AB is parallel to y-axis
    if (ax == bx){
        __int128_t lv = __int128_t(cx - dx) * __int128_t(min(ay,by) - dy);
        __int128_t mv = __int128_t(cy - dy) * __int128_t(ax - dx);
        __int128_t rv = __int128_t(cx - dx) * __int128_t(max(ay,by) - dy);
        return lv <= mv && mv <= rv;
    }
    // both AB and CD are NOT parallel to y-axis
    ll gAB = gcd_safe(ay-by,ax-bx);
    ll pAB = (ax-bx) / gAB, qAB = (ay-by) / gAB;
    ll gCD = gcd_safe(cy-dy,cx-dx);
    ll pCD = (cx-dx) / gCD, qCD = (cy-dy) / gCD;
    //   AB and CD are parallel
    if (pAB == pCD && qAB == qCD){
        if (bx == dx){
            return by == dy;
        }
        ll gDB = gcd_safe(dy-by,dx-bx);
        ll pDB = (dx-bx) / gDB, qDB = (dy-by) / gDB;
        if (bx > dx){
            pDB = -pDB;
            qDB = -qDB;
        }
        // Line AB = Line CD
        if (pDB == pAB && qDB == qAB){
            return bx <= cx && dx <= ax;
        }
        return false;
    }
    //   AB and CD are NOT parallel
    __int128_t tal = __int128_t(cx - dx) * __int128_t(ay - cy); // ta = tal - tar
    __int128_t tar = __int128_t(cy - dy) * __int128_t(ax - cx); // ta <=> 0  ==  tal <=> tar
    __int128_t tbl = __int128_t(cx - dx) * __int128_t(by - cy); // tb = tbl - tbr
    __int128_t tbr = __int128_t(cy - dy) * __int128_t(bx - cx); // tb <=> 0  ==  tbl <=> tbr
    __int128_t tcl = __int128_t(ax - bx) * __int128_t(cy - ay); // tc = tcl - tcr
    __int128_t tcr = __int128_t(ay - by) * __int128_t(cx - ax); // tc <=> 0  ==  tcl <=> tcr
    __int128_t tdl = __int128_t(ax - bx) * __int128_t(dy - ay); // td = tdl - tdr
    __int128_t tdr = __int128_t(ay - by) * __int128_t(dx - ax); // td <=> 0  ==  tdl <=> tdr
    // ta * tb <= 0 && tc * td <= 0  ->  true
    // ta > 0 && tb > 0 -> false
    if ((tal > tar && tbl > tbr) || (tal < tar && tbl < tbr)){
        return false;
    }
    // tc > 0 && td > 0 -> false
    if ((tcl > tcr && tdl > tdr) || (tcl < tcr && tdl < tdr)){
        return false;
    }
    return true;
}

} // namespace noya2
#line 66 "f.cpp"

using vec = Vec<rat>;

const vector<vector<int>> order = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};

bool mat2(vec a0, vec a1, vec b, vec &res){
    res = vec(b.x * a1.y - b.y * a1.x, b.y * a0.x - b.x * a0.y);
    rat d = cross(a0,a1);
    if (d == 0) return false;
    res /= d;
    return true;
}

void solve(){
    while (true){
        vector<vec> ia(3), b(3);
        rep(i,6){
            ll x, y; cin >> x >> y;
            if (!cin) return ;
            (i < 3 ? ia[i] : b[i-3]) = vec(x,y);
        }
        
        int ans = 5;
        for (auto fid : order) for (auto tid : order) rep(j,2){
            auto a = ia;
            int cur = 3;
            rep(i,3){
                int f = fid[i], t = tid[i];
                int p = (f+1)%3, q = (f+2)%3;
                if (cross(a[p]-a[q],b[t]-a[f]) == 0){
                    a[f] = b[t];
                    continue;
                }
                cur++;
                if (cur == 5) break;
                if (j == 1) swap(p,q);
                vec ab;
                if (mat2(a[f]-b[t],a[p]-a[f],a[q]-a[p],ab)){
                    a[q] += ab.y * (a[f]-a[p]);
                    a[f] = b[t];
                }
                else {
                    cur = 5;
                    break;
                }
            }
            chmin(ans,cur);
        }
        if (ans == 5) cout << "Many" << endl;
        else cout << ans << endl;
        if (cin.eof()) break;
    }
}

int main(){
    fast_io();
    int t = 1; //cin >> t;
    while(t--) solve();
}
accuracy: 1
time_ms: 260
memory_kb: 3416
final_rank: 5

code_snippet: #line 1 "f.cpp"
#include<bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < int(n); ++i)
#define repp(i,n,m) for (int i = m; i < int(n); ++i)
#define reb(i,n) for (int i = int(n)-1; i >= 0; --i)
#define all(v) v.begin(),v.end()

using namespace std;
using ll = long long;
using ld = long double;
using P = pair<int,int>;
using PL = pair<ll,ll>;

template<class T>istream &operator>>(istream &is,vector<T> &v){for(auto &e:v)is>>e;return is;}
template<typename T1, typename T2>void print(pair<T1,T2> a);
template<typename T>void print(vector<T> v);
template<typename T>void print(vector<vector<T>> v);
void print(){ putchar(' '); }
void print(bool a){ printf("%d", a); }
void print(int a){ printf("%d", a); }
void print(long a){ printf("%ld", a); }
void print(long long a){ printf("%lld", a); }
void print(char a){ printf("%c", a); }
void print(char a[]){ printf("%s", a); }
void print(const char a[]){ printf("%s", a); }
void print(long double a){ printf("%.15Lf", a); }
void print(const string& a){ for(auto&& i : a) print(i); }
void print(unsigned int a){ printf("%u", a); }
void print(__int128_t a){print((long long)(a));}
template<class T> void print(const T& a){ cout << a;}
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
template<typename T1,typename T2>void print(pair<T1,T2> a){print(a.first);print(),print(a.second);}
template<typename T>void print(vector<T> v){for(auto ite=v.begin();ite!=v.end();){print(*ite);if(++ite!=v.end())print();}}
template<typename T>void print(vector<vector<T>> v){for(auto ite=v.begin();ite!=v.end();){print(*ite);if(++ite!=v.end())out();}}

template<typename T>bool chmin(T &a,const T &b){if(a>b){a=b;return true;}return false;}
template<typename T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}

void fast_io(){cin.tie(0); ios::sync_with_stdio(0); cout<<fixed<<setprecision(20);}

namespace noya2{

const int INF = 1001001007;
const long long mod1 = 998244353;
const long long mod2 = 1000000007;
const long long inf = 2e18;
const long double pi = 3.14159265358979323;
const long double eps = 1e-7;
vector<int> dx = {0,1,0,-1,1,1,-1,-1};
vector<int> dy = {1,0,-1,0,1,-1,-1,1};
const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string alp = "abcdefghijklmnopqrstuvwxyz";
const string NUM = "0123456789";
void o(){out("!?");}
void yn(bool f){out(f ? "Yes" : "No");}
void YN(bool F){out(F ? "YES" : "NO");}
template<typename T>bool range(T a,T b,T x){return (a<=x&&x<b);}
template<typename T>bool rrange(T a,T b,T c,T d,T x,T y){return (range(a,c,x)&&range(b,d,y));}

} // namespace noya2
using namespace noya2;

#line 2 "rational.hpp"

namespace noya2{

template<typename T>
struct rational{
    rational() : p(T(0)), q(T(1)) {}
    rational(T n) : p(n), q(T(1)) {}
    rational(T n, T m){
        assert(m != T(0));
        if (m < T(0)) n = -n, m = -m;
        T g = gcd(n,m);
        p = n / g; q = m / g;
    }
    T num(){return p;}
    T den(){return q;}
    void set_num(T n){
        p = n;
        T g = gcd(p,q);
        p /= g, q /= g;
    }
    void set_den(T n){
        assert(n != T(0));
        q = n;
        T g = gcd(p,q);
        p /= g, q /= g;
    }
    long double val(){
        return (long double)(p) / (long double)(q);
    }
    rational& operator+=(const rational& rhs){
        T g = gcd(q,rhs.q);
        T np = rhs.q / g * p + q / g * rhs.p;
        T nq = q / g * rhs.q;
        T ng = gcd(np,nq);
        p = np/ng, q = nq/ng;
        return *this; 
    }
    rational& operator-=(const rational& rhs){
        T g = gcd(q,rhs.q);
        T np = rhs.q / g * p - q / g * rhs.p;
        T nq = q / g * rhs.q;
        T ng = gcd(np,nq);
        p = np/ng, q = nq/ng;
        return *this;
    }
    rational& operator*=(const rational& rhs){
        T g1 = gcd(q,rhs.p), g2 = gcd(p,rhs.q);
        T np = p / g2 * rhs.p / g1;
        T nq = q / g1 * rhs.q / g2;
        p = np, q = nq;
        return *this;
    }
    rational& operator/=(const rational& rhs){
        assert(rhs.p != T(0));
        T g1 = gcd(q,rhs.q), g2 = gcd(p,rhs.p);
        T np = p / g2 * rhs.q / g1;
        T nq = q / g1 * rhs.p / g2;
        p = np, q = nq;
        return *this;
    }
    rational operator+() const {return *this;}
    rational operator-() const {return rational() - *this;}
    friend rational operator+(const rational& lhs, const rational& rhs) {
        return rational(lhs) += rhs;
    }
    friend rational operator-(const rational& lhs, const rational& rhs) {
        return rational(lhs) -= rhs;
    }
    friend rational operator*(const rational& lhs, const rational& rhs) {
        return rational(lhs) *= rhs;
    }
    friend rational operator/(const rational& lhs, const rational& rhs) {
        return rational(lhs) /= rhs;
    }
    friend bool operator==(const rational& lhs, const rational& rhs) {
        return lhs.p == rhs.p && lhs.q == rhs.q;
    }
    friend bool operator!=(const rational& lhs, const rational& rhs) {
        return lhs.p != rhs.p || lhs.q != rhs.q;
    }
    friend bool operator< (const rational lhs, const rational rhs) {
        return less_than(lhs,rhs);
    }
    friend bool operator> (const rational lhs, const rational rhs) {
        return less_than(rhs,lhs);
    }
    friend bool operator<= (const rational lhs, const rational rhs) {
        return lhs == rhs || lhs < rhs;
    }
    friend bool operator>= (const rational lhs, const rational rhs) {
        return lhs == rhs || lhs > rhs;
    }
    friend std::ostream &operator<<(std::ostream &os,const rational&r) {
        return os << r.p << " / " << r.q;
    }
  private:
    T p, q;
    T gcd(T a,T b){if(a<T(0))return gcd(-a,b);if(b<T(0))return gcd(a,-b);return _gcd(a,b);}
    T _gcd(T a,T b){return b?_gcd(b,a%b):a;}
    static bool less_than(rational lhs, rational rhs){
        __int128_t lv = __int128_t(lhs.p) * __int128_t(rhs.q);
        __int128_t rv = __int128_t(lhs.q) * __int128_t(rhs.p);
        return lv < rv;
    }
};

using rat = rational<long long>;

} // namespace noya2
#line 2 "geometry2D.hpp"

#line 6 "geometry2D.hpp"

#line 2 "math.hpp"

#line 6 "math.hpp"

namespace noya2{

using namespace std;
using ll = long long;

template<typename T> T sqrt_safe(T x){ // floor(sqrt(x))
    assert(x >= T(0));
    if (x <= T(1)) return x;
    T tmp = (T)(sqrtl((long double)(x))) + T(2);
    while (tmp--){
        if (tmp * tmp <= x) break;
    }
    return tmp;
}

ll mod_safe(ll a, ll m){ // m >= 1, 0 <= mod_safe(a,m) < m, mod_safe(a,m) = a (mod m)
    ll res = a % m;
    if (res < 0) res += m;
    return res;
}
ll modpow(ll x, ll n, ll mod){
    x = mod_safe(x,mod);
    if (n == 0) return 1;
    ll res = modpow(x,n/2,mod);
    res = (res * res) % mod;
    if (n % 2 == 1) res = (res * x) % mod;
    return res;
}

ll naive_gcd(ll a, ll b){ return b ? naive_gcd(b, a % b) : a; }

// gcd(N >= 0, 0) = N, especialy gcd(0, 0) = 0
ll gcd_safe(ll a, ll b){ return naive_gcd(abs(a),abs(b)); }
ll lcm_safe(ll a, ll b){ return a / gcd_safe(a,b) * b; }

void ext_gcd1_plus(ll a, ll b, ll &x, ll &y){ // gcd(a,b) = 1, a >= 0, b >= 0, ax + by = 1
    if (b == 0){ // a = 1
        x = 1, y = 0;
        return ;
    }
    ext_gcd1_plus(b, a%b, y, x);
    x = mod_safe(x,b);
    y = (1 - a * x) / b;
}
void ext_gcd1_minus(ll a, ll b, ll &x, ll &y){ // gcd(a,b) = 1, a >= 0, b >= 0, ax - by = 1
    if (b == 0){ // a = 1
        x = 1, y = 0;
        return ;
    }
    ext_gcd1_plus(b, a%b, y, x);
    x = mod_safe(x,b);
    y = (a * x - 1) / b;
}

pair<ll,ll> ext_gcd(ll a, ll b, ll c){ // ax + by = c, |a|,|b|,|c| < 1e9, x <= max(|B|,|C|), y <= max(|A|,|C|)
    if (a < 0) return ext_gcd(-a,-b,-c);
    if (c < 0){
        pair<ll,ll> res = ext_gcd(a,b,-c);
        res.first = -res.first, res.second = -res.second;
        return res;
    }
    if (c == 0) return pair<ll,ll>(0,0);
    if (a == 0 && b == 0) return pair<ll,ll>(0,0); // answer not exist
    ll g = gcd_safe(a,b);
    if (c % g != 0) return pair<ll,ll>(0,0); // answer not exist
    a /= g, b /= g, c /= g;
    ll x, y;
    if (b == 0) return pair<ll,ll>(c,0);
    if (b > 0) ext_gcd1_plus(a,b,x,y);
    else ext_gcd1_minus(a,-b,x,y);
    x = mod_safe(x*c,abs(b));
    y = (c - a * x) / b;
    return pair<ll,ll>(x,y);
}

template<typename T>
T ceil_safe(T p, T q);

template<typename T>
T floor_safe(T p, T q){
    if (q < T(0)) return floor_safe(-p,-q);
    if (p >= T(0)) return p / q;
    return -ceil_safe(-p,q);
}

template<typename T>
T ceil_safe(T p, T q){
    if (q < T(0)) return ceil_safe(-p,-q);
    if (p >= T(0)) return (p + q - 1) / q;
    return -floor_safe(-p,q);
}

struct Eratosthenes{
    static vector<int> table;
    Eratosthenes (int Nmax = -1) {init(Nmax);}
    static void init(int Nmax){
        if (!table.empty()) return ;
        table.resize(Nmax+1,0);
        table[0] = 1, table[1] = 1;
        for (int p = 2; p <= Nmax; p++){
            if (table[p] != 0) continue;
            for (int j = p; j <= Nmax; j += p){
                table[j] = p;
            }
        }
    }
};
vector<int>Eratosthenes::table = vector<int>(0);

void build_eratosthenes(const int Nmax){Eratosthenes::init(Nmax);}

vector<pair<int,int>> fast_prime_factorization(int N){
    int pre = -1, cnt = 0;
    vector<pair<int,int>> res;
    while(true) {
        if (N == 1){
            if (cnt > 0) res.emplace_back(pre,cnt);
            break;
        }
        int div = Eratosthenes::table[N];
        if (pre != div){
            if (cnt > 0) res.emplace_back(pre,cnt);
            pre = div, cnt = 1;
        }
        else cnt++;
        N /= div;
    }
    return res;
}

vector<int> fast_divisor_enumeration(int N){
    auto pes = fast_prime_factorization(N);
    vector<int> res = {1};
    for (auto pe : pes){
        vector<int> nres;
        for (auto x : res){
            for (int _t = 0; _t <= pe.second; _t++){
                nres.emplace_back(x);
                x *= pe.first;
            }
        }
        swap(res,nres);
    }
    return res;
}

bool fast_is_prime(int N){
    if (N <= 1) return false;
    return Eratosthenes::table[N] == N;
}

vector<int> mobius(int N){
    vector<int> res(N+1,0);
    res[1] = 1;
    for (int p = 2; p <= N; p++){
        if (fast_is_prime(p)){
            for (int i = N/p; i > 0; i--){
                res[i*p] = -res[i];
            }
        }
    }
    return res;
};

vector<pair<ll,int>> prime_factorization(ll N){
    vector<pair<ll,int>> res;
    ll iN = N;
    for (ll d = 2; d * d <= N; d++){
        if (iN % d != 0) continue;
        if (iN == 1) break;
        int ie = 0;
        while (iN % d == 0) iN /= d, ie++;
        res.emplace_back(d,ie);
    }
    if (iN != 1) res.emplace_back(iN,1);
    return res;
}

vector<ll> divisor_enumeration(ll N){
    vector<ll> res;
    for (ll d = 1; d * d <= N; d++){
        if (N % d != 0) continue;
        res.emplace_back(d);
        if (d * d != N) res.emplace_back(N/d);
    }
    return res;
}

bool is_prime(ll N){
    if (N <= 1) return false;
    if (N <= 3) return true;
    if (N % 2 == 0) return false;
    for (ll d = 3; d * d <= N; d += 2){
        if (N % d == 0) return false;
    }
    return true;
}

}// namespace noya2
#line 8 "geometry2D.hpp"

namespace noya2{

using namespace std;
using ld = long double;

template<typename T>
struct Vec {
    T x, y;
    Vec (T _x = T(0), T _y = T(0)) : x(_x), y(_y) {}
    Vec& operator*=(const T& a){
        x *= a;
        y *= a;
        return *this;
    }
    Vec& operator/=(const T& a){
        x /= a;
        y /= a;
        return *this;
    }
    Vec& operator+=(const Vec& rhs) {
        x += rhs.x;
        y += rhs.y;
        return *this;
    }
    Vec& operator-=(const Vec& rhs) {
        x -= rhs.x;
        y -= rhs.y;
        return *this;
    }
    friend bool operator==(const Vec& lhs, const Vec& rhs) {
        return lhs.x == rhs.x && lhs.y == rhs.y;
    }
    friend bool operator!=(const Vec& lhs, const Vec& rhs) {
        return lhs.x != rhs.x || lhs.y != rhs.y;
    }
    friend Vec operator+(const Vec& lhs, const Vec& rhs) {
        return Vec(lhs) += rhs;
    }
    friend Vec operator-(const Vec& lhs, const Vec& rhs) {
        return Vec(lhs) -= rhs;
    }
    friend Vec operator*(const Vec& lhs, const T& rhs) {
        return Vec(lhs) *= rhs;
    }
    friend Vec operator*(const T& rhs, const Vec& lhs) {
        return Vec(lhs) *= rhs;
    }
    friend Vec operator/(const Vec& lhs, const T& rhs) {
        return Vec(lhs) /= rhs;
    }
    friend Vec operator/(const T& rhs, const Vec& lhs) {
        return Vec(lhs) /= rhs;
    }
    ld norm(){
        return sqrtl(ld(x*x+y*y));
    }
    T norm2(){
        return x*x+y*y;
    }
};

template<typename T>
T dot(const Vec<T> &a, const Vec<T> &b){
    return a.x * b.x + a.y * b.y;
}

// cross > 0 : counter clockwise a -> b
template<typename T>
T cross(const Vec<T> &a, const Vec<T> &b){
    return a.x * b.y - a.y * b.x;
}

// T = int, ll
// number of lattice points ( point(x,y) s.t. x in Z and y in Z ) on Vec a
template<typename T>
T lattice_points(const Vec<T> &a){
    return gcd_safe(a.x,a.y) + 1;
}

// e : vec(OX)
// orthant k : [ pi/2 * k, pi/2 * (k+1) ) rad
// orthant 4 is NOT expected
template<typename T>
int orthant(const Vec<T> &e, const Vec<T> &p){
    T _dot = dot(e,p), _cross = cross(e,p);
    if (_dot >  0 && _cross >= 0) return 0;
    if (_dot <= 0 && _cross >  0) return 1;
    if (_dot <  0 && _cross <= 0) return 2;
    if (_dot >= 0 && _cross <  0) return 3;
    return 4;
}

// usage : 
//   vector<Vec<ll>> vec;
//   sort(vec.begin(),vec.end(),comp_for_argument_sort<ll>);
template<typename T>
bool comp_for_argument_sort(const Vec<T> &lhs, const Vec<T> &rhs){
    int pl = orthant(Vec<T>(1,0),lhs), pr = orthant(Vec<T>(1,0),rhs);
    if (pl == pr){
        return cross(lhs,rhs) > 0;
    }
    return pl < pr;
}

// DISTINCT points are given
// ans[0] --- ans[1] --- ... --- ans[k-1] --- ans[k] --- ans[0]
// upper_hull --- lower_hull
// upper_hull : x is from small to large
// lower hull : x is from large to small
// points rearranged counter clockwise
template<typename T>
vector<Vec<T>> convex_hull(vector<Vec<T>> a){
    int n = a.size();
    if (n <= 2) return a;
    using vec = Vec<T>;
    auto comp = [&](vec lhs, vec rhs){
        if (lhs.x == rhs.x) return lhs.y < rhs.y;
        return lhs.x < rhs.x;
    };
    sort(a.begin(),a.end(),comp);
    stack<int> uid, did;
    uid.push(0);
    vec ri = a[n-1];
    for (int i = 1; i < n-1; i++){
        vec le = a[uid.top()];
        if (cross(ri-le,a[i]-le) > 0){
            while (uid.size() >= 2){
                int test = uid.top(); uid.pop();
                vec from = a[uid.top()];
                if (cross(a[i]-from,a[test]-from) > 0){
                    uid.push(test);
                    break;
                }
            }
            uid.push(i);
        }
    }
    did.push(0);
    for (int i = 1; i < n-1; i++){
        vec le = a[did.top()];
        if (cross(ri-le,a[i]-le) < 0){
            while (did.size() >= 2){
                int test = did.top(); did.pop();
                vec from = a[did.top()];
                if (cross(a[i]-from,a[test]-from) < 0){
                    did.push(test);
                    break;
                }
            }
            did.push(i);
        }
    }
    vector<int> ids(1,n-1);
    while (!did.empty()) ids.emplace_back(did.top()), did.pop();
    reverse(ids.begin(),ids.end());
    while (!uid.empty()) ids.emplace_back(uid.top()), uid.pop();
    ids.pop_back();
    vector<vec> ans(ids.size());
    for (int i = 0; i < (int)(ids.size()); i++){
        ans[i] = a[ids[i]];
    }
    return ans;
}

using ll = long long;
struct Line{
    ll a, b, c; // ax + by = c
    void norm(){ // a >= 0, if (a == 0) -> b >= 0, gcd(a,b,c) = 1
        if (a < 0) a = -a, b = -b, c = -c;
        if (a == 0) if (b < 0) b = -b, c = -c;
        ll g = gcd_safe(gcd_safe(a,b),c);
        a /= g, b /= g, c /= g;
    }
    Line (ll _a = 1, ll _b = 0, ll _c = 0) : a(_a), b(_b), c(_c) {
        assert(_a != 0 || _b != 0);
        norm();
    }
    Line (ll x1, ll y1, ll x2, ll y2){ // --- (x1,y1) --- (x2,y2) ---
        assert(x1 != x2 || y1 != y2);
        ll wx = x2 - x1, wy = y2 - y1;
        ll wg = gcd_safe(wx,wy);
        a = wy / wg, b = -wx / wg;
        c = a * x1 + b * y1;
        norm();
    }
    static Line get_Line(ll x1, ll y1, ll ex, ll ey){ // y = ey/ex (x - x1) + y1 
        return Line(ey,-ex,ey*x1-ex*y1);
    }
    static Line vertical_Line(ll x1, ll y1, ll x2, ll y2){ // perpendicular bisector
        ll ex = y2 - y1, ey = x1 - x2;
        return Line(ey*2,-ex*2,ey*(x1+x2)-ex*(y1+y2));
    }
    void slide(const Vec<ll> &v){ // ax + by = c -> a(x - vx) + b(y - vy) = c
        c += a * v.x + b * v.y;
    }
    //Vec<ll> normal_Vec(const Vec<ll> &from){}
    ld dist_from_point(const Vec<ll> &from){
        return abs(ld(a) * ld(from.x) + ld(b) * ld(from.y) - ld(c)) / sqrtl(ld(a*a+b*b));
    }
    bool operator<(const Line &rhs) const { // to use set or map for Line
        if (a == rhs.a){
            if (b == rhs.b) return c < rhs.c;
            return b < rhs.b;
        }
        return a < rhs.a;
    }
};

struct Directed_Line{
    Vec<ll> from, direct; // Line : from + k * direct
    void normalize(){
        ll g = gcd_safe(direct.x,direct.y);
        direct /= g;
    }
    Directed_Line (ll x_from = 0, ll y_from = 0, ll x_to = 1, ll y_to = 0){
        from.x = x_from, from.y = y_from;
        direct.x = x_to - x_from;
        direct.y = y_to - y_from;
        normalize();
    }
    Directed_Line (Vec<ll> _from, Vec<ll> _to){
        from = _from;
        direct = _to - _from;
        normalize();
    }
    bool in(const Vec<ll> &r, bool on){
        ll z = cross(direct,r-from);
        if (z == 0) return on;
        return z > 0;
    }
    bool slide_if_smaller(const Vec<ll> &v){
        if (in(from+v,false)){
            from += v;
            return true;
        }
        return false;
    }
    Directed_Line slide(const Vec<ll> &v){
        auto res = *this;
        res.from += v;
        return res;
    }
};


// two line segments AB and CD shared at least one point
bool check_intersection(ll ax, ll ay, ll bx, ll by, ll cx, ll cy, ll dx, ll dy){
    // both AB and CD are parallel to y-axis 
    if (ax == bx && cx == dx){
        if (ax != cx) return false;
        return (min(ay,by) <= max(cy,dy)) && (min(cy,dy) <= max(ay,by));
    }
    // change to cx != dx 
    if (cx == dx){
        swap(ax,cx), swap(ay,cy);
        swap(bx,dx), swap(by,dy);
    }
    // change to ax >= bx
    if (ax < bx){
        swap(ax,bx), swap(ay,by);
    }
    // change to cx >= dx
    if (cx < dx){
        swap(cx,dx), swap(cy,dy);
    }
    // AB is parallel to y-axis
    if (ax == bx){
        __int128_t lv = __int128_t(cx - dx) * __int128_t(min(ay,by) - dy);
        __int128_t mv = __int128_t(cy - dy) * __int128_t(ax - dx);
        __int128_t rv = __int128_t(cx - dx) * __int128_t(max(ay,by) - dy);
        return lv <= mv && mv <= rv;
    }
    // both AB and CD are NOT parallel to y-axis
    ll gAB = gcd_safe(ay-by,ax-bx);
    ll pAB = (ax-bx) / gAB, qAB = (ay-by) / gAB;
    ll gCD = gcd_safe(cy-dy,cx-dx);
    ll pCD = (cx-dx) / gCD, qCD = (cy-dy) / gCD;
    //   AB and CD are parallel
    if (pAB == pCD && qAB == qCD){
        if (bx == dx){
            return by == dy;
        }
        ll gDB = gcd_safe(dy-by,dx-bx);
        ll pDB = (dx-bx) / gDB, qDB = (dy-by) / gDB;
        if (bx > dx){
            pDB = -pDB;
            qDB = -qDB;
        }
        // Line AB = Line CD
        if (pDB == pAB && qDB == qAB){
            return bx <= cx && dx <= ax;
        }
        return false;
    }
    //   AB and CD are NOT parallel
    __int128_t tal = __int128_t(cx - dx) * __int128_t(ay - cy); // ta = tal - tar
    __int128_t tar = __int128_t(cy - dy) * __int128_t(ax - cx); // ta <=> 0  ==  tal <=> tar
    __int128_t tbl = __int128_t(cx - dx) * __int128_t(by - cy); // tb = tbl - tbr
    __int128_t tbr = __int128_t(cy - dy) * __int128_t(bx - cx); // tb <=> 0  ==  tbl <=> tbr
    __int128_t tcl = __int128_t(ax - bx) * __int128_t(cy - ay); // tc = tcl - tcr
    __int128_t tcr = __int128_t(ay - by) * __int128_t(cx - ax); // tc <=> 0  ==  tcl <=> tcr
    __int128_t tdl = __int128_t(ax - bx) * __int128_t(dy - ay); // td = tdl - tdr
    __int128_t tdr = __int128_t(ay - by) * __int128_t(dx - ax); // td <=> 0  ==  tdl <=> tdr
    // ta * tb <= 0 && tc * td <= 0  ->  true
    // ta > 0 && tb > 0 -> false
    if ((tal > tar && tbl > tbr) || (tal < tar && tbl < tbr)){
        return false;
    }
    // tc > 0 && td > 0 -> false
    if ((tcl > tcr && tdl > tdr) || (tcl < tcr && tdl < tdr)){
        return false;
    }
    return true;
}

} // namespace noya2
#line 66 "f.cpp"

using vec = Vec<rat>;

const vector<vector<int>> order = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};

bool mat2(vec a0, vec a1, vec b, vec &res){
    res = vec(b.x * a1.y - b.y * a1.x, b.y * a0.x - b.x * a0.y);
    rat d = cross(a0,a1);
    if (d == 0) return false;
    res /= d;
    return true;
}

void solve(){
    ll xx;
    while (std::cin >> xx){
        vector<vec> ia(3), b(3);
        {
            ll y;
            std::cin >> y;
            ia[0] = {xx, y};
        }
        rep(i,6){
            if(i == 0) continue;
            ll x, y; cin >> x >> y;
            (i < 3 ? ia[i] : b[i-3]) = vec(x,y);
        }
        int ans = 5;
        for (auto fid : order) for (auto tid : order) rep(j,2){
            auto a = ia;
            int cur = 0;
            rep(i,3){
                int f = fid[i], t = tid[i];
                if (a[f] == b[t]) continue;
                cur++;
                int p = (f+1)%3, q = (f+2)%3;
                if (cross(a[p]-a[q],b[t]-a[f]) == 0){
                    a[f] = b[t];
                    continue;
                }
                cur++;
                if (j == 1) swap(p,q);
                vec ab;
                if (mat2(a[f]-b[t],a[p]-a[f],a[q]-a[p],ab)){
                    a[q] += ab.y * (a[f]-a[p]);
                    a[f] = b[t];
                }
                else {
                    cur = 1000;
                    break;
                }
            }
            chmin(ans,cur);
        }
        if (ans == 5) out("Many");
        else out(ans);
    }
}

int main(){
    fast_io();
    int t = 1; //cin >> t;
    while(t--) solve();
}
accuracy: 1
time_ms: 850
memory_kb: 3520
final_rank: 19

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi

namespace ebi {

constexpr long double EPS = 1e-7;

const long double PI = std::acos(-1);

namespace internal {

int sgn(long double a) {
    return (a<-EPS) ? -1 : (a>EPS) ? 1 : 0;
}

long double add(long double a, long double b) {
    if(std::abs(a+b) < EPS*(std::abs(a) + std::abs(b))) return 0;
    return a+b;
}

} // namespace internal


long double arg_to_radian(long double arg) {
    return PI * arg / (long double)(180);
}

struct point {
    long double x,y;

    point() = default;

    point(long double x, long double y) : x(x), y(y) { }

    point &operator+=(const point rhs) noexcept {
        x = internal::add(x, rhs.x);
        y = internal::add(y, rhs.y);
        return *this;
    }

    point &operator-=(const point rhs) noexcept {
        x = internal::add(x, -rhs.x);
        y = internal::add(y, -rhs.y);
        return *this;
    }

    point &operator*=(const point rhs) noexcept {
        long double _x = internal::add(x*rhs.x, -y*rhs.y);
        long double _y = internal::add(x*rhs.y, y*rhs.x);
        x = _x;
        y = _y;
        return *this;
    }

    point &operator*=(const long double k) noexcept {
        x *= k;
        y *= k;
        return *this;
    }

    point &operator/=(const long double k) {
        assert(internal::sgn(k)!=0);
        x /= k;
        y /= k;
        return *this;
    }

    point operator+(const point &rhs) const noexcept {
        return point(*this) += rhs;
    }

    point operator-(const point &rhs) const noexcept {
        return point(*this) -= rhs;
    }

    point operator*(const point &rhs) const noexcept {
        return point(*this) *= rhs;
    }

    point operator*(const long double rhs) const noexcept {
        return point(*this) *= rhs;
    }

    point operator/(const long double rhs) const {
        return point(*this) /= rhs;
    }

    point operator-() const noexcept {
        return point(0, 0) - *this;
    }

    long double abs() const noexcept {
        return std::sqrt(internal::add(x*x, y*y));
    }

    long double dot(const point rhs) const noexcept {
        return internal::add(x*rhs.x, y*rhs.y);
    }

    long double det(const point rhs) const noexcept {
        return internal::add(x*rhs.y, -y*rhs.x);
    }

    // arctan(y/x) (単位はラジアン)

    long double arg() const {
        return std::atan2(y, x);
    }

    // x昇順, その後y昇順

    bool operator<(const point &rhs) const noexcept {
        if(internal::sgn(x-rhs.x)) return internal::sgn(x-rhs.x)<0;
        return internal::sgn(y-rhs.y)<0;
    }

    bool operator==(const point &rhs) const noexcept {
        if(internal::sgn(x - rhs.x) == 0 && internal::sgn(y - rhs.y) == 0) return true;
        else return false;
    }

    bool operator!=(const point &rhs) const noexcept {
        return !(*this == rhs);
    }
};

std::ostream& operator<<(std::ostream& os, const point &a) {
    return os << a.x << " " << a.y;
}

std::istream& operator>>(std::istream& os, point &a) {
    return os >> a.x >> a.y;
}

point conj(const point &a) {
    return point(a.x, -a.y);
}

// 点a をang(ラジアン)回転する

point rot(const point &a, long double ang) {
    return point(std::cos(ang) * a.x - std::sin(ang) * a.y, std::sin(ang) * a.x + std::cos(ang) * a.y);
} 

point rot90(const point &a) {
    return point(-a.y, a.x);
}

long double dot(const point &a, const point &b) {
    return a.dot(b);
}

long double det(const point &a, const point &b) {
    return a.det(b);
}

long double abs(const point &a) {
    return a.abs();
}

long double norm(const point &a) {
    return internal::add(a.x*a.x, a.y*a.y);
}

int isp(const point &a, const point &b, const point &c) {
    int flag = internal::sgn(det(b-a,c-a));
    if(flag == 0) {
        if(internal::sgn(dot(b-a, c-a))<0) return -2;
        if(internal::sgn(dot(a-b, c-b))<0) return +2;
    }
    return flag;
}

// 分割統治で最近点対を求める O(N log N)

long double closest_pair(std::vector<point> p) {
    std::sort(p.begin(), p.end());
    int n = p.size();
    auto f = [&](auto &&self, int l, int r) -> long double {
        if(r-l == 1) {
            return 1e9;
        }
        int mid = (l+r)/2;
        long double x = p[mid].x;
        long double d = std::min(self(self, l, mid), self(self, mid, r));
        std::vector<point> b;
        b.reserve(r-l);
        int j = mid;
        for(int i = l; i < mid; i++) {
            while(j < r && p[j].y <= p[i].y) {
                b.emplace_back(p[j++]);
            }
            b.emplace_back(p[i]);
        }
        while(j < r) {
            b.emplace_back(p[j++]);
        }
        for(int i = 0; i < r-l; i++) {
            p[l+i] = b[i];
        }
        b.clear();
        for(int i = l; i < r; i++) {
            if(std::abs(p[i].x - x) >= d) continue;
            for(int j = int(b.size())-1; j >= 0; j--) {
                if(p[i].y - b[j].y >= d) break;
                d = std::min(d, abs(p[i]-b[j]));
            }
            b.emplace_back(p[i]);
        }
        return d;
    };
    return f(f, 0, n);
}

// ∠ABCを求める(ラジアン)

long double angle(const point &A, const point &B, const point &C) {
    long double a = (B - C).abs(), b = (C - A).abs(), c = (A - B).abs();
    long double cos = internal::add(internal::add(a*a, c*c), -b*b)/(2.0*c*a);
    return std::acos(cos);
}

void arg_sort(std::vector<point> &a) {
    int n = a.size();
    std::vector ps(4, std::vector<point>());
    auto idx = [](point v) -> int {
        if(v.y >= 0) return (v.x >= 0) ? 0 : 1;
        else return (v.x >= 0) ? 3 : 2;
    };
    for(auto p: a) {
        assert(!(p.x == 0 && p.y == 0));
        ps[idx(p)].emplace_back(p);
    }
    a.clear();
    a.reserve(n);
    for(int i = 0; i < 4; i++) {
        std::sort(ps[i].begin(), ps[i].end(), 
            [](point &p1, point &p2) -> bool {
                int flag = internal::sgn(internal::add(p1.x * p2.y, - p2.x * p1.y));
                return flag == 0 ? (norm(p1) < norm(p2)) : flag > 0;
            });
        for(auto &p: ps[i]) a.emplace_back(p);
    }
    return;
}

template<class T>
void arg_sort_ll(std::vector<std::pair<T , T>> &a) {
    using Point = std::pair<T, T>;
    int n = a.size();
    std::vector ps(4, std::vector<Point>());
    auto idx = [](Point v) -> int {
        if(v.second >= 0) return (v.first >= 0) ? 0 : 1;
        else return (v.first >= 0) ? 3 : 2;
    };
    for(auto p: a) {
        assert(!(p.first == 0 && p.second == 0));
        ps[idx(p)].emplace_back(p);
    }
    a.clear();
    a.reserve(n);
    for(int i = 0; i < 4; i++) {
        std::sort(ps[i].begin(), ps[i].end(), 
            [](Point &p1, Point &p2) -> bool { 
                T flag = p1.first * p2.second - p2.first * p1.second;
                return flag == 0 ? (p1.first * p1.first + p1.second * p1.second < p2.first * p2.first + p2.second * p2.second) : flag > 0;
            });
        for(auto &p: ps[i]) a.emplace_back(p);
    }
    return;
}

}

namespace ebi {

struct line {
    point a,b;

    line(long double x1, long double y1, long double x2, long double y2) : a(x1, y1), b(x2, y2) { }

    line(const point &a, const point &b) : a(a), b(b) { }

    point proj(const point &p) const {
        return a + (b-a)*(dot(b-a,p-a)/norm(b-a));
    }

    point relf(const point &p) const {
        return proj(p)*double(2) - p;
    }

    long double distance(const point &c) const {
    return std::abs(det(c - a, b - a)/abs(b-a));
    }
};

int intersection(const line &a, const line &b) {
    if(internal::sgn(det(a.b-a.a, b.a-b.b)) != 0) {
        if(internal::sgn(dot(a.b-a.a, b.b-b.a)) == 0) { // 垂直
            return 1;
        }
        return 0; // 交差
    }
    else if(internal::sgn(det(a.b-a.a, b.a-a.a)) != 0) { // 平行
        return 2;
    }
    else { // 同一直線
        return 3;
    }
}

point cross_point(const point &a, const point &b, const point &c, const point &d) {
    return a + (b-a) * det(c - a, d - c) / det(b - a, d - c);
}

// 交点があるか確認する！
point cross_point(const line &s, const line &t) {
    assert(intersection(s, t) < 2);
    return s.a + (s.b - s.a) * det(t.a - s.a, t.b - t.a) / det(s.b - s.a, t.b - t.a);
}

// 直線aと点cの距離
long double distance(const line &a, const point &c) {
    return std::abs(det(c-a.a, a.b - a.a)/abs(a.b-a.a));
}

long double distance(const line &a, const line &b) {
    if(intersection(a, b) < 2) {
        return 0;
    }
    else {
        return distance(a, b.a);
    }
}

}

namespace ebi {

struct line_segment {
    point a, b;

    line_segment() = default;

    line_segment(long double x1, long double y1, long double x2, long double y2) : a(x1, y1), b(x2, y2) { }

    line_segment(const point &a, const point &b) : a(a), b(b) { }
};

// 線分ab, cd が交わるか判定
bool intersection_line_segment(const point &a, const point &b, const point &c, const point &d) {
    if(internal::sgn(isp(a,b,c)*isp(a,b,d)) <= 0 && internal::sgn(isp(c,d,a)*isp(c,d,b)) <= 0) {
        return true;
    }
    return false;
}

// 線分ab, cd が交わるか判定
bool intersection(const line_segment &a, const line_segment &b) {
    return intersection_line_segment(a.a, a.b, b.a, b.b);
}

bool intersection(const line &a, const line_segment &b) {
    if(internal::sgn(det(a.b - a.a, b.a - a.a)) * internal::sgn(det(a.b - a.a, b.b - a.a)) < 0) {
        return true;
    }
    else {
        return false;
    }
}

point cross_point(const line_segment &s, const line_segment &t) {
    assert(intersection(s, t));
    return s.a + (s.b - s.a) * det(t.a - s.a, t.b - t.a) / det(s.b - s.a, t.b - t.a);
}

long double distance(const line_segment &a, const point &c) {
    if(internal::sgn(dot(a.b - a.a, c - a.a)) < 0) {
        return abs(c-a.a);
    }
    else if(internal::sgn(dot(a.a - a.b, c - a.b)) < 0) {
        return abs(c-a.b);
    }
    else {
        return std::abs(det(c - a.a, a.b - a.a)/abs(a.b-a.a));
    }
}

long double distance(const line_segment &a, const line_segment &b) {
    if(intersection(a, b)) {
        return 0;
    }
    else {
        return std::min(std::min(distance(a, b.a), distance(a, b.b)), std::min(distance(b, a.a), distance(b, a.b)));
    }
}

long double distance(const line &a, const line_segment &b) {
    if(intersection(a, b)) {
        return 0;
    }
    else {
        return std::min(distance(a, b.a), distance(a, b.b));
    }
}

}

namespace ebi {

void main_() {
    long double x;
    while (std::cin >> x) {
        long double y;
        std::vector<point> t1(3), t2(3);
        std::cin >> y;
        t1[0] = {x, y};
        std::cin >> t1[1] >> t1[2] >> t2;
        std::vector<int> idx(3), jdx(3);
        std::iota(all(idx), 0);
        std::iota(all(jdx), 0);
        int ans = INF;

        auto move = [&](int i, int j, int k, std::vector<point> &t, point target) -> int {
            if(t[i] == target) return 0;
            int cnt = 0;
            line l1(t[j], t[j] + target - t[i]);
            line l2(t[k], t[k] + t[i] - t[j]);
            if(intersection(l1, l2) >= 2) return 1000;
            point p = cross_point(l1, l2);
            if(p != t[k]) cnt++;
            t[k] = p;
            t[i] = target;
            cnt++;
            return cnt;
        };
        do {
            do {
                {
                    int cnt = 0;
                    auto t = t1;
                    cnt += move(idx[0], idx[1], idx[2], t, t2[jdx[0]]);
                    cnt += move(idx[1], idx[0], idx[2], t, t2[jdx[1]]);
                    line_segment lseg(t[idx[2]], t2[jdx[2]]);
                    if(intersection(line(t[idx[0]], t[idx[1]]), lseg)) cnt = 1000;
                    if(t[idx[2]] != t2[jdx[2]]) cnt++;
                    chmin(ans, cnt);
                }
                {
                    int cnt = 0;
                    auto t = t1;
                    cnt += move(idx[0], idx[2], idx[1], t, t2[jdx[0]]);
                    cnt += move(idx[1], idx[0], idx[2], t, t2[jdx[1]]);
                    line_segment lseg(t[idx[2]], t2[jdx[2]]);
                    if(intersection(line(t[idx[0]], t[idx[1]]), lseg)) cnt = 1000;
                    if(t[idx[2]] != t2[jdx[2]]) cnt++;
                    chmin(ans, cnt);
                }
            } while(std::next_permutation(all(jdx)));
        } while(std::next_permutation(all(idx)));
        if(ans >= 5) {
            std::cout << "Many\n";
            continue;
        }
        std::cout << ans << '\n';
    }

}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3432
final_rank: 6

code_snippet: #include <cmath>
#include <string>
#include <vector>
#include <cassert>
#include <iostream>
#include <algorithm>
using namespace std;

int gcd(int x, int y) {
	if (y == 0) return x;
	return gcd(y, x % y);
}

class fraction {
public:
	int a, b;
	fraction() : a(0), b(1) {};
	fraction(int a_, int b_) {
		assert(b_ != 0);
		int g = gcd(abs(a_), abs(b_));
		a = a_ / g;
		b = b_ / g;
		if (b < 0) {
			a *= -1;
			b *= -1;
		}
	};
	bool operator==(const fraction& f) const {
		return a == f.a && b == f.b;
	}
	bool operator!=(const fraction& f) const {
		return a != f.a || b != f.b;
	}
	fraction operator+=(const fraction& f) {
		(*this) = fraction(a * f.b + f.a * b, b * f.b);
		return (*this);
	}
	fraction operator-=(const fraction& f) {
		(*this) = fraction(a * f.b - f.a * b, b * f.b);
		return (*this);
	}
	fraction operator*=(const fraction& f) {
		(*this) = fraction(a * f.a, b * f.b);
		return (*this);
	}
	fraction operator/=(const fraction& f) {
		assert(f.a != 0);
		(*this) = fraction(a * f.b, b * f.a);
		return (*this);
	}
	fraction operator+(const fraction& f) const {
		return fraction(*this) += f;
	}
	fraction operator-(const fraction& f) const {
		return fraction(*this) -= f;
	}
	fraction operator*(const fraction& f) const {
		return fraction(*this) *= f;
	}
	fraction operator/(const fraction& f) const {
		return fraction(*this) /= f;
	}
	string to_string() const {
		return std::to_string(a) + "/" + std::to_string(b);
	}
};

class point2d {
public:
	fraction x, y;
	point2d() : x(fraction()), y(fraction()) {};
	point2d(const fraction& x_, const fraction& y_) : x(x_), y(y_) {};
	bool operator==(const point2d& p) const {
		return x == p.x && y == p.y;
	}
	bool operator!=(const point2d& p) const {
		return x != p.x || y != p.y;
	}
	point2d& operator+=(const point2d& p) {
		x += p.x;
		y += p.y;
		return (*this);
	}
	point2d& operator-=(const point2d& p) {
		x -= p.x;
		y -= p.y;
		return (*this);
	}
	point2d& operator*=(const fraction& f) {
		x *= f;
		y *= f;
		return (*this);
	}
	point2d& operator/=(const fraction& f) {
		x /= f;
		y /= f;
		return (*this);
	}
	point2d operator+(const point2d& p) const {
		return point2d(*this) += p;
	}
	point2d operator-(const point2d& p) const {
		return point2d(*this) -= p;
	}
	point2d operator*(const fraction& f) const {
		return point2d(*this) *= f;
	}
	point2d operator/(const fraction& f) const {
		return point2d(*this) /= f;
	}
	fraction dot(const point2d& p) const {
		return x * p.x + y * p.y;
	}
	fraction cross(const point2d& p) const {
		return x * p.y - y * p.x;
	}
};

const int INF = 1012345678;

// find status of crossing of two lines [p1 + v1 * t and p2 + v2 * t]
int cross_status(const point2d& p1, const point2d& v1, const point2d& p2, const point2d& v2) {
	assert(!(v1.x == fraction(0, 1) && v1.y == fraction(0, 1)) && !(v2.x == fraction(0, 1) && v2.y == fraction(0, 1)));
	if (v1.cross(v2) != fraction(0, 1)) {
		return 100; // one cross point
	}
	if ((p2 - p1).cross(v1) != fraction(0, 1)) {
		return 101; // no cross point
	}
	return 102; // cross line
}

// find cross point of two lines [p1 + v1 * t and p2 + v2 * t]
point2d cross_point(const point2d& p1, const point2d& v1, const point2d& p2, const point2d& v2) {
	assert(cross_status(p1, v1, p2, v2) == 100);
	// p1 + v1 * t1 = p2 + v2 * t2
	// ==> (-v1) * t1 + v2 * t2 = p1 - p2
	// ==> [ -v1, v2 ] * [ [ t1 ], [ t2 ] ] = p1 - p2
	// ==> [ [ t1 ], [ t2 ] ] = [ -v1, v2 ]^-1 * (p1 - p2) = 1/(-v1.x*v2.y+v1.y*v2.x) * [ [ v2.y, -v2.x ], [ v1.y, -v1.x ] ] * (p1 - p2)
	fraction detinv = fraction(1, 1) / (v1.y * v2.x - v1.x * v2.y);
	fraction t1 = detinv * (v2.y * (p1 - p2).x - v2.x * (p1 - p2).y);
	return p1 + v1 * t1;
}

// solve for 0->1->0 case
bool solve_010(const vector<point2d>& TA, const vector<point2d>& TB) {
	assert(TA[2] == TB[2]);
	int status = cross_status(TA[0], TA[2] - TA[1], TB[0], TB[2] - TB[1]);
	if (status == 100) {
		point2d p = cross_point(TA[0], TA[2] - TA[1], TB[0], TB[2] - TB[1]);
		return ((TB[1] - TA[1]).cross(TA[2] - p) == fraction(0, 1));
	}
	if (status == 101) {
		return false;
	}
	if (status == 102) {
		return false;
	}
	return false;
}

// solve for specific case
int solve_target(const vector<point2d>& TA, const vector<point2d>& TB) {
	// step #1. check for 0->1->2
	bool flag1 = true;
	if ((TB[0] - TA[0]).cross(TA[2] - TA[1]) != fraction(0, 1)) flag1 = false;
	if ((TB[1] - TA[1]).cross(TA[2] - TB[0]) != fraction(0, 1)) flag1 = false;
	if ((TB[2] - TA[2]).cross(TB[1] - TB[0]) != fraction(0, 1)) flag1 = false;
	if (flag1 == true) {
		return 3;
	}

	// step #2. check for 0->1->0->2
	if ((TB[2] - TA[2]).cross(TB[1] - TB[0]) == fraction(0, 1)) {
		bool flag2 = solve_010(TA, vector<point2d>({ TB[0], TB[1], TA[2] }));
		if (flag2 == true) {
			return 4;
		}
	}

	// step #3. check for 2->0->1->0
	if ((TB[2] - TA[2]).cross(TA[1] - TA[0]) == fraction(0, 1)) {
		bool flag3 = solve_010(vector<point2d>({ TA[0], TA[1], TB[2] }), TB);
		if (flag3 == true) {
			return 4;
		}
	}

	// step #4. check for 0->1->2->0
	int status = cross_status(TA[0], TA[2] - TA[1], TB[0], TB[2] - TB[1]);
	if (status == 100) {
		point2d p = cross_point(TA[0], TA[2] - TA[1], TB[0], TB[2] - TB[1]);
		bool flag4 = true;
		if ((TB[1] - TA[1]).cross(TA[2] - p) != fraction(0, 1)) flag4 = false;
		if ((TB[2] - TA[2]).cross(TB[1] - p) != fraction(0, 1)) flag4 = false;
		if (flag4 == true) {
			return 4;
		}
	}
	if (status == 101) {
		// NO CHANCE!
	}
	if (status == 102) {
		fraction c1 = (TB[0] - TA[0]).cross(TA[1] - TA[0]);
		fraction c2 = (TB[0] - TA[0]).cross(TB[1] - TB[0]);
		fraction c3 = (TA[2] - TA[1]).cross(TB[1] - TA[1]);
		if ((c1.a > 0) == (c2.a > 0) && c3.a != 0) {
			return 4;
		}
	}

	// no chance
	return INF;
}

// solve for general case
int solve(const vector<point2d>& TA, const vector<point2d>& TB) {
	const vector<vector<int> > perms = { { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, { 1, 2, 0 }, { 2, 0, 1 }, { 2, 1, 0 } };
	int res = INF;
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 6; j++) {
			int subres = solve_target(vector<point2d>({ TA[perms[i][0]], TA[perms[i][1]], TA[perms[i][2]] }), vector<point2d>({ TB[perms[j][0]], TB[perms[j][1]], TB[perms[j][2]] }));
			// cout << i << ' ' << j << ' ' << subres << endl;
			res = min(res, subres);
		}
	}
	return res;
}

int main() {
	int x, y;
	while (cin >> x >> y) {
		vector<point2d> TA(3), TB(3);
		TA[0].x = fraction(x, 1);
		TA[0].y = fraction(y, 1);
		for (int i = 1; i < 3; i++) {
			cin >> x >> y;
			TA[i].x = fraction(x, 1);
			TA[i].y = fraction(y, 1);
		}
		for (int i = 0; i < 3; i++) {
			cin >> x >> y;
			TB[i].x = fraction(x, 1);
			TB[i].y = fraction(y, 1);
		}
		int res = solve(TA, TB);
		if (res != INF) {
			cout << res << endl;
		}
		else {
			cout << "Many" << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3348
final_rank: 2

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi

namespace ebi {

constexpr long double EPS = 1e-7;

const long double PI = std::acos(-1);

namespace internal {

int sgn(long double a) {
    return (a<-EPS) ? -1 : (a>EPS) ? 1 : 0;
}

long double add(long double a, long double b) {
    if(std::abs(a+b) < EPS*(std::abs(a) + std::abs(b))) return 0;
    return a+b;
}

} // namespace internal


long double arg_to_radian(long double arg) {
    return PI * arg / (long double)(180);
}

struct point {
    long double x,y;

    point() = default;

    point(long double x, long double y) : x(x), y(y) { }

    point &operator+=(const point rhs) noexcept {
        x = internal::add(x, rhs.x);
        y = internal::add(y, rhs.y);
        return *this;
    }

    point &operator-=(const point rhs) noexcept {
        x = internal::add(x, -rhs.x);
        y = internal::add(y, -rhs.y);
        return *this;
    }

    point &operator*=(const point rhs) noexcept {
        long double _x = internal::add(x*rhs.x, -y*rhs.y);
        long double _y = internal::add(x*rhs.y, y*rhs.x);
        x = _x;
        y = _y;
        return *this;
    }

    point &operator*=(const long double k) noexcept {
        x *= k;
        y *= k;
        return *this;
    }

    point &operator/=(const long double k) {
        assert(internal::sgn(k)!=0);
        x /= k;
        y /= k;
        return *this;
    }

    point operator+(const point &rhs) const noexcept {
        return point(*this) += rhs;
    }

    point operator-(const point &rhs) const noexcept {
        return point(*this) -= rhs;
    }

    point operator*(const point &rhs) const noexcept {
        return point(*this) *= rhs;
    }

    point operator*(const long double rhs) const noexcept {
        return point(*this) *= rhs;
    }

    point operator/(const long double rhs) const {
        return point(*this) /= rhs;
    }

    point operator-() const noexcept {
        return point(0, 0) - *this;
    }

    long double abs() const noexcept {
        return std::sqrt(internal::add(x*x, y*y));
    }

    long double dot(const point rhs) const noexcept {
        return internal::add(x*rhs.x, y*rhs.y);
    }

    long double det(const point rhs) const noexcept {
        return internal::add(x*rhs.y, -y*rhs.x);
    }

    // arctan(y/x) (単位はラジアン)

    long double arg() const {
        return std::atan2(y, x);
    }

    // x昇順, その後y昇順

    bool operator<(const point &rhs) const noexcept {
        if(internal::sgn(x-rhs.x)) return internal::sgn(x-rhs.x)<0;
        return internal::sgn(y-rhs.y)<0;
    }

    bool operator==(const point &rhs) const noexcept {
        if(internal::sgn(x - rhs.x) == 0 && internal::sgn(y - rhs.y) == 0) return true;
        else return false;
    }

    bool operator!=(const point &rhs) const noexcept {
        return !(*this == rhs);
    }
};

std::ostream& operator<<(std::ostream& os, const point &a) {
    return os << a.x << " " << a.y;
}

std::istream& operator>>(std::istream& os, point &a) {
    return os >> a.x >> a.y;
}

point conj(const point &a) {
    return point(a.x, -a.y);
}

// 点a をang(ラジアン)回転する

point rot(const point &a, long double ang) {
    return point(std::cos(ang) * a.x - std::sin(ang) * a.y, std::sin(ang) * a.x + std::cos(ang) * a.y);
} 

point rot90(const point &a) {
    return point(-a.y, a.x);
}

long double dot(const point &a, const point &b) {
    return a.dot(b);
}

long double det(const point &a, const point &b) {
    return a.det(b);
}

long double abs(const point &a) {
    return a.abs();
}

long double norm(const point &a) {
    return internal::add(a.x*a.x, a.y*a.y);
}

int isp(const point &a, const point &b, const point &c) {
    int flag = internal::sgn(det(b-a,c-a));
    if(flag == 0) {
        if(internal::sgn(dot(b-a, c-a))<0) return -2;
        if(internal::sgn(dot(a-b, c-b))<0) return +2;
    }
    return flag;
}

// 分割統治で最近点対を求める O(N log N)

long double closest_pair(std::vector<point> p) {
    std::sort(p.begin(), p.end());
    int n = p.size();
    auto f = [&](auto &&self, int l, int r) -> long double {
        if(r-l == 1) {
            return 1e9;
        }
        int mid = (l+r)/2;
        long double x = p[mid].x;
        long double d = std::min(self(self, l, mid), self(self, mid, r));
        std::vector<point> b;
        b.reserve(r-l);
        int j = mid;
        for(int i = l; i < mid; i++) {
            while(j < r && p[j].y <= p[i].y) {
                b.emplace_back(p[j++]);
            }
            b.emplace_back(p[i]);
        }
        while(j < r) {
            b.emplace_back(p[j++]);
        }
        for(int i = 0; i < r-l; i++) {
            p[l+i] = b[i];
        }
        b.clear();
        for(int i = l; i < r; i++) {
            if(std::abs(p[i].x - x) >= d) continue;
            for(int j = int(b.size())-1; j >= 0; j--) {
                if(p[i].y - b[j].y >= d) break;
                d = std::min(d, abs(p[i]-b[j]));
            }
            b.emplace_back(p[i]);
        }
        return d;
    };
    return f(f, 0, n);
}

// ∠ABCを求める(ラジアン)

long double angle(const point &A, const point &B, const point &C) {
    long double a = (B - C).abs(), b = (C - A).abs(), c = (A - B).abs();
    long double cos = internal::add(internal::add(a*a, c*c), -b*b)/(2.0*c*a);
    return std::acos(cos);
}

void arg_sort(std::vector<point> &a) {
    int n = a.size();
    std::vector ps(4, std::vector<point>());
    auto idx = [](point v) -> int {
        if(v.y >= 0) return (v.x >= 0) ? 0 : 1;
        else return (v.x >= 0) ? 3 : 2;
    };
    for(auto p: a) {
        assert(!(p.x == 0 && p.y == 0));
        ps[idx(p)].emplace_back(p);
    }
    a.clear();
    a.reserve(n);
    for(int i = 0; i < 4; i++) {
        std::sort(ps[i].begin(), ps[i].end(), 
            [](point &p1, point &p2) -> bool {
                int flag = internal::sgn(internal::add(p1.x * p2.y, - p2.x * p1.y));
                return flag == 0 ? (norm(p1) < norm(p2)) : flag > 0;
            });
        for(auto &p: ps[i]) a.emplace_back(p);
    }
    return;
}

template<class T>
void arg_sort_ll(std::vector<std::pair<T , T>> &a) {
    using Point = std::pair<T, T>;
    int n = a.size();
    std::vector ps(4, std::vector<Point>());
    auto idx = [](Point v) -> int {
        if(v.second >= 0) return (v.first >= 0) ? 0 : 1;
        else return (v.first >= 0) ? 3 : 2;
    };
    for(auto p: a) {
        assert(!(p.first == 0 && p.second == 0));
        ps[idx(p)].emplace_back(p);
    }
    a.clear();
    a.reserve(n);
    for(int i = 0; i < 4; i++) {
        std::sort(ps[i].begin(), ps[i].end(), 
            [](Point &p1, Point &p2) -> bool { 
                T flag = p1.first * p2.second - p2.first * p1.second;
                return flag == 0 ? (p1.first * p1.first + p1.second * p1.second < p2.first * p2.first + p2.second * p2.second) : flag > 0;
            });
        for(auto &p: ps[i]) a.emplace_back(p);
    }
    return;
}

}

namespace ebi {

struct line {
    point a,b;

    line(long double x1, long double y1, long double x2, long double y2) : a(x1, y1), b(x2, y2) { }

    line(const point &a, const point &b) : a(a), b(b) { }

    point proj(const point &p) const {
        return a + (b-a)*(dot(b-a,p-a)/norm(b-a));
    }

    point relf(const point &p) const {
        return proj(p)*double(2) - p;
    }

    long double distance(const point &c) const {
    return std::abs(det(c - a, b - a)/abs(b-a));
    }
};

int intersection(const line &a, const line &b) {
    if(internal::sgn(det(a.b-a.a, b.a-b.b)) != 0) {
        if(internal::sgn(dot(a.b-a.a, b.b-b.a)) == 0) { // 垂直
            return 1;
        }
        return 0; // 交差
    }
    else if(internal::sgn(det(a.b-a.a, b.a-a.a)) != 0) { // 平行
        return 2;
    }
    else { // 同一直線
        return 3;
    }
}

point cross_point(const point &a, const point &b, const point &c, const point &d) {
    return a + (b-a) * det(c - a, d - c) / det(b - a, d - c);
}

// 交点があるか確認する！
point cross_point(const line &s, const line &t) {
    assert(intersection(s, t) < 2);
    return s.a + (s.b - s.a) * det(t.a - s.a, t.b - t.a) / det(s.b - s.a, t.b - t.a);
}

// 直線aと点cの距離
long double distance(const line &a, const point &c) {
    return std::abs(det(c-a.a, a.b - a.a)/abs(a.b-a.a));
}

long double distance(const line &a, const line &b) {
    if(intersection(a, b) < 2) {
        return 0;
    }
    else {
        return distance(a, b.a);
    }
}

}

namespace ebi {

struct line_segment {
    point a, b;

    line_segment() = default;

    line_segment(long double x1, long double y1, long double x2, long double y2) : a(x1, y1), b(x2, y2) { }

    line_segment(const point &a, const point &b) : a(a), b(b) { }
};

// 線分ab, cd が交わるか判定
bool intersection_line_segment(const point &a, const point &b, const point &c, const point &d) {
    if(internal::sgn(isp(a,b,c)*isp(a,b,d)) <= 0 && internal::sgn(isp(c,d,a)*isp(c,d,b)) <= 0) {
        return true;
    }
    return false;
}

// 線分ab, cd が交わるか判定
bool intersection(const line_segment &a, const line_segment &b) {
    return intersection_line_segment(a.a, a.b, b.a, b.b);
}

bool intersection(const line &a, const line_segment &b) {
    if(internal::sgn(det(a.b - a.a, b.a - a.a)) * internal::sgn(det(a.b - a.a, b.b - a.a)) < 0) {
        return true;
    }
    else {
        return false;
    }
}

point cross_point(const line_segment &s, const line_segment &t) {
    assert(intersection(s, t));
    return s.a + (s.b - s.a) * det(t.a - s.a, t.b - t.a) / det(s.b - s.a, t.b - t.a);
}

long double distance(const line_segment &a, const point &c) {
    if(internal::sgn(dot(a.b - a.a, c - a.a)) < 0) {
        return abs(c-a.a);
    }
    else if(internal::sgn(dot(a.a - a.b, c - a.b)) < 0) {
        return abs(c-a.b);
    }
    else {
        return std::abs(det(c - a.a, a.b - a.a)/abs(a.b-a.a));
    }
}

long double distance(const line_segment &a, const line_segment &b) {
    if(intersection(a, b)) {
        return 0;
    }
    else {
        return std::min(std::min(distance(a, b.a), distance(a, b.b)), std::min(distance(b, a.a), distance(b, a.b)));
    }
}

long double distance(const line &a, const line_segment &b) {
    if(intersection(a, b)) {
        return 0;
    }
    else {
        return std::min(distance(a, b.a), distance(a, b.b));
    }
}

}

namespace ebi {

void main_() {
    long double x;
    while (std::cin >> x) {
        long double y;
        std::vector<point> t1(3), t2(3);
        std::cin >> y;
        t1[0] = {x, y};
        std::cin >> t1[1] >> t1[2] >> t2;
        std::vector<int> idx(3), jdx(3);
        std::iota(all(idx), 0);
        std::iota(all(jdx), 0);
        int ans = INF;

        auto move = [&](int i, int j, int k, std::vector<point> &t, point target) -> int {
            if(t[i] == target) return 0;
            int cnt = 0;
            line l1(t[j], t[j] + target - t[i]);
            line l2(t[k], t[k] + t[i] - t[j]);
            if(intersection(l1, l2) >= 2) return 1000;
            point p = cross_point(l1, l2);
            if(p != t[k]) cnt++;
            t[k] = p;
            t[i] = target;
            cnt++;
            return cnt;
        };
        do {
            do {
                {
                    int cnt = 0;
                    auto t = t1;
                    cnt += move(idx[0], idx[1], idx[2], t, t2[jdx[0]]);
                    cnt += move(idx[1], idx[0], idx[2], t, t2[jdx[1]]);
                    line_segment lseg(t[idx[2]], t2[jdx[2]]);
                    if(intersection(line(t[idx[0]], t[idx[1]]), lseg)) cnt = 1000;
                    if(t[idx[2]] != t2[jdx[2]]) cnt++;
                    chmin(ans, cnt);
                }
                {
                    int cnt = 0;
                    auto t = t1;
                    cnt += move(idx[0], idx[2], idx[1], t, t2[jdx[0]]);
                    cnt += move(idx[1], idx[0], idx[2], t, t2[jdx[1]]);
                    line_segment lseg(t[idx[2]], t2[jdx[2]]);
                    if(intersection(line(t[idx[0]], t[idx[1]]), lseg)) cnt = 1000;
                    if(t[idx[2]] != t2[jdx[2]]) cnt++;
                    chmin(ans, cnt);
                }
            } while(std::next_permutation(all(jdx)));
        } while(std::next_permutation(all(idx)));
        if(ans >= 5) {
            std::cout << "Many\n";
            continue;
        }
        std::cout << ans << '\n';
    }

}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3492
final_rank: 13

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

const double eps=1e-8;

struct point{
    double x,y;
    point() {}
    point(double x,double y): x(x), y(y) {}
    point& operator-=(const point &p){
        x -= p.x; y -= p.y;
        return *this;
    }
    point& operator+=(const point &p){
        x += p.x; y += p.y;
        return *this;
    }
    point& operator*=(double d){
        x *= d; y *= d;
        return *this;
    }
    point& operator/=(double d){
        x /= d; y /= d;
        return *this;
    }
    const point operator+ (const point& p) const;
    const point operator- (const point& p) const;
    const point operator* (double d) const;
    const point operator/ (double d) const;
    const bool operator == (const point& p) const;
};
const point point::operator+ (const point& p) const{
    point res(*this); return res += p;
}
const point point::operator- (const point& p) const{
    point res(*this); return res -= p;
}
const point point::operator* (double d) const{
    point res(*this); return res *= d;
}
const point point::operator/ (double d) const{
    point res(*this); return res /= d;
}
const bool point::operator == (const point& p) const{
    point pp(*this);
    return (p.x == pp.x and p.y == pp.y);
}
struct line{
    point A,B;
    line() {}
    line(point A, point B): A(A), B(B) {}
};

// BOJ-6487
// 平行判定
bool is_parallel(line l1, line l2){
    double dx1 = l1.B.x - l1.A.x;
    double dy1 = l1.B.y - l1.A.y;
    double dx2 = l2.B.x - l2.A.x;
    double dy2 = l2.B.y - l2.A.y;
    return abs(dy1*dx2 - dy2*dx1) < eps;
}

point vec(line L){
    return (L.B - L.A);
}
double cross(point a,point b){
    return a.x*b.y-a.y*b.x;
}
// AOJ 2596
// 直線の交点
point line_intersection(line l1, line l2){
    return l1.A + vec(l1) * cross(l2.A - l1.A, vec(l2)) / cross(vec(l1), vec(l2));
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    array<point, 3> P,Q;
    while(cin >> P[0].x >> P[0].y >> P[1].x >> P[1].y >> P[2].x >> P[2].y){
        cin >> Q[0].x >> Q[0].y >> Q[1].x >> Q[1].y >> Q[2].x >> Q[2].y;
        int res = 5;
        auto dfs=[&](auto dfs,array<point,3> s,int cnt)->void{

            auto check=[&]()->int{
                vector<int> p={0,1,2};
                int mx = 0;
                do{
                    int cnt = 0;
                    for(int i=0;i<3;i++){
                        if(s[p[i]] == Q[i])cnt++;
                    }
                    mx = max(mx, cnt);
                }while(next_permutation(p.begin(), p.end()));
                return mx;
            };

            int u = check();
            // 揃った
            if(u == 3){
                res = min(res, cnt); return;
            }
            // 枝刈り
            if(cnt+3-u >= res) return;

            // s[i]をQ[j]に揃えたい
            for(int i=0;i<3;i++){
                for(int j=0;j<3;j++){
                    if(s[i] == Q[j])continue;

                    // 直接揃えられる
                    {
                        line L1 = {s[i], Q[j]};
                        line L2;
                        if(i == 0) L2 = {s[1], s[2]};
                        else if(i == 1) L2 = {s[0], s[2]};
                        else L2 = {s[0], s[1]};

                        if(is_parallel(L1, L2)){
                            auto p = s[i];
                            s[i] = Q[j];
                            dfs(dfs,s,cnt+1);
                            s[i] = p;
                        }
                    }
                    // 1点経由
                    if(3-u+1 < res){
                        int k1 = -1, k2 = -1;
                        for(int k=0;k<3;k++){
                            if(i == k)continue;
                            if(k1 == -1) k1 = k;
                            else k2 = k;
                        }
                        // k2をずらす
                        {
                            line L1 = {s[k1], Q[j]-s[i]+s[k1]};
                            line L2 = {s[k2], s[i]-s[k1]+s[k2]};
                            auto p = line_intersection(L1, L2);
                            auto pp = s[k2];
                            s[k2] = p;
                            dfs(dfs,s,cnt+1);
                            s[k2] = pp;
                        }
                        swap(k1,k2);
                        // k1をずらす
                        {
                            line L1 = {s[k1], Q[j]-s[i]+s[k1]};
                            line L2 = {s[k2], s[i]-s[k1]+s[k2]};
                            auto p = line_intersection(L1, L2);
                            auto pp = s[k2];
                            s[k2] = p;
                            dfs(dfs,s,cnt+1);
                            s[k2] = pp;
                        }          
                    }
                }
            }

        };
        dfs(dfs,P,0);
        if(res >= 5){
            cout << "Many" << "\n";
        }
        else{
            cout << res << "\n";
        }
    }
}
accuracy: 1
time_ms: 30
memory_kb: 3484
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

using T = double;
using Vec = std::complex<T>;

const T PI = std::acos(-1);

constexpr T eps = 1e-8;
inline bool eq(T a, T b) { return std::abs(a - b) < eps; }
inline bool eq(Vec a, Vec b) { return std::abs(a - b) < eps; }
inline bool lt(T a, T b) { return a < b - eps; }
inline bool leq(T a, T b) { return a < b + eps; }

std::istream& operator>>(std::istream& is, Vec& p) {
    T x, y;
    is >> x >> y;
    p = {x, y};
    return is;
}

struct Line {
    Vec p1, p2;
    Line() = default;
    Line(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Segment {
    Vec p1, p2;
    Segment() = default;
    Segment(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Circle {
    Vec c;
    T r;
    Circle() = default;
    Circle(const Vec& c, T r) : c(c), r(r) {}
};

using Polygon = std::vector<Vec>;

T dot(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).real();
}

T cross(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).imag();
}

Vec rot(const Vec& a, T ang) {
    return a * Vec(std::cos(ang), std::sin(ang));
}

Vec perp(const Vec& a) {
    return Vec(-a.imag(), a.real());
}

Vec projection(const Line& l, const Vec& p) {
    return l.p1 + dot(p - l.p1, l.dir()) * l.dir() / std::norm(l.dir());
}

Vec reflection(const Line& l, const Vec& p) {
    return T(2) * projection(l, p) - p;
}

// 0: collinear
// 1: counter-clockwise
// 2: clockwise
int ccw(const Vec& a, const Vec& b, const Vec& c) {
    if (eq(cross(b - a, c - a), 0)) return 0;
    if (lt(cross(b - a, c - a), 0)) return -1;
    return 1;
}

void sort_by_arg(std::vector<Vec>& pts) {
    std::sort(pts.begin(), pts.end(), [&](auto& p, auto& q) {
        if ((p.imag() < 0) != (q.imag() < 0)) return (p.imag() < 0);
        if (cross(p, q) == 0) {
            if (p == Vec(0, 0)) return !(q.imag() < 0 || (q.imag() == 0 && q.real() > 0));
            if (q == Vec(0, 0)) return  (p.imag() < 0 || (p.imag() == 0 && p.real() > 0));
            return (p.real() > q.real());
        }
        return (cross(p, q) > 0);
    });
}

Vec intersection(const Line& l, const Line& m) {
    Vec r = m.p1 - l.p1;
    assert(!eq(cross(l.dir(), m.dir()), 0)); // not parallel
    return l.p1 + cross(m.dir(), r) / cross(m.dir(), l.dir()) * l.dir();
}

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) os << v[i] << " ";
    return os;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    auto check2 = [&](vector<Vec> a, vector<Vec> b) {
        if (!eq(a[0], b[0])) {
            return false;
        }
        Line l(b[1], b[1]+b[2]-b[0]);
        if (!eq(cross(l.p1 - a[1], l.p2 - a[1]), 0)) return false;
        b[1] = a[1];
        return ccw(a[0], a[1], a[2]) == ccw(b[0], b[1], b[2]);
    };

    auto check3 = [&](vector<Vec> a, vector<Vec> b) {
        if (eq(a[0], b[0])) {
            Line m(b[0], b[0]+b[1]-a[1]);
            Line n(b[2], b[2]+b[1]-b[0]);
            if (!eq(cross(m.dir(), n.dir()), 0)) {
                auto p = intersection(m, n);
                b[2] = p;
                return check2(a, b);
            }
            return false;
        } else {
            Line l(b[0], b[0]+b[2]-b[1]);
            if (!eq(cross(l.p1 - a[0], l.p2 - a[0]), 0)) return false;
            b[0] = a[0];
            return check2(a, b);
        }
    };

    auto check4 = [&](vector<Vec> a, vector<Vec> b) {
        Line l(b[0], b[0]+b[2]-b[1]);
        if (eq(cross(l.p1 - a[0], l.p2 - a[0]), 0)) {
            auto tmp = b[0];
            b[0] = a[0];
            if (check3(a, b)) return true;
            b[0] = tmp;
        }
        // move b[2]
        {
            Line m(b[1], b[1]+b[0]-a[0]);
            Line n(b[2], b[2]+b[1]-b[0]);
            if (!eq(cross(m.dir(), n.dir()), 0)) {
                auto p = intersection(m, n);
                auto tmp = b[2];
                b[2] = p;
                if (check3(a, b)) return true;
                b[2] = tmp;
            }
        }
        // move b[1]
        {
            Line m(b[2], b[2]+b[0]-a[0]);
            Line n(b[1], b[1]+b[2]-b[0]);
            if (!eq(cross(m.dir(), n.dir()), 0)) {
                auto p = intersection(m, n);
                auto tmp = b[1];
                b[1] = p;
                if (check3(a, b)) return true;
                b[1] = tmp;
            }
        }
        return false;
    };

    while (true) {
        vector<Vec> a(3), b(3);
        for (auto& x : a) cin >> x;
        for (auto& x : b) cin >> x;
        swap(a, b);
        vector<int> perm1 = {0, 1, 2};
        int ans = 5;
        do {
            vector<Vec> aa(3);
            rep(i,0,3) aa[i] = a[perm1[i]];
            vector<int> perm2 = {0, 1, 2};
            do {
                vector<Vec> bb(3);
                rep(i,0,3) bb[i] = b[perm2[i]];

                if (check3(aa, bb)) {
                    chmin(ans, 3);
                } else if (check4(aa, bb)) {
                    chmin(ans, 4);
                }
            } while (next_permutation(all(perm2)));
        } while (next_permutation(all(perm1)));
        if (ans < 5) cout << ans;
        else cout << "Many";
        cout << "\n";
        string s;
        getline(cin, s);
        if (!getline(cin, s)) break;
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3544
final_rank: 16

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

//constexpr long long int MOD = 1000000007;
constexpr long long int MOD = 998244353;
constexpr long double EPS = 1e-7;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

vector<long double>Sx;
vector<long double>Sy;

struct  Point {
	long double x;
	long double y;
	Point(long double xx, long double yy) {
		x = xx, y = yy;
	}
	Point() {

	}
	void Input() {
		cin >> x >> y;
	}
	Point operator + (const Point& c)const {
		Point box;
		box.x = x + c.x;
		box.y = y + c.y;
		return box;
	}
	Point operator - (const Point& c)const {
		Point box;
		box.x = x - c.x;
		box.y = y - c.y;
		return box;
	}
	Point operator * (const long double& b)const {
		Point box;
		box.x = x * b;
		box.y = y * b;
		return box;
	}
	bool operator <(const Point& c)const {
		if (y < c.y)return true;
		if (y > c.y)return false;
		if (x < c.x)return true;
		return false;
	}
	bool operator >(const Point& c)const {
		if (y > c.y)return true;
		if (y < c.y)return false;
		if (x > c.x)return true;
		return false;
	}
	bool operator ==(const Point& c)const {
		return abs(x - c.x) <= EPS && abs(y - c.y) <= EPS;
	}
	long double det(Point a) {
		return x * a.y - y * a.x;
	}
};

struct Line {
	long double a, b, c;
	Line(const int aa, const int bb, const int cc) {
		a = aa, b = bb, c = cc;
	}
	Line(const Point s, const Point t) {
		if (abs(s.x - t.x) < EPS) {
			a = 1;
			b = 0;
		}
		else {
			b = 1;
			a = (t.y - s.y) / (s.x - t.x);
		}
		c = s.x * a + s.y * b;
	}
};

long double dot(Point a, Point b) {
	return a.x * b.x + a.y * b.y;
}

long double cross(Point a, Point b) {
	return a.x * b.y - b.x * a.y;
}

long double Distance(Point a, Point b) {
	return sqrtl((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

long double Distance(Point a, pair<Point, Point>b) {
	Line l = Line(b.first, b.second);
	if (abs(l.a * a.x + l.b * a.y - l.c) < EPS) {
		if (abs(Distance(a, b.first) + Distance(a, b.second) - Distance(b.second, b.first)) <= sqrtl(EPS))return 0;
		return min(Distance(a, b.first), Distance(a, b.second));
	}
	long double A = powl((b.first.x - b.second.x), 2) + powl((b.first.y - b.second.y), 2);
	long double B = 2 * (a.x - b.first.x) * (b.first.x - b.second.x) + 2 * (a.y - b.first.y) * (b.first.y - b.second.y);
	long double r = B / 2 / A;
	r = -r;
	if (r >= 0 && r <= 1) {
		return Distance(a, Point(b.first.x + r * (b.second.x - b.first.x), b.first.y + r * (b.second.y - b.first.y)));
	}
	else {
		return min(Distance(a, b.first), Distance(a, b.second));
	}
}

bool LineCross(Point a1, Point a2, Point b1, Point b2) {
	return cross(a2 - a1, b1 - a1) * cross(a2 - a1, b2 - a1) < EPS && cross(b2 - b1, a1 - b1) * cross(b2 - b1, a2 - b1) < EPS && !(abs((a1 - a2).x * (a1 - b1).y - (a1 - a2).y * (a1 - b1).x) < EPS && abs((a1 - a2).x * (a1 - b2).y - (a1 - a2).y * (a1 - b2).x) < EPS && abs(Distance(a1, a2) - Distance(a1, b1) - Distance(a2, b1)) > EPS && abs(Distance(a1, a2) - Distance(a2, b2) - Distance(a1, b2)) > EPS && abs(Distance(b1, b2) - Distance(a1, b1) - Distance(a1, b2)) > EPS && abs(Distance(b1, b2) - Distance(a2, b1) - Distance(a2, b2)) > EPS);
}

long double Distance(pair<Point, Point>a, pair<Point, Point>b) {
	if (LineCross(a.first, a.second, b.first, b.second))return 0;
	return min({ Distance(a.first,b),Distance(a.second,b),Distance(b.first,a),Distance(b.second,a) });
}

Point LineCross(Line a, Line b) {
	Point ret;
	ret.x = (a.c * b.b - a.b * b.c) / (a.a * b.b - a.b * b.a);
	ret.y = -(a.c * b.a - a.a * b.c) / (a.a * b.b - a.b * b.a);
	return ret;
}

long double TriangleArea(Point a, Point b, Point c) {
	long double A, B, C;
	A = Distance(a, b);
	B = Distance(a, c);
	C = Distance(b, c);
	long double S = (A + B + C) / 2;
	return sqrtl(S * (S - A) * (S - B) * (S - C));
}

void func(vector<Point>s, vector<Point>g, vector<int>oks, vector<int>okg, int& ans, int step = 0) {
	if (step >= 5)return;
	//cout << endl;
	//for (auto i : s)cout << i.x << " " << i.y << endl;
	//for (auto i : g)cout << i.x << " " << i.y << endl;
	//cout << step << " " << oks[0] << " " << oks[1] << " " << oks[2] << endl;
	if (oks[0] && oks[1] && oks[2]) {
		ans = min(ans, step);
		return;
	}
	auto ns = s;
	for (int i = 0; i < 3; i++) {
		if (oks[i])continue;
		for (int j = 0; j < 3; j++) {
			if (okg[j])continue;
			for (int k = 0; k < 3; k++) {
				s = ns;
				if (i == k)continue;
				Line a(s[k], s[k] + s[i] - s[3 - i - k]);
				Line b(s[3 - i - k], g[j] - s[i] + s[3 - i - k]);
				//	cout << a.a << " " << a.b << " " << b.a << " " << b.b << endl;
				auto p = LineCross(a, b);
				if (isinf(p.x) || isinf(p.y))continue;
				if (isnan(p.x) || isnan(p.y))continue;
				oks[i] = 1;
				okg[j] = 1;
				int add = 1;
				if (Distance(s[k], p) <= EPS) {

				}
				else {
					s[k] = p;
					add++;
				}
				s[i] = g[j];
				if (add == 1 || !oks[k])func(s, g, oks, okg, ans, step + add);
				oks[i] = 0;
				okg[j] = 0;
			}
		}
	}
}

void Solve() {
	vector<long double>Gx(3);
	vector<long double>Gy(3);
	for (int i = 0; i < 3; i++) {
		cin >> Gx[i] >> Gy[i];
	}
	int ans = 100;
	vector<int>oks(3);
	vector<int>okg(3);
	vector<Point>S;
	vector<Point>G;
	for(int i=0;i<3;i++){
		S.push_back(Point(Sx[i], Sy[i]));
		G.push_back(Point(Gx[i], Gy[i]));
	}
	func(S, G, oks, okg, ans);
	if (ans >= 5)cout << "Many\n";
	else cout << ans << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	Sx.resize(3);
	Sy.resize(3);
	while (cin >> Sx[0] >> Sy[0]) {
		for (int i = 1; i < 3; i++) {
			cin >> Sx[i] >> Sy[i];
		}
		Solve();
	}
}
accuracy: 1
time_ms: 40
memory_kb: 3476
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

// arg(x) : argment,[-PI,PI]
using CP = complex<long double>;
#define X real()
#define Y imag()
const long double PI = acos(-1.0L);
const long double EPS = 1e-7;
bool operator==(const CP &l, const CP &r) { return norm(l - r) <= EPS; }
struct Circle {
  CP o;
  long double r;
  Circle(long double _x = 0.0L, long double _y = 0.0L, long double _r = 0.0L)
      : o(CP(_x, _y)), r(_r) {}
  Circle(CP _o, long double _r = 0.0) : o(_o), r(_r) {}
  bool operator<(const Circle &cr) const { return r < cr.r; }
};

struct Line {
  CP s, t;
  Line(long double sx = 0.0L, long double sy = 0.0L, long double tx = 0.0L,
       long double ty = 0.0L)
      : s(CP(sx, sy)), t(CP(tx, ty)) {}
  Line(CP _s, CP _t) : s(_s), t(_t) {}
};

// cos a
long double costh(const long double &a, const long double &b,
                  const long double &c) {
  return (b * b - a * a + c * c) / (2.0L * b * c);
}

// dot(a,b) = |a||b|cos x
long double dot(const CP &a, const CP &b) { return (conj(a) * b).X; }
// cross(a,b) : area of parallelogram
// sign : a-> b ,counter clockwise? + : -
long double cross(const CP &a, const CP &b) { return (conj(a) * b).Y; }
long double corner(const CP &a, const CP &b) {
  //[0,PI]
  return acos(dot(a, b) / (abs(a) * abs(b)));
}

CP projectionLP(const CP &s, const CP &t, const CP &p) {
  if (s == t) return s;
  CP base = t - s;
  long double r = dot(p - s, base) / norm(base);
  return s + base * r;
}
CP projectionLP(const Line &l, const CP &p) {
  return projectionLP(l.s, l.t, p);
}

CP reflectionLP(const CP &s, const CP &t, const CP &p) {
  CP tmp = (projectionLP(s, t, p) - p);
  tmp *= 2;
  return p + tmp;
}
CP reflectionLP(const Line &l, const CP &p) {
  return reflectionLP(l.s, l.t, p);
}

int calc_clockwiseSP(const CP &s, CP t, CP p) {
  t -= s, p -= s;
  if (cross(t, p) > EPS) return 1;    // "COUNTER_CLOCKWISE"
  if (cross(t, p) < -EPS) return -1;  //"CLOCK_WISE"
  if (dot(t, p) < 0) return 2;        // "ONLINE_BACK"
  if (norm(t) < norm(p)) return -2;   // "ONLINE_FRONT"
  return 0;                           // "ON_SEGMENT"
}
int calc_clockwiseSP(const Line &l, const CP &p) {
  return calc_clockwiseSP(l.s, l.t, p);
}

int parallel_orthogonalLL(const CP &s, CP t, const CP &a, CP b) {
  t -= s;
  b -= a;
  if (abs(cross(t, b)) <= EPS) return 2;  // "parallel"
  if (abs(dot(t, b)) <= EPS) return 1;    // "orthogonal"
  return 0;
}
int parallel_orthogonalLL(const Line &ll, const Line &lr) {
  return parallel_orthogonalLL(ll.s, ll.t, lr.s, lr.t);
}

CP intersectionLL(const CP &a, const CP &b, const CP &c, const CP &d) {
  return a + (b - a) * (cross(d - c, d - a) / cross(d - c, b - a));
}
CP intersectionLL(const Line &ll, const Line &lr) {
  return intersectionLL(ll.s, ll.t, lr.s, lr.t);
}

bool on_segSP(const CP &s, const CP &t, const CP &p) {
  // if not use end point, dot(s - p, t - p) < 0
  return abs(cross(s - p, t - p)) <= EPS && dot(s - p, t - p) <= 0;
}
bool on_segSP(const Line &l, const CP &p) { return on_segSP(l.s, l.t, p); }

// crossing segments? (a,b) and (c,d)
bool iscrossSS(const CP &a, const CP &b, const CP &c, const CP &d) {
  // parallel
  return calc_clockwiseSP(a, b, c) * calc_clockwiseSP(a, b, d) <= 0 &&
         calc_clockwiseSP(c, d, a) * calc_clockwiseSP(c, d, b) <= 0;
  // if (abs(cross(a - b, c - d)) <= EPS) {
  //   return on_segSP(a, b, c) || on_segSP(a, b, d) || on_segSP(c, d, a) ||
  //          on_segSP(c, d, b);
  // }
  // CP isp = intersectionLL(a, b, c, d);
  // return on_segSP(a, b, isp) && on_segSP(c, d, isp);
}

bool iscrossSS(const Line &ll, const Line &lr) {
  return iscrossSS(ll.s, ll.t, lr.s, lr.t);
}

long double distLP(const CP &s, const CP &t, const CP &p) {
  return abs(cross(t - s, p - s) / abs(t - s));
}
long double distLP(const Line &l, const CP &p) { return distLP(l.s, l.t, p); }

long double distSP(const CP &s, const CP &t, const CP &p) {
  if (dot(t - s, p - s) < 0) return abs(p - s);
  if (dot(s - t, p - t) < 0) return abs(p - t);
  return distLP(s, t, p);
}
long double distSP(const Line &l, const CP &p) { return distSP(l.s, l.t, p); }

long double distSS(const CP &a, const CP &b, const CP &c, const CP &d) {
  long double res = 1e18;
  if (iscrossSS(a, b, c, d)) return 0.0L;
  res = min(res, distSP(a, b, c));
  res = min(res, distSP(a, b, d));
  res = min(res, distSP(c, d, a));
  res = min(res, distSP(c, d, b));
  return res;
}
long double distSS(const Line &ll, const Line &lr) {
  return distSS(ll.s, ll.t, lr.s, lr.t);
}

// counter clockwise
bool is_convex(const vector<CP> &pol) {
  int n = pol.size();
  for (int i = 0; i < n; ++i)
    if (cross(pol[(i + 1) % n] - pol[i], pol[(i + 2) % n] - pol[(i + 1) % n]) <
        -EPS)
      return 0;
  return 1;
}

vector<CP> convex_hull(vector<CP> &ps) {
  auto lmd = [&](const CP &l, const CP &r) {
    if (l.X != r.X) return l.X < r.X;
    return l.Y < r.Y;
  };
  vector<CP> res;
  int psize = ps.size();
  sort(ps.begin(), ps.end(), lmd);
  int k = 0;
  res.resize(psize * 2);
  for (int i = 0; i < psize; ++i) {
    while (k > 1 && cross(res[k - 1] - res[k - 2], ps[i] - res[k - 1]) <= 0)
      --k;
    res[k++] = ps[i];
  }
  for (int i = psize - 2, t = k; i >= 0; --i) {
    while (k > t && cross(res[k - 1] - res[k - 2], ps[i] - res[k - 1]) <= 0)
      --k;
    res[k++] = ps[i];
  }
  res.resize(k - 1);
  return res;
}

long double convex_diameter(const vector<CP> &pol) {
  vector<CP> ps = pol;
  ps = convex_hull(ps);
  int n = ps.size(), i = 0, j = 0;
  if (n < 2) return 0.0L;
  if (n == 2) return abs(ps[0] - ps[1]);
  for (int k = 0; k < n; ++k) {
    if (ps[k].X < ps[i].X) i = k;
    if (ps[k].X > ps[j].X) j = k;
  }
  long double res = 0;
  int si = i, sj = j;
  while (i != sj || j != si) {
    res = max(res, abs(ps[i] - ps[j]));
    if (cross(ps[(i + 1) % n] - ps[i], ps[(j + 1) % n] - ps[j]) < 0)
      (++i) %= n;
    else
      (++j) %= n;
  }
  return res;
}

vector<CP> convex_cut(const vector<CP> &pol, const CP &s, const CP &t) {
  vector<CP> res;
  int n = pol.size();
  for (int i = 0; i < n; ++i) {
    CP nows = pol[i], nowt = pol[(i + 1) % n];
    if (cross(t - s, nows - s) >= -EPS) res.push_back(nows);
    if (cross(t - s, nows - s) * cross(t - s, nowt - s) < 0)
      res.push_back(intersectionLL(s, t, nows, nowt));
  }
  return res;
}
vector<CP> convex_cut(const vector<CP> &pol, const Line &l) {
  return convex_cut(pol, l.s, l.t);
}

// number of tangents
int iscrossCC(Circle l, Circle r) {
  if (l.r < r.r) swap(l, r);
  long double distlr = abs(l.o - r.o);
  if (l.r + r.r < distlr)
    return 4;  // not touch
  else if (abs(distlr - l.r - r.r) <= EPS)
    return 3;  // circumscription
  else if (l.r - r.r < distlr)
    return 2;  // cross
  else if (abs(distlr - l.r + r.r) <= EPS)
    return 1;  // inscribed
  else         // contain
    return 0;
}

vector<CP> intersectionCC(const Circle &c1, const Circle &c2) {
  vector<CP> res;
  if (iscrossCC(c1, c2) == 4) return res;

  long double d = abs(c1.o - c2.o);
  long double a = acos(costh(c2.r, c1.r, d));
  long double t = atan2(c2.o.imag() - c1.o.imag(), c2.o.real() - c1.o.real());
  res.push_back(c1.o + CP(cos(t + a) * c1.r, sin(t + a) * c1.r));
  res.push_back(c1.o + CP(cos(t - a) * c1.r, sin(t - a) * c1.r));
  if (res[0].X > res[1].X || (res[0].X == res[1].X && res[0].Y > res[1].Y))
    swap(res[0], res[1]);
  return res;
}

vector<CP> intersectionCL(const Circle &ci, const CP &s, CP t) {
  vector<CP> res(2, projectionLP(s, t, ci.o));
  long double r = sqrt(ci.r * ci.r - norm(res[0] - ci.o));
  if (r <= EPS || t == s) return res;
  t -= s;
  t *= r / abs(t);
  res[0] += t;
  res[1] -= t;
  if (res[0].X > res[1].X || (res[0].X == res[1].X && res[0].Y > res[1].Y))
    swap(res[0], res[1]);
  return res;
}
vector<CP> intersectionCL(const Circle &ci, const Line &l) {
  return intersectionCL(ci, l.s, l.t);
}

vector<CP> contactCP(const Circle &ci, const CP &p) {
  vector<CP> res;
  long double d = abs(ci.o - p);
  if (abs(d - ci.r) <= EPS) {
    res.push_back(p);
    return res;
  } else if (d < ci.r)
    return res;
  long double arg = asin(ci.r / d);
  res.push_back((ci.o - p) * CP(cos(arg), sin(arg)));
  res[0] *= (d * cos(arg)) / abs(res[0]);
  res[0] += p;
  res.push_back(reflectionLP(p, ci.o, res[0]));
  if (res[0].X > res[1].X || (res[0].X == res[1].X && res[0].Y > res[1].Y))
    swap(res[0], res[1]);
  return res;
}

vector<Line> tangentCC(Circle cl, Circle cr) {
  vector<Line> res;
  if (cl.r < cr.r) swap(cl, cr);
  long double g = abs(cl.o - cr.o);
  if (abs(g - 0.0L) <= EPS) return res;
  CP hor = (cr.o - cl.o) / g, ver;
  ver = hor * (CP(cos(PI * 0.5L), sin(PI * 0.5L)));
  for (int s : {-1, 1}) {
    long double h = (cl.r + s * cr.r) / g;
    if (abs(1 - h * h) <= EPS) {
      res.emplace_back(cl.o + hor * cl.r, cl.o + (hor + ver) * cl.r);
    } else if (1 - h * h > 0) {
      CP nhor = hor * h, nver = ver * sqrtl(1 - h * h);
      res.emplace_back(cl.o + (nhor + nver) * cl.r,
                       cr.o - (nhor + nver) * (cr.r * s));
      res.emplace_back(cl.o + (nhor - nver) * cl.r,
                       cr.o - (nhor - nver) * (cr.r * s));
    }
  }
  return res;
}

long double areaPol(const vector<CP> &pol) {
  int n = pol.size();
  long double res = 0;
  for (int i = 0; i < n; ++i)
    res += (pol[(i - 1 + n) % n].X - pol[(i + 1) % n].X) * pol[i].Y;
  return res / 2.0L;
}

int containPolP(const vector<CP> &pol, CP p) {
  bool con = 0, onseg = 0;
  int n = pol.size();
  for (int i = 0; i < n; ++i) {
    onseg |= on_segSP(pol[i], pol[(i + 1) % n], p);
    CP s = pol[i] - p, t = pol[(i + 1) % n] - p;
    if (s.Y > t.Y) swap(s, t);
    if (s.Y * t.Y <= 0 && t.Y > 0 && cross(s, t) < 0) con = !con;
  }
  if (onseg) return 1;
  if (con) return 2;
  return 0;
}

long double closest_pair(vector<CP> &ps, int l = -1, int r = -1,
                         bool reqsqrt = 0) {
  if (l == r && l == -1) {
    l = 0;
    r = ps.size();
    reqsqrt = 1;
    auto lmd = [&](const CP &l, const CP &r) {
      if (l.X != r.X) return l.X < r.X;
      return l.Y < r.Y;
    };
    sort(ps.begin(), ps.end(), lmd);
  }
  if (r - l < 2) return 1e18;
  if (r - l == 2) {
    if (ps[l].Y > ps[l + 1].Y) swap(ps[l], ps[l + 1]);
    if (reqsqrt) return abs(ps[l] - ps[l + 1]);
    return norm(ps[l] - ps[l + 1]);
  }
  int mid = (l + r) / 2;
  long double x = ps[mid].X,
              res = min(closest_pair(ps, l, mid), closest_pair(ps, mid, r));
  auto f = [](CP pl, CP pr) { return pl.Y < pr.Y; };
  inplace_merge(ps.begin() + l, ps.begin() + mid, ps.begin() + r, f);
  vector<CP> tmp;
  for (int i = l; i < r; ++i) {
    long double dx = abs(ps[i].X - x);
    int tsize = tmp.size();
    if (dx * dx >= res) continue;
    for (int j = 0; j < tsize; ++j) {
      CP delta = ps[i] - tmp[tsize - 1 - j];
      if (delta.Y * delta.Y >= res) break;
      res = min(res, norm(delta));
    }
    tmp.push_back(ps[i]);
  }
  if (reqsqrt) res = sqrtl(res);
  return res;
}

Circle min_ball(vector<CP> ps) {
  int n = ps.size();
  if (n == 1) return Circle(ps[0], 0.0L);
  mt19937 mt(int(time(0)));
  shuffle(ps.begin(), ps.end(), mt);
  auto make3 = [](const CP &a, const CP &b, const CP &c) {
    long double A = norm(b - c), B = norm(c - a), C = norm(a - b),
                S = cross(b - a, c - a);
    CP p = (A * (B + C - A) * a + B * (C + A - B) * b + C * (A + B - C) * c) /
           (4 * S * S);
    long double nowr = norm(p - a);
    return Circle(p, nowr);
  };
  auto make2 = [](const CP &a, const CP &b) {
    CP c = (a + b) / 2.0L;
    long double nowr = norm(a - c);
    return Circle(c, nowr);
  };
  auto in_circle = [](const CP &a, const Circle &c) {
    return norm(a - c.o) <= c.r + EPS;
  };
  Circle res = make2(ps[0], ps[1]);
  for (int i = 2; i < n; ++i)
    if (!in_circle(ps[i], res)) {
      res = make2(ps[0], ps[i]);
      for (int j = 1; j < i; ++j)
        if (!in_circle(ps[j], res)) {
          res = make2(ps[i], ps[j]);
          for (int k = 0; k < j; ++k)
            if (!in_circle(ps[k], res)) res = make3(ps[i], ps[j], ps[k]);
        }
    }
  res.r = sqrtl(res.r);
  return res;
}

bool arg_comp(CP a, CP b) {
  int up_down_a = a.Y > 0 || (abs(a.Y) <= EPS && a.X >= 0);
  int up_down_b = b.Y > 0 || (abs(b.Y) <= EPS && b.X >= 0);
  if (up_down_a != up_down_b) return up_down_a < up_down_b;
  if (a.X * b.Y == a.Y * b.X) return norm(a) < norm(b);
  return calc_clockwiseSP(CP(0, 0), a, b) == 1;
}
bool operator<(const Line &l, const Line &r) {
  CP lp = l.t - l.s, rp = r.t - r.s;
  return arg_comp(lp, rp);
}

vector<CP> s, t;
vector<int> ps(3), pt(3), pf = {1, 2};

int solve();
int calc();

int main() {
  int x, y;
  while (cin >> x) {
    s.clear(), t.clear();
    pf = {1, 2};
    cin >> y;
    s.emplace_back(x, y);
    for (int i = 0; i < 2; ++i) {
      cin >> x >> y;
      s.emplace_back(x, y);
    }
    for (int i = 0; i < 3; ++i) {
      cin >> x >> y;
      t.emplace_back(x, y);
    }
    int res = solve();
    if (res >= 5)
      cout << "Many" << endl;
    else
      cout << res << endl;
  }
  return 0;
}

int solve() {
  int res = 5;
  vector<CP> vs = s, vt = t;
  do {
    iota(ps.begin(), ps.end(), 0);
    do {
      iota(pt.begin(), pt.end(), 0);
      do {
        for (int i = 0; i < 3; ++i) s[i] = vs[ps[i]], t[i] = vt[pt[i]];
        res = min(res, calc());
      } while (next_permutation(pt.begin(), pt.end()));
    } while (next_permutation(ps.begin(), ps.end()));
  } while (next_permutation(pf.begin(), pf.end()));
  return res;
}

int calc() {
  int res = 0;
  if (abs(t[0] - s[0]) > EPS) {
    CP veca = t[0] - s[0], tar = s[pf[0]], vecb = s[0] - tar;
    veca /= abs(veca), vecb /= abs(vecb);
    CP x = tar + veca, y = s[pf[1]], z = y + vecb;
    if (abs(calc_clockwiseSP(s[0], t[0], tar)) != 1) return 5;
    assert(parallel_orthogonalLL(s[0], tar, z, y) == 2);
    CP is = intersectionLL(tar, x, y, z);
    if (abs(is - y) > EPS) s[pf[1]] = is, ++res;
    ++res, s[0] = t[0];
  }
  if (abs(t[1] - s[1]) > EPS) {
    CP veca = t[1] - s[1], vecb = s[0] - s[1];
    veca /= abs(veca), vecb /= abs(vecb);
    CP x = s[0] + veca, y = s[2] + vecb;
    CP is = intersectionLL(s[0], x, s[2], y);
    if (abs(is - s[2]) > EPS) s[2] = is, ++res;
    ++res, s[1] = t[1];
  }
  if (abs(t[2] - s[2]) > EPS) {
    if (parallel_orthogonalLL(s[2], t[2], s[0], s[1]) != 2) return 5;
    ++res;
  }
  return res;
}
accuracy: 1
time_ms: 60
memory_kb: 3504
final_rank: 14

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
const int mod = 1e9 + 7;
//const int mod = 998244353;

namespace geometry {
    // Point : 複素数型を位置ベクトルとして扱う
    // 実軸(real)をx軸、挙軸(imag)をy軸として見る
    using D = long double;
    using Point = complex<D>;
    const D EPS = 1e-7;
    const D PI = acosl(-1);

    inline bool equal(const D &a, const D &b) { return fabs(a - b) < EPS; }

    // 単位ベクトル(unit vector)を求める
    Point unitVector(const Point &a) { return a / abs(a); }

    // 法線ベクトル(normal vector)を求める
    // 90度回転した単位ベクトルをかける
    // -90度がよければPoint(0, -1)をかける
    Point normalVector(const Point &a) { return a * Point(0, 1); }

    // 内積(dot product) : a・b = |a||b|cosΘ
    D dot(const Point &a, const Point &b) {
        return (a.real() * b.real() + a.imag() * b.imag());
    }

    // 外積(cross product) : a×b = |a||b|sinΘ
    D cross(const Point &a, const Point &b) {
        return (a.real() * b.imag() - a.imag() * b.real());
    }

    // 点pを反時計回りにtheta度回転
    // thetaはラジアン！！！
    Point rotate(const Point &p, const D &theta) {
        return Point(cos(theta) * p.real() - sin(theta) * p.imag(),
                     sin(theta) * p.real() + cos(theta) * p.imag());
    }

    // ラジアン->度
    D radianToDegree(const D &radian) { return radian * 180.0 / PI; }

    // 度->ラジアン
    D degreeToRadian(const D &degree) { return degree * PI / 180.0; }

    // 点の回転方向
    // 点a, b, cの位置関係について(aが基準点)
    int ccw(const Point &a, Point b, Point c) {
        b -= a, c -= a;
        // 点a, b, c が
        // 反時計回りの時、
        if(cross(b, c) > EPS) return 1;
        // 時計回りの時、
        if(cross(b, c) < -EPS) return -1;
        // c, a, bがこの順番で同一直線上にある時、
        if(dot(b, c) < 0) return 2;
        // a, b, cがこの順番で同一直線上にある場合、
        if(norm(b) < norm(c)) return -2;
        // cが線分ab上にある場合、
        return 0;
    }

    // Line : 直線を表す構造体
    // b - a で直線・線分を表せる
    struct Line {
        Point a, b;
        Line() = default;
        Line(Point a, Point b) : a(a), b(b) {}
        // Ax+By=C
        Line(D A, D B, D C) {
            if(equal(A, 0)) {
                a = Point(0, C / B), b = Point(1, C / B);
            } else if(equal(B, 0)) {
                b = Point(C / A, 0), b = Point(C / A, 1);
            } else {
                a = Point(0, C / B), b = Point(C / A, 0);
            }
        }
    };

    // Segment : 線分を表す構造体
    // Lineと同じ
    struct Segment : Line {
        Segment() = default;

        Segment(Point a, Point b) : Line(a, b) {}
    };

    // Circle : 円を表す構造体
    // pが中心の位置ベクトル、rは半径
    struct Circle {
        Point p;
        D r;

        Circle() = default;

        Circle(Point p, D r) : p(p), r(r) {}
    };

    // 2直線の直交判定 : a⊥b <=> dot(a, b) = 0
    bool isOrthogonal(const Line &a, const Line &b) {
        return equal(dot(a.b - a.a, b.b - b.a), 0);
    }
    // 2直線の平行判定 : a//b <=> cross(a, b) = 0
    bool isParallel(const Line &a, const Line &b) {
        return equal(cross(a.b - a.a, b.b - b.a), 0);
    }

    // 点cが直線ab上にあるか
    bool isPointOnLine(const Point &a, const Point &b, const Point &c) {
        return isParallel(Line(a, b), Line(a, c));
    }

    // 点cが"線分"ab上にあるか
    bool isPointOnSegment(const Point &a, const Point &b, const Point &c) {
        // |a-c| + |c-b| <= |a-b| なら線分上
        return (abs(a - c) + abs(c - b) < abs(a - b) + EPS);
    }

    // 直線lと点pの距離を求める
    D distanceBetweenLineAndPoint(const Line &l, const Point &p) {
        return abs(cross(l.b - l.a, p - l.a)) / abs(l.b - l.a);
    }

    // 線分lと点pの距離を求める
    // 定義：点pから「線分lのどこか」への最短距離
    D distanceBetweenSegmentAndPoint(const Segment &l, const Point &p) {
        if(dot(l.b - l.a, p - l.a) < EPS) return abs(p - l.a);
        if(dot(l.a - l.b, p - l.b) < EPS) return abs(p - l.b);
        return abs(cross(l.b - l.a, p - l.a)) / abs(l.b - l.a);
    }

    // 直線s, tの交点の計算
    Point crossPoint(const Line &s, const Line &t) {
        D d1 = cross(s.b - s.a, t.b - t.a);
        D d2 = cross(s.b - s.a, s.b - t.a);
        if(equal(abs(d1), 0) && equal(abs(d2), 0)) return t.a;
        return t.a + (t.b - t.a) * (d2 / d1);
    }

    // 線分s, tの交点の計算
    Point crossPoint(const Segment &s, const Segment &t) {
        return crossPoint(Line(s), Line(t));
    }

    // 線分sと線分tが交差しているかどうか
    // bound:線分の端点を含むか
    bool isIntersect(const Segment &s, const Segment &t, bool bound) {
        return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) < bound &&
               ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) < bound;
    }

    // 線分sとtの距離
    D distanceBetweenSegments(const Segment &s, const Segment &t) {
        if(isIntersect(s, t, 1)) return (D)(0);
        D ans = distanceBetweenSegmentAndPoint(s, t.a);
        chmin(ans, distanceBetweenSegmentAndPoint(s, t.b));
        chmin(ans, distanceBetweenSegmentAndPoint(t, s.a));
        chmin(ans, distanceBetweenSegmentAndPoint(t, s.b));
        return ans;
    }

    // 射影(projection)
    // 直線(線分)lに点pから引いた垂線の足を求める
    Point projection(const Line &l, const Point &p) {
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }

    Point projection(const Segment &l, const Point &p) {
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }

    // 反射(reflection)
    // 直線lを対称軸として点pと線対称の位置にある点を求める
    Point reflection(const Line &l, const Point &p) {
        return p + (projection(l, p) - p) * (D)2.0;
    }

    // 2つの円の交差判定
    // 返り値は共通接線の数
    int isIntersect(const Circle &c1, const Circle &c2) {
        D d = abs(c1.p - c2.p);
        // 2つの円が離れている場合
        if(d > c1.r + c2.r + EPS) return 4;
        // 外接している場合
        if(equal(d, c1.r + c2.r)) return 3;
        // 内接している場合
        if(equal(d, abs(c1.r - c2.r))) return 1;
        // 内包している場合
        if(d < abs(c1.r - c2.r) - EPS) return 0;
        return 2;
    }

    // 2つの円の交点
    vector<Point> crossPoint(const Circle &c1, const Circle &c2) {
        vector<Point> res;
        int mode = isIntersect(c1, c2);
        // 2つの中心の距離
        D d = abs(c1.p - c2.p);
        // 2円が離れている場合
        if(mode == 4) return res;
        // 1つの円がもう1つの円に内包されている場合
        if(mode == 0) return res;
        // 2円が外接する場合
        if(mode == 3) {
            D t = c1.r / (c1.r + c2.r);
            res.emplace_back(c1.p + (c2.p - c1.p) * t);
            return res;
        }
        // 内接している場合
        if(mode == 1) {
            if(c2.r < c1.r - EPS) {
                res.emplace_back(c1.p + (c2.p - c1.p) * (c1.r / d));
            } else {
                res.emplace_back(c2.p + (c1.p - c2.p) * (c2.r / d));
            }
            return res;
        }
        // 2円が重なる場合
        D rc1 = (c1.r * c1.r + d * d - c2.r * c2.r) / (2 * d);
        D rs1 = sqrt(c1.r * c1.r - rc1 * rc1);
        if(c1.r - abs(rc1) < EPS) rs1 = 0;
        Point e12 = (c2.p - c1.p) / abs(c2.p - c1.p);
        res.emplace_back(c1.p + rc1 * e12 + rs1 * e12 * Point(0, 1));
        res.emplace_back(c1.p + rc1 * e12 + rs1 * e12 * Point(0, -1));
        return res;
    }

    // 点pが円cの内部(円周上も含む)に入っているかどうか
    bool isInCircle(const Circle &c, const Point &p) {
        D d = abs(c.p - p);
        return (equal(d, c.r) || d < c.r - EPS);
    }

    // 円cと直線lの交点
    vector<Point> crossPoint(const Circle &c, const Line &l) {
        vector<Point> res;
        D d = distanceBetweenLineAndPoint(l, c.p);
        // 交点を持たない
        if(d > c.r + EPS) return res;
        // 接する
        Point h = projection(l, c.p);
        if(equal(d, c.r)) {
            res.emplace_back(h);
            return res;
        }
        Point e = unitVector(l.b - l.a);
        D ph = sqrt(c.r * c.r - d * d);
        res.emplace_back(h - e * ph);
        res.emplace_back(h + e * ph);
        return res;
    }

    // 点pを通る円cの接線
    // 2本あるので、接点のみを返す
    vector<Point> tangentToCircle(const Point &p, const Circle &c) {
        return crossPoint(c, Circle(p, sqrt(norm(c.p - p) - c.r * c.r)));
    }

    // 円の共通接線
    vector<Line> tangent(const Circle &a, const Circle &b) {
        vector<Line> ret;
        // 2円の中心間の距離
        D g = abs(a.p - b.p);
        // 円が内包されている場合
        if(equal(g, 0)) return ret;
        Point u = unitVector(b.p - a.p);
        Point v = rotate(u, PI / 2);
        for(int s : {-1, 1}) {
            D h = (a.r + b.r * s) / g;
            if(equal(h * h, 1)) {
                ret.emplace_back(a.p + (h > 0 ? u : -u) * a.r,
                                 a.p + (h > 0 ? u : -u) * a.r + v);

            } else if(1 - h * h > 0) {
                Point U = u * h, V = v * sqrt(1 - h * h);
                ret.emplace_back(a.p + (U + V) * a.r,
                                 b.p - (U + V) * (b.r * s));
                ret.emplace_back(a.p + (U - V) * a.r,
                                 b.p - (U - V) * (b.r * s));
            }
        }
        return ret;
    }

    // 多角形の面積を求める
    D PolygonArea(const vector<Point> &p) {
        D res = 0;
        int n = p.size();
        for(int i = 0; i < n - 1; i++) res += cross(p[i], p[i + 1]);
        res += cross(p[n - 1], p[0]);
        return res * 0.5;
    }

    // 凸多角形かどうか
    bool isConvex(const vector<Point> &p) {
        int n = p.size();
        int now, pre, nxt;
        for(int i = 0; i < n; i++) {
            pre = (i - 1 + n) % n;
            nxt = (i + 1) % n;
            now = i;
            if(ccw(p[pre], p[now], p[nxt]) == -1) return false;
        }
        return true;
    }

    // 凸包 O(NlogN)
    vector<Point> ConvexHull(vector<Point> &p) {
        int n = (int)p.size(), k = 0;
        sort(all(p), [](const Point &a, const Point &b) {
            return (real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b));
        });
        vector<Point> ch(2 * n);
        // 一直線上の3点を含める -> (< -EPS)
        // 含め無い -> (< EPS)
        for(int i = 0; i < n; ch[k++] = p[i++]) { // lower
            while(k >= 2 &&
                  cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < EPS)
                --k;
        }
        for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) { // upper
            while(k >= t &&
                  cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < EPS)
                --k;
        }
        ch.resize(k - 1);
        return ch;
    }

    // 多角形gに点pが含まれているか?
    // 含まれる:2, 辺上にある:1, 含まれない:0
    int isContained(const vector<Point> &g, const Point &p) {
        bool in = false;
        int n = (int)g.size();
        for(int i = 0; i < n; i++) {
            Point a = g[i] - p, b = g[(i + 1) % n] - p;
            if(imag(a) > imag(b)) swap(a, b);
            if(imag(a) <= EPS && EPS < imag(b) && cross(a, b) < -EPS) in = !in;
            if(cross(a, b) == 0 && dot(a, b) <= 0) return 1;
        }
        return (in ? 2 : 0);
    }

    vector<Point> convex_cut(const vector<Point> &g, Line l){
        vector<Point> ret;
        for(int i=0; i<g.size(); i++){
            Point now = g[i], nxt = g[(i+1)%g.size()];
            if(ccw(l.a,l.b,now) != -1) ret.push_back(now);
            if(ccw(l.a,l.b,now) * ccw(l.a,l.b,nxt) < 0){
                ret.push_back(crossPoint(Line(now,nxt),l));
            }
        }
        return ret;
    }

    bool equal (const Point &a, const Point &b) {
        return equal(a.real(),b.real()) && equal(a.imag(),b.imag());
    }

    D circlesIntersectArea(Circle &a, Circle &b){
        double d = abs(a.p - b.p);
        if(d >= a.r + b.r - EPS) return 0; //2円が離れている
        auto R = minmax(a.r,b.r);
        if(d <= R.second - R.first + EPS) return R.first*R.first*pi; //円が円を内包する
        D theta1 = acos((d*d + a.r*a.r - b.r*b.r)/(2*a.r*d));
        D theta2 = acos((d*d + b.r*b.r - a.r*a.r)/(2*b.r*d));
        D ret = a.r*a.r*(theta1-cos(theta1)*sin(theta1)) + b.r*b.r*(theta2-cos(theta2)*sin(theta2));
        return ret;
    }
} // namespace geometry

using namespace geometry;


int main(){
    int x,y;
    while(cin >> x){
        cin >> y;
        vector<Point> a(3),b(3);
        a[0] = Point(x,y);
        rep(i,2){
            int x,y; cin >> x >> y;
            a[i+1] = Point(x,y);
        }
        rep(i,3){
            int x,y; cin >> x >> y;
            b[i] = Point(x,y);
        }
        vl nxt(3); rep(i,3) nxt[i] = i;
        vl nxt2(3); rep(i,3) nxt2[i] = i;

        //3回
        bool f = false;
        bool h = false;
        do{
            do{
                auto c = a;
                bool g = true;
                rep(i,3){
                    int id = nxt[i];
                    int u = (id+1) % 3;
                    int v = (id+2) % 3;
                    if(isParallel(Line(c[u],c[v]), Line(c[id],b[nxt2[i]]))){
                        c[id] = b[nxt2[i]];
                        if(i == 0) h = true;
                    }else{
                        g = false; break;
                    }
                }
                if(g) f = true;
            }while(next_permutation(all(nxt2)));
        }while(next_permutation(all(nxt)));
        if(f){
            cout << "3\n";
            continue;
        }

        //4回
        if(h){
            cout << "4\n";
            continue;
        }
        rep(j,3){ //最初に動かすもの
            do{
                if(j == nxt[0]) continue;
                do{
                    auto c = a;
                    Point vec = Point(c[(j+1)%3]-c[(j+2)%3]);
                    Line l1(c[j],c[j]+vec);
                    Point vec2(c[nxt[0]]-b[nxt2[0]]);
                    Line l2(c[3-j-nxt[0]]+vec2,c[3-j-nxt[0]]);
                    if(isParallel(l1,l2)) continue;
                    c[j] = crossPoint(l1,l2);

                    //3回のときと同じ
                    bool g = true;
                    rep(i,3){
                        int id = nxt[i];
                        int u = (id+1) % 3;
                        int v = (id+2) % 3;
                        if(isParallel(Line(c[u],c[v]), Line(c[id],b[nxt2[i]]))){
                            c[id] = b[nxt2[i]];
                        }else{
                            if(i == 0) assert(false);
                            g = false; break;
                        }
                    }
                    if(g) f = true;
                }while(next_permutation(all(nxt2)));
            }while(next_permutation(all(nxt)));
        }
        if(f){
            cout << "4\n";
        }else{
            cout << "Many\n";
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3468
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double EPS = 0.00001;
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(double k){
    return point(x * k, y * k);
  }
  point operator /(double k){
    return point(x / k, y / k);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
bool is_parallel(line L1, line L2){
  return abs(cross(vec(L1), vec(L2))) <= EPS;
}
line parallel(point P, line L){
  return line(P, P + vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
bool ok(vector<point> A, vector<point> B){
  vector<int> p = {0, 1, 2}, q = {0, 1, 2};
  while (true){
    while (true){
      if (is_parallel(line(A[p[0]], B[q[0]]), line(A[p[1]], A[p[2]]))){
        if (is_parallel(line(A[p[1]], B[q[1]]), line(B[q[0]], A[p[2]]))){
          if (is_parallel(line(A[p[2]], B[q[2]]), line(B[q[0]], B[q[1]]))){
            return true;
          }
        }
      }
      if (!next_permutation(q.begin(), q.end())){
        break;
      }
    }
    if (!next_permutation(p.begin(), p.end())){
      break;
    }
  }
  return false;
}
int main(){
  while (true){
    vector<point> A(3);
    cin >> A[0].x;
    if (!cin){
      break;
    }
    cin >> A[0].y;
    for (int i = 1; i < 3; i++){
      cin >> A[i].x >> A[i].y;
    }
    vector<point> B(3);
    for (int i = 0; i < 3; i++){
      cin >> B[i].x >> B[i].y;
    }
    vector<point> C = {A[0], A[1], A[2], B[0], B[1], B[2]};
    if (ok(A, B)){
      cout << 3 << endl;
    } else {
      bool P = false;
      for (int i = 0; i < 2; i++){
        for (int j = 0; j < 3; j++){
          line L1 = parallel(A[j], line(A[(j + 1) % 3], A[(j + 2) % 3]));
          for (int k = 0; k < 6; k++){
            for (int l = 0; l < 6; l++){
              for (int m = l + 1; m < 6; m++){
                line L2 = parallel(C[k], line(C[l], C[m]));
                if (!is_parallel(L1, L2)){
                  vector<point> A2 = A;
                  A2[j] = line_intersection(L1, L2);
                  if (ok(A2, B) || ok(B, A2)){
                    P = true;
                  }
                }
              }
            }
          }
        }
        swap(A, B);
      }
      if (P){
        cout << 4 << endl;
      } else {
        cout << "Many" << endl;
      }
    }
  }
}
accuracy: 1
time_ms: 450
memory_kb: 3124
final_rank: 1