#include <bits/stdc++.h>
using namespace std;
namespace geometry {
static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;
bool cmp(const complex<double>& a, const complex<double>& b) {
  if (a.real() != b.real()) return a.real() < b.real();
  return a.imag() < b.imag();
}
void debug(complex<double> p) { printf("x: %f, y: %f\n", p.real(), p.imag()); }
void debug(pair<complex<double>, double> c) {
  printf("x: %f, y: %f, r: %f\n", c.first.real(), c.first.imag(), c.second);
}
void debug(pair<complex<double>, complex<double> > s) {
  printf("{\n");
  printf("    ");
  debug(s.first);
  printf("    ");
  debug(s.second);
  printf("}\n");
}
void debug(vector<complex<double> > poly) {
  printf("{\n");
  for (int i = 0; i < poly.size(); i++) {
    printf("    ");
    debug(poly[i]);
  }
  printf("}\n");
}
double norm(complex<double> a) {
  return a.real() * a.real() + a.imag() * a.imag();
}
double dot(complex<double> a, complex<double> b) {
  return a.real() * b.real() + a.imag() * b.imag();
}
double cross(complex<double> a, complex<double> b) {
  return a.real() * b.imag() - a.imag() * b.real();
}
bool isOrthogonal(complex<double> a1, complex<double> a2, complex<double> b1,
                  complex<double> b2) {
  return (abs((dot(a1 - a2, b1 - b2)) - (0.0)) < (1e-10));
}
bool isOrthogonal(pair<complex<double>, complex<double> > a,
                  pair<complex<double>, complex<double> > b) {
  return isOrthogonal(a.first, a.second, b.first, b.second);
}
bool isParallel(complex<double> a1, complex<double> a2, complex<double> b1,
                complex<double> b2) {
  return (abs((cross(a1 - a2, b1 - b2)) - (0.0)) < (1e-10));
}
bool isParallel(pair<complex<double>, complex<double> > a,
                pair<complex<double>, complex<double> > b) {
  return isParallel(a.first, a.second, b.first, b.second);
}
bool isPointOnLine(complex<double> a, complex<double> b, complex<double> c) {
  return (abs((cross(b - a, c - a)) - (0.0)) < (1e-10));
}
bool isPointOnLine(pair<complex<double>, complex<double> > a,
                   complex<double> b) {
  return isPointOnLine(a.first, a.second, b);
}
bool isPointOnSegment(complex<double> a, complex<double> b, complex<double> c) {
  return (abs((cross(b - a, c - a)) - (0.0)) < (1e-10)) &&
         (dot(b - a, c - a) > -(1e-10)) && (dot(a - b, c - b) > -(1e-10));
}
bool isPointOnSegment(pair<complex<double>, complex<double> > a,
                      complex<double> b) {
  return isPointOnLine(a.first, a.second, b);
}
int ccw(complex<double> p0, complex<double> p1, complex<double> p2) {
  complex<double> a = p1 - p0;
  complex<double> b = p2 - p0;
  if (cross(a, b) > (1e-10)) return COUNTER_CLOCKWISE;
  if (cross(a, b) < -(1e-10)) return CLOCKWISE;
  if (dot(a, b) < -(1e-10)) return ONLINE_BACK;
  if (norm(a) < norm(b)) return ONLINE_FRONT;
  return ON_SEGMENT;
}
bool intersect(complex<double> p1, complex<double> p2, complex<double> p3,
               complex<double> p4) {
  return ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
         ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0;
}
bool intersect(pair<complex<double>, complex<double> > s1,
               pair<complex<double>, complex<double> > s2) {
  return intersect(s1.first, s1.second, s2.first, s2.second);
}
double distanceLP(complex<double> a, complex<double> b, complex<double> c) {
  return abs(cross(b - a, c - a)) / abs(b - a);
}
double distanceLP(pair<complex<double>, complex<double> > a,
                  complex<double> b) {
  return distanceLP(a.first, a.second, b);
}
double distanceSP(complex<double> a, complex<double> b, complex<double> c) {
  if (dot(b - a, c - a) < (1e-10)) return abs(c - a);
  if (dot(a - b, c - b) < (1e-10)) return abs(c - b);
  return abs(cross(b - a, c - a)) / abs(b - a);
}
double distanceSP(pair<complex<double>, complex<double> > a,
                  complex<double> b) {
  return distanceSP(a.first, a.second, b);
}
double distanceCS(pair<complex<double>, double> c,
                  pair<complex<double>, complex<double> > s) {
  return distanceSP(s, c.first) - c.second;
}
bool intersectCL(pair<complex<double>, double> c,
                 pair<complex<double>, complex<double> > l) {
  return c.second - distanceLP(l, c.first) > -(1e-10);
}
bool intersectCS(pair<complex<double>, double> c,
                 pair<complex<double>, complex<double> > s) {
  if ((abs((c.second - abs(c.first - s.first)) - (0.0)) < (1e-10)) ||
      (abs((c.second - abs(c.first - s.second)) - (0.0)) < (1e-10)))
    return true;
  if (c.second - distanceSP(s, c.first) > -(1e-10)) {
    return (c.second - abs(c.first - s.first) < (1e-10) ||
            c.second - abs(c.first - s.second) < (1e-10));
  }
  return false;
}
complex<double> project(pair<complex<double>, complex<double> > s,
                        complex<double> p) {
  complex<double> base = s.second - s.first;
  double r = dot(p - s.first, base) / norm(base);
  return s.first + base * r;
}
complex<double> reflect(pair<complex<double>, complex<double> > s,
                        complex<double> p) {
  return p + (project(s, p) - p) * (double)2.0;
}
complex<double> crossPoint(pair<complex<double>, complex<double> > s1,
                           pair<complex<double>, complex<double> > s2) {
  complex<double> base = s2.second - s2.first;
  double d1 = abs(cross(base, s1.first - s2.first));
  double d2 = abs(cross(base, s1.second - s2.first));
  double t = d1 / (d1 + d2);
  return s1.first + (s1.second - s1.first) * t;
}
double area(vector<complex<double> > poly) {
  if (poly.size() < 3) return 0.0;
  double res = 0.0;
  for (int i = 1; i < poly.size() - 1; i++) {
    complex<double> v1 = poly[i] - poly[0];
    complex<double> v2 = poly[i + 1] - poly[0];
    res += abs(cross(v1, v2)) / 2;
  }
  return res;
}
vector<complex<double> > convexHull(vector<complex<double> > s) {
  if (s.size() < 3) return s;
  vector<complex<double> > u, l;
  sort(s.begin(), s.end(), cmp);
  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size() - 1]);
  l.push_back(s[s.size() - 2]);
  for (int i = 2; i < s.size(); i++) {
    for (int n = u.size(); n >= 2 && ccw(u[n - 2], u[n - 1], s[i]) != CLOCKWISE;
         n--) {
      u.pop_back();
    }
    u.push_back(s[i]);
  }
  for (int i = s.size() - 3; i >= 0; i--) {
    for (int n = l.size(); n >= 2 && ccw(l[n - 2], l[n - 1], s[i]) != CLOCKWISE;
         n--) {
      l.pop_back();
    }
    l.push_back(s[i]);
  }
  reverse(l.begin(), l.end());
  for (int i = u.size() - 2; i >= 1; i--) {
    l.push_back(u[i]);
  }
  return l;
}
}  // namespace geometry
using namespace geometry;
int main() {
  int n;
  while (scanf("%d", &n), n) {
    vector<vector<bool> > f(n, vector<bool>(n));
    vector<int> cnt(n);
    vector<complex<double> > pv;
    for (int i = 0; i < n; i++) {
      double x, y;
      scanf("%lf,%lf", &x, &y);
      pv.push_back(complex<double>(x, y));
    }
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (abs(pv[i] - pv[j]) < 2.0 + (1e-10)) {
          f[i][j] = true;
          cnt[i]++;
        }
      }
    }
    int res = 0;
    for (int i = 0; i < n; i++) {
      vector<bool> ff = f[i];
      for (int j = 0; j < n; j++) {
        if (!f[i][j]) continue;
        for (int k = 0; k < n; k++) {
          if (!(ff[k] && f[j][k])) {
            ff[k] = false;
          }
        }
      }
      int cnt = 0;
      for (int i = 0; i < n; i++) {
        cnt += (ff[i] == true);
      }
      res = max(res, cnt);
    }
    printf("%d\n", res);
  }
  return 0;
}
