#include <bits/stdc++.h>
using namespace std;
template <typename T>
void __read(T &a) {
  cin >> a;
}
template <typename T, typename... Args>
void __read(T &a, Args &...args) {
  cin >> a;
  __read(args...);
}
constexpr long long M7 = 1000000007ll;
constexpr long long M9 = 1000000009ll;
constexpr long long MFFT = 998244353ll;
template <class T>
void outv(T &a) {
  for (auto &x : a) cout << x << ' ';
}
static mt19937 rnd(static_cast<unsigned>(
    chrono::steady_clock::now().time_since_epoch().count()));
auto __fast_io__ = (ios_base::sync_with_stdio(false), cin.tie(nullptr));
struct point {
  __int128 x, y, z;
  point(long long x = 0, long long y = 0, long long z = 0) : x(x), y(y), z(z) {}
  point(__int128 x, __int128 y, __int128 z) : x(x), y(y), z(z) {}
  bool operator<(const point &other) const {
    if (x != other.x) {
      return x < other.x;
    }
    if (y != other.y) {
      return y < other.y;
    }
    return z < other.z;
  }
  bool operator==(const point &other) const {
    return x == other.x && y == other.y && z == other.z;
  }
};
point vectorBy(const point &a, const point &b) {
  return {b.x - a.x, b.y - a.y, b.z - a.z};
}
template <class T>
T gcd(T a, T b) {
  while (b > 0) {
    long long t = a % b;
    a = b;
    b = t;
  }
  return a;
}
point cross(const point &a, const point &b) {
  return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
}
__int128 ABS(__int128 a) { return a > 0 ? a : -a; }
struct plane {
  __int128 a, b, c, d;
  void normalize() {
    __int128 g = ABS(a);
    g = gcd(g, ABS(b));
    g = gcd(g, ABS(c));
    g = gcd(g, ABS(d));
    if (g != 0) {
      a /= g;
      b /= g;
      c /= g;
      d /= g;
      if (a != 0) {
        if (a < 0) {
          a *= -1;
          b *= -1;
          c *= -1;
          d *= -1;
        }
      } else if (b != 0) {
        if (b < 0) {
          b *= -1;
          c *= -1;
          d *= -1;
        }
      } else if (c < 0) {
        c *= -1;
        d *= -1;
      }
    }
  }
  plane(const point &in, const point &norm) {
    a = norm.x;
    b = norm.y;
    c = norm.z;
    d = -(a * in.x + b * in.y + c * in.z);
    normalize();
  }
  bool operator<(const plane &other) const {
    if (a != other.a) {
      return a < other.a;
    }
    if (b != other.b) {
      return b < other.b;
    }
    if (c != other.c) {
      return c < other.c;
    }
    return d < other.d;
  }
  bool in(const point &p) const { return a * p.x + b * p.y + c * p.z + d == 0; }
};
__int128 determ(__int128 x1, __int128 y1, __int128 z1, __int128 x2, __int128 y2,
                __int128 z2, __int128 x3, __int128 y3, __int128 z3) {
  return x1 * (y2 * z3 - z2 * y3) - y1 * (x2 * z3 - z2 * x3) +
         z1 * (x2 * y3 - y2 * x3);
}
using LPII = pair<__int128, __int128>;
void normalizeFraction(LPII &a) {
  __int128 g = gcd(a.first > 0 ? a.first : -a.first,
                   a.second > 0 ? a.second : -a.second);
  if (g != 0) {
    a.first /= g;
    a.second /= g;
  }
  if (a.first != 0) {
    if (a.first < 0) {
      a.first *= -1;
      a.second *= -1;
    }
  } else if (a.second < 0) {
    a.second *= -1;
  }
}
bool solve(const plane &a, const plane &b, const plane &c, LPII &x, LPII &y,
           LPII &z) {
  __int128 d = determ(a.a, a.b, a.c, b.a, b.b, b.c, c.a, c.b, c.c);
  if (d == 0) {
    return false;
  }
  __int128 dx = determ(a.b, a.c, a.d, b.b, b.c, b.d, c.b, c.c, c.d);
  __int128 dy = determ(a.c, a.d, a.a, b.c, b.d, b.a, c.c, c.d, c.a);
  __int128 dz = determ(a.d, a.a, a.b, b.d, b.a, b.b, c.d, c.a, c.b);
  x = {-dx, d};
  y = {dy, d};
  z = {-dz, d};
  normalizeFraction(x);
  normalizeFraction(y);
  normalizeFraction(z);
  return true;
}
int32_t main() {
  long long n;
  __read(n);
  vector<pair<point, point>> a(n);
  for (auto &p : a) {
    long long x, y, z;
    __read(x, y, z);
    p.first = {x, y, z};
    cin >> x >> y >> z;
    p.second = {x, y, z};
  }
  vector<vector<long long>> equal(n, vector<long long>(n));
  map<tuple<LPII, LPII, LPII>, vector<long long>> cnt;
  map<plane, vector<long long>> ind;
  for (long long i = 0; i < n; ++i) {
    for (long long j = i + 1; j < n; ++j) {
      auto norm = cross(vectorBy(a[i].first, a[i].second),
                        vectorBy(a[j].first, a[j].second));
      if (norm == 0) {
        norm = cross(vectorBy(a[i].first, a[i].second),
                     vectorBy(a[i].first, a[j].first));
      }
      if (norm == 0) {
        norm = cross(vectorBy(a[i].first, a[i].second),
                     vectorBy(a[i].first, a[j].second));
      }
      if (norm == 0) {
        norm = cross(vectorBy(a[i].first, a[i].second),
                     vectorBy(a[i].second, a[j].first));
      }
      assert(!(norm == point()));
      plane p(a[i].first, norm);
      if (p.in(a[i].first) && p.in(a[i].second) && p.in(a[j].first) &&
          p.in(a[j].second)) {
        ind[p].push_back(i);
        ind[p].push_back(j);
        vector<point> d{a[i].first, a[i].second, a[j].first, a[j].second};
        sort((d).begin(), (d).end());
        d.resize(unique((d).begin(), (d).end()) - d.begin());
        if (d.size() == 3) {
          d = {a[i].first, a[i].second, a[j].first, a[j].second};
          sort((d).begin(), (d).end());
          for (long long k = 0; k < 3; ++k) {
            if (d[k] == d[k + 1]) {
              tuple<LPII, LPII, LPII> key{
                  {d[k].x, 1}, {d[k].y, 1}, {d[k].z, 1}};
              normalizeFraction(get<0>(key));
              normalizeFraction(get<1>(key));
              normalizeFraction(get<2>(key));
              cnt[key].push_back(i);
              cnt[key].push_back(j);
              break;
            }
          }
        } else {
          plane p2(a[i].first, cross(vectorBy(a[i].first, a[i].second), norm));
          plane p3(a[j].first, cross(vectorBy(a[j].first, a[j].second), norm));
          LPII x, y, z;
          if (solve(p, p2, p3, x, y, z)) {
            cnt[{x, y, z}].push_back(i);
            cnt[{x, y, z}].push_back(j);
          } else {
            equal[i][j] = equal[j][i] = 1;
          }
        }
      }
    }
  }
  vector<long long> color(n);
  function<void(long long)> dfs = [&](long long v) {
    for (long long u = 0; u < n; ++u) {
      if (equal[v][u]) {
        assert(color[u] == 0 || color[u] == color[v]);
        if (color[u] == 0) {
          color[u] = color[v];
          dfs(u);
        }
      }
    }
  };
  long long c = 1;
  for (long long i = 0; i < n; ++i) {
    if (!color[i]) {
      color[i] = c;
      dfs(i);
      c++;
    }
  }
  long long ans = 1;
  for (auto &[p, v] : cnt) {
    sort((v).begin(), (v).end());
    v.resize(unique((v).begin(), (v).end()) - v.begin());
    ans = max(ans, (long long)v.size());
  }
  for (auto &[p, v] : ind) {
    vector<long long> b;
    for (auto &i : v) {
      b.push_back(color[i]);
    }
    sort((b).begin(), (b).end());
    b.resize(unique((b).begin(), (b).end()) - b.begin());
    ans = max(ans, (long long)b.size());
  }
  cout << ans;
  return 0;
}
