#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<complex>
#include<iomanip>
#include<cstdio>
#include<cassert>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-10)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;
typedef pair<double,double> BB;

class Point
{
  public:
  double x,y;

  Point(double x = -1,double y = -1): 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 a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}//※イケメンに限る

  bool operator < (const Point& p) const
  {
    return x != p.x?x<p.x:y<p.y;
  }

  bool operator == (const Point& p)const
  {
    return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
  }
};

struct Segment
{
  Point p1,p2;
  Segment(Point p1 = Point(-1,-1),Point p2 = Point(-1,-1)):p1(p1),p2(p2){}
};
typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

struct Circle
{
  Point p;
  double r;
  Circle(Point p=Point(0,0),double r=0):p(p),r(r){}
  bool operator < (const Circle &a)const
  {
    if(p.x != a.p.x)return p.x < a.p.x;
    if(p.y != a.p.y)return p.y < a.p.y;
    return r < a.r;
  }
};


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

double norm(Point a)
{
  return a.x*a.x+a.y*a.y;
}

int ccw(Point p0,Point p1,Point p2)
{
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > 0)return COUNTER_CLOCKWISE;
  if(cross(a,b) < 0)return CLOCKWISE;
  if(dot(a,b) < 0)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool isIntersectCC(Circle a,Circle b)
{
  double d = sqrt(norm(a.p-b.p));
  double r1 = max(a.r,b.r);
  double r2 = min(a.r,b.r);
 
  if(d > r1+r2)return false;
  if(d < r1-r2)return false; 
  return true;
}

pair<Point,Point> getPointsCC(Circle a,Circle b)
{
  //assert(isIntersectCC(a,b));
  complex<double> c1,c2;
  c1 = complex<double>(a.p.x,a.p.y);
  c2 = complex<double>(b.p.x,b.p.y);
  double r1 = a.r;
  double r2 = b.r;

  /*
  complex<double> nf[2];
  nf[0] = complex<double>(a.p.x,a.p.y);
  nf[1] = complex<double>(b.p.x,b.p.y);
  double MD = sqrt(1-0.25*norm(nf[1]-nf[0]));
  complex<double> mid = (nf[0]+nf[1])*0.5;
  complex<double> p1 = mid + (nf[0]-nf[1])/abs(nf[0]-nf[1])*polar(MD,M_PI/2);
  complex<double> p2 = mid + (nf[0]-nf[1])/abs(nf[0]-nf[1])*polar(MD,-M_PI/2);

  return pair<Point,Point>(Point(p1.real(),p1.imag()),Point(p2.real(),p2.imag()));
  */

  complex<double> A = conj(c2-c1),B = (r2*r2-r1*r1-(c2-c1)*conj(c2-c1)), C = r1*r1*(c2-c1);
  complex<double> D = B*B-4.0*A*C;
  complex<double> z1 = (-B+sqrt(D))/(2.0*A)+c1, z2 = (-B-sqrt(D))/(2.0*A)+c1;
  Point R1,R2;
  R1 = Point(z1.real(),z1.imag());
  R2 = Point(z2.real(),z2.imag());
  return pair<Point,Point>(R1,R2);
}

int main()
{
  int n;
  while(cin >> n,n)
    {
      vector<Circle> c(n);
      rep(i,n)
	{
	  scanf("%lf,%lf",&c[i].p.x,&c[i].p.y);
	  c[i].r = 1.0;
	}

      int ans = 1;
      rep(i,n)
	{
	  REP(j,i+1,n)
	    {
	      if(!isIntersectCC(c[i],c[j]))continue;
	      pair<Point,Point> pp = getPointsCC(c[i],c[j]);
	      int cnt = 0;
	      Point p1 = pp.first;
	      Point p2 = pp.second;
	      rep(k,n)if(sqrt(norm(p1-c[k].p)) < EPS+1.0)cnt++;
	      ans = (ans<cnt?cnt:ans);
		     cnt = 0;
	      rep(k,n)if(sqrt(norm(p2-c[k].p)) < EPS+1.0)cnt++;
	      ans = (ans<cnt?cnt:ans);

	    }
	}
		cout <<ans << endl;
    }
  return 0;
}

Measured memory_bytes: 1300