#include <bits/stdc++.h>   using namespace std;   struct point {     double x, y;   };   double dist(point P, point Q) {     double dx = P.x - Q.x, dy = P.y - Q.y;     return sqrt(dx * dx + dy * dy);   }   vector<point> crossing(point O1, double r1, point O2, double r2) {     double d = dist(O1, O2);     double t = (d * d + r1 * r1 - r2 * r2) / 2.0 / d / d;     double fx = O1.x + (O2.x - O1.x) * t, fy = O1.y + (O2.y - O1.y) * t;     double h = sqrt(r1 * r1 - t * d * t * d);     double dx = (O2.y - O1.y) / d * h, dy = (O1.x - O2.x) / d * h;     vector<point> ans;     point ans1 = {fx + dx, fy + dy};     ans.push_back(ans1);     point ans2 = {fx - dx, fy - dy};     ans.push_back(ans2);     return ans;   }   vector<double> tri[10];   void read(int id) {     point P, Q, R;     cin >> P.x >> P.y >> Q.x >> Q.y >> R.x >> R.y;     tri[id].push_back(dist(P, Q));     tri[id].push_back(dist(P, R));     tri[id].push_back(dist(Q, R));     sort(tri[id].begin(), tri[id].end());   }   bool quad(double a, double b, double c, double d) {     double x[] = {a, b, c, d};     sort(x, x + 4);     return (x[0] + x[1] + x[2] + 1.0E-9 > x[3]);   }   bool triineq(double a, double b, double c) {     double x[] = {a, b, c};     sort(x, x + 3);     return (x[0] + x[1] + 1.0E-9 > x[2]);   }   bool equals(double x, double y) { return (x - y < 1.0E-9 && x - y > -1.0E-9); }   int N;   point P[20];   int a[(1 << 4)], dp[(1 << 4)];   void dfs(int mask) {     int i, x, y, z;     a[mask] = min(a[mask], N);     for ((i) = 0; (i) < (int)(4); (i)++)       if (!(mask & (1 << i))) {         int mask2 = (mask | (1 << i));         bool found = false;         for ((x) = 0; (x) < (int)(N); (x)++)           for ((y) = 0; (y) < (int)(N); (y)++)             for ((z) = 0; (z) < (int)(N); (z)++) {               if (equals(dist(P[x], P[y]), tri[i][0]) &&                   equals(dist(P[x], P[z]), tri[i][1]) &&                   equals(dist(P[y], P[z]), tri[i][2])) {                 dfs(mask2);                 found = true;               }             }         if (!found)           for ((x) = 0; (x) < (int)(N); (x)++)             for ((y) = 0; (y) < (int)(N); (y)++) {               if (equals(dist(P[x], P[y]), tri[i][0])) {                 N++;                 P[N - 1] = crossing(P[x], tri[i][1], P[y], tri[i][2])[0];                 dfs(mask2);                 P[N - 1] = crossing(P[x], tri[i][1], P[y], tri[i][2])[1];                 dfs(mask2);                 N--;               }               if (equals(dist(P[x], P[y]), tri[i][1])) {                 N++;                 P[N - 1] = crossing(P[x], tri[i][0], P[y], tri[i][2])[0];                 dfs(mask2);                 P[N - 1] = crossing(P[x], tri[i][0], P[y], tri[i][2])[1];                 dfs(mask2);                 N--;               }               if (equals(dist(P[x], P[y]), tri[i][2])) {                 N++;                 P[N - 1] = crossing(P[x], tri[i][0], P[y], tri[i][1])[0];                 dfs(mask2);                 P[N - 1] = crossing(P[x], tri[i][0], P[y], tri[i][1])[1];                 dfs(mask2);                 N--;               }             }       }   }   vector<point> crossed(point O1, double r1, point O2, double r2) {     vector<point> ans = crossing(O1, r1, O2, r2);     vector<point> ans2 = crossing(O1, r2, O2, r1);     ans.push_back(ans2[0]);     ans.push_back(ans2[1]);     return ans;   }   void init() {     int a, b, c, i, j, k, x, y, z;     for ((i) = 0; (i) < (int)(4); (i)++) {       N = 3;       P[0].x = P[0].y = P[1].y = 0.0;       P[1].x = tri[i][0];       P[2] = crossing(P[0], tri[i][1], P[1], tri[i][2])[0];       dfs(1 << i);     }     for ((a) = 0; (a) < (int)(4); (a)++)       for ((b) = 0; (b) < (int)(a); (b)++)         for ((c) = 0; (c) < (int)(b); (c)++)           for ((i) = 0; (i) < (int)(3); (i)++)             for ((j) = 0; (j) < (int)(3); (j)++)               for ((k) = 0; (k) < (int)(3); (k)++) {                 if (triineq(tri[a][i], tri[b][j], tri[c][k])) {                   N = 6;                   P[0].x = P[0].y = P[1].y = 0.0;                   P[1].x = tri[a][i];                   P[2] = crossing(P[0], tri[b][j], P[1], tri[c][k])[0];                   vector<point> three = crossed(P[0], tri[a][(i + 1) % 3], P[1],                                                 tri[a][(i + 2) % 3]);                   vector<point> four = crossed(P[0], tri[b][(j + 1) % 3], P[2],                                                tri[b][(j + 2) % 3]);                   vector<point> five = crossed(P[1], tri[c][(k + 1) % 3], P[2],                                                tri[c][(k + 2) % 3]);                   for ((x) = 0; (x) < (int)(4); (x)++)                     for ((y) = 0; (y) < (int)(4); (y)++)                       for ((z) = 0; (z) < (int)(4); (z)++) {                         P[3] = three[x];                         P[4] = four[y];                         P[5] = five[z];                         dfs((1 << a) | (1 << b) | (1 << c));                       }                 }               }   }   int main() {     int i, j, k, l;     for ((i) = 0; (i) < (int)(4); (i)++) read(i);     int ans = 9;     for ((i) = 0; (i) < (int)(3); (i)++)       for ((j) = 0; (j) < (int)(3); (j)++)         for ((k) = 0; (k) < (int)(3); (k)++)           for ((l) = 0; (l) < (int)(3); (l)++)             if (quad(tri[0][i], tri[1][j], tri[2][k], tri[3][l])) ans = 8;     for ((i) = 0; (i) < (int)((1 << 4)); (i)++) a[i] = (1 << 29);     a[0] = 0;     init();     for ((i) = 0; (i) < (int)((1 << 4)); (i)++) {       dp[i] = a[i];       for (j = 1; j < i; j++)         if ((i & j) == j) dp[i] = min(dp[i], dp[j] + a[i ^ j] - 1);     }     ans = min(ans, dp[15]);     cout << ans << endl;     return 0;   }