#include <bits/stdc++.h>
using namespace std;
long long rdtsc() {
  long long tmp;
  asm("rdtsc" : "=A"(tmp));
  return tmp;
}
inline int myrand() { return abs((rand() << 15) ^ rand()); }
inline int rnd(int x) { return myrand() % x; }
long long gcd(long long a, long long b) {
  for (; b != 0; a %= b, swap(a, b))
    ;
  return a;
}
struct Ratio {
  long long a, b;
  Ratio() {}
  Ratio(long long _x) : a(_x), b(1) { update(); }
  Ratio(long long _a, long long _b) : a(_a), b(_b) { update(); }
  void update() {
    long long d = gcd(a, b);
    a /= d, b /= d;
    if (b < 0) b = -b, a = -a;
  }
  inline Ratio operator*(const Ratio &r) const {
    long long d1 = gcd(a, r.b), d2 = gcd(b, r.a);
    return Ratio((a / d1) * (r.a / d2), (b / d2) * (r.b / d1));
  }
  inline Ratio operator/(const Ratio &r) const {
    long long d1 = gcd(a, r.a), d2 = gcd(b, r.b);
    return Ratio((a / d1) * (r.b / d2), (b / d2) * (r.a / d1));
  }
  inline Ratio operator+(const Ratio &r) const {
    long long d = gcd(b, r.b);
    return Ratio(a * (r.b / d) + (b / d) * r.a, (b / d) * r.b);
  }
  inline Ratio operator-(const Ratio &r) const {
    long long d = gcd(b, r.b);
    return Ratio(a * (r.b / d) - (b / d) * r.a, (b / d) * r.b);
  }
  inline bool operator==(const Ratio &r) const { return a == r.a && b == r.b; }
  inline bool operator!=(const Ratio &r) const { return a != r.a || b != r.b; }
  inline bool operator<(const Ratio &r) const {
    if (a != r.a) return a < r.a;
    return b < r.b;
  }
  inline double toDouble() const { return (double)a / b; }
};
struct Point {
  Ratio x, y, z;
  Point() {}
  Point(Ratio _x, Ratio _y, Ratio _z) : x(_x), y(_y), z(_z) {}
  Point operator*(const Ratio &r) const { return Point(x * r, y * r, z * r); }
  Point operator^(const Point &p) const {
    return Point(y * p.z - z * p.y, z * p.x - x * p.z, x * p.y - y * p.x);
  }
  inline bool operator==(const Point &p) const {
    return x == p.x && y == p.y && z == p.z;
  }
  inline bool operator<(const Point &p) const {
    if (x != p.x) return x < p.x;
    if (y != p.y) return y < p.y;
    if (z != p.z) return z < p.z;
    return false;
  }
};
struct Line {
  Ratio x, y;
  Ratio dx, dy;
  int read() {
    int x1, x2, y1, y2, t1, t2;
    if (scanf("%d%d%d%d%d%d", &t1, &x1, &y1, &t2, &x2, &y2) < 6) return 0;
    dx = Ratio(x2 - x1, t2 - t1);
    dy = Ratio(y2 - y1, t2 - t1);
    x = Ratio(x1, 1) - Ratio(t1, 1) * dx;
    y = Ratio(y1, 1) - Ratio(t1, 1) * dy;
    return 1;
  }
  inline void println() const {
    fprintf(stderr, "(%.3lf %.3lf)    d = (%.3lf %.3lf)\n", x.toDouble(),
            y.toDouble(), dx.toDouble(), dy.toDouble());
  }
};
bool intersect(const Line &l1, const Line &l2, Point &res) {
  if (l1.dx == l2.dx && l1.dy == l2.dy) {
    assert(l1.x != l2.x || l1.y != l2.y);
    return false;
  }
  Ratio z;
  if (l2.dx != l1.dx) {
    z = (l1.x - l2.x) / (l2.dx - l1.dx);
    if (l2.dy != l1.dy) {
      Ratio z1 = (l1.y - l2.y) / (l2.dy - l1.dy);
      if (z != z1) return false;
    } else if (l1.y != l2.y)
      return false;
  } else {
    if (l1.x != l2.x) return false;
    z = (l1.y - l2.y) / (l2.dy - l1.dy);
  }
  res = Point(l1.dx * z + l1.x, l1.dy * z + l1.y, z);
  return true;
}
const int maxn = 1000;
Line ls[maxn];
const int maxi = maxn * (maxn - 1) / 2;
Point inters[maxi];
Point current[maxn];
pair<Point, int> pairs[maxn];
bool solve() {
  int n;
  if (scanf("%d", &n) < 1) return 0;
  for (int i = 0; i < n; ++i) {
    assert(ls[i].read());
  }
  for (int i = 0; i < n; ++i)
    for (int j = i + 1; j < n; ++j)
      if (ls[i].dx == ls[j].dx && ls[i].dy == ls[j].dy && ls[i].x == ls[j].x &&
          ls[i].y == ls[j].y) {
        assert(0);
      }
  int cnti = 0;
  for (int i = 0; i < n; ++i) {
    for (int j = i + 1; j < n; ++j) {
      Point cur;
      if (intersect(ls[i], ls[j], cur)) {
        assert(cnti < maxi);
        inters[cnti++] = cur;
      }
    }
  }
  sort(inters, inters + cnti);
  int maxs = 0;
  for (int i = 0; i < cnti;) {
    int i0 = i;
    while (i < cnti && inters[i] == inters[i0]) ++i;
    maxs = max(maxs, i - i0);
  }
  maxs *= 2;
  int ans = 0;
  while (ans * (ans - 1) < maxs) ++ans;
  assert(ans * (ans - 1) == maxs);
  ans = max(ans, 1);
  for (int i = 0; i < n; ++i) {
    int cnt = 0;
    for (int j = i + 1; j < n; ++j) {
      Point cur;
      if (!intersect(ls[i], ls[j], cur)) continue;
      Point dir = Point(ls[i].dx, ls[i].dy, 1) ^ Point(ls[j].dx, ls[j].dy, 1);
      long long d = gcd(gcd(dir.x.a, dir.y.a), dir.z.a);
      dir = dir * (Ratio(1) / d);
      dir = dir * dir.x.b;
      dir = dir * dir.y.b;
      dir = dir * dir.z.b;
      if (dir.x * 1013 + dir.y * 8952 + dir.z * 12347 < 0) dir = dir * -1;
      assert(dir.x.b == 1 && dir.y.b == 1 && dir.z.b == 1);
      pairs[cnt++] = make_pair(dir, j);
    }
    sort(pairs, pairs + cnt);
    for (int j = 0; j < cnt;) {
      int j0 = j;
      while (j < cnt && pairs[j].first == pairs[j0].first) ++j;
      for (int k = j0; k < j; ++k) {
        Line &l = ls[pairs[k].second];
        current[k - j0] = Point(l.dx, l.dy, 1);
      }
      sort(current, current + j - j0);
      int cnt = unique(current, current + j - j0) - current;
      ans = max(ans, cnt + 1);
    }
  }
  printf("%d\n", ans);
  return 1;
}
int main() {
  srand(rdtsc());
  while (1) {
    if (!solve()) break;
  }
  return 0;
}
