#include <stdio.h>
#include <iostream>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>

using namespace std;

#define EPS (1e-10)
#define EQ(a,b) (abs((a) - (b)) < EPS)
#define EQV(a,b) (EQ((a).real(),(b).real()) && EQ((a).imag(),(b).imag()))

typedef complex<double> P;
typedef long long ll;

const int MAX_SIZE = 10000;

// àÏ
double dot(P a, P b) {
  return (a.real() * b.real() + a.imag() * b.imag());
}
// OÏ
double cross(P a, P b) {
  return (a.real() * b.imag() - a.imag() * b.real());
}
// _cª¼üabãÉ é©È¢©
int is_point_on_line(P a, P b, P c) {
  return EQ( cross(b-a, c-a), 0.0 );
}
// 2¼üÌ¼s»è
int is_orthogonal(P a1, P a2, P b1, P b2) {
  return EQ( dot(a1-a2, b1-b2), 0.0 );
}
// 2¼üÌ½s»è
int is_parallel(P a1, P a2, P b1, P b2) {
  return EQ( cross(a1-a2, b1-b2), 0.0 );
}
// _a,bðÊé¼üÆ_cÌÔÌ£
double distance_l_p(P a, P b, P c) {
  return abs(cross(b-a, c-a)) / abs(b-a);
}
// _a,bð[_Æ·éüªÆ_cÆÌ£
double distance_ls_p(P a, P b, P c) {
  if ( dot(b-a, c-a) < EPS ) return abs(c-a);
  if ( dot(a-b, c-b) < EPS ) return abs(c-b);
  return abs(cross(b-a, c-a)) / abs(b-a);
}
// a1,a2ð[_Æ·éüªÆb1,b2ð[_Æ·éüªÌð·»è
int is_intersected_ls(P a1, P a2, P b1, P b2) {
  return ( cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS ) &&
         ( cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < EPS );
}
// a1,a2ð[_Æ·éüªÆb1,b2ð[_Æ·éüªÌð_vZ
P intersection_ls(P a1, P a2, P b1, P b2) {
  P b = b2-b1;
  double d1 = abs(cross(b, a1-b1));
  double d2 = abs(cross(b, a2-b1));
  double t = d1 / (d1 + d2);

  return a1 + (a2-a1) * t;
}
// a1,a2ðÊé¼üÆb1,b2ðÊé¼üÌð·»è
int is_intersected_l(P a1, P a2, P b1, P b2) {
  return !EQ( cross(a1-a2, b1-b2), 0.0 );
}
// a1,a2ðÊé¼üÆb1,b2ðÊé¼üÌð_vZ
P intersection_l(P a1, P a2, P b1, P b2) {
  P a = a2 - a1; P b = b2 - b1;
  return a1 + a * cross(b, b1-a1) / cross(b, a);
}
/*
~üÆüªÌð·»è
*/
bool isCircleCrossLine(P a,P b,P c,double r){
	double d1 = abs(a-c);
	double d2 = abs(b-c);
	if(d1<r&&d2<r){
		return false;
	}
	double d = distance_ls_p(a,b,c);
	if(EQ(d,r)||d<r){
		return true;
	}
	else
		return false;
}
// Op`ÌàÉ_ª é©Ç¤©
// OÏÌ³ª·×Ä¯¶ÈçàÉ_ è
bool isInTriangle(P p1,P p2,P p3,P s){
	P a=p1-s;
	P b=p2-s;
	P c=p3-s;
	return ((cross(a,b)>0&&cross(b,c)>0&&cross(c,a)>0)||(cross(a,b)<0&&cross(b,c)<0&&cross(c,a)<0));
}
// Op`ÌÊÏðÀW©çvZ
double calcAreaOfTriangle(P a,P b,P c){
	return abs((b.real()-a.real())*(c.imag()-a.imag()) - (c.real()-a.real())*(b.imag()-a.imag()))/2;
}


int main(){

	int n;
	while(cin>>n&&n!=0){
		vector<P> ps;
		double x,y;
		for(int i = 0; i < n; i++){
			char ch;
			cin>>x>>ch>>y;
			ps.push_back(P(x,y));
		}
		int maxDot=1;
		for(int i = 0; i < n; i++){
			for(int j = i + 1; j < n; j++){
				// ~Æ~Ìð_ðßé
				P &p1 = ps[i];
				P &p2 = ps[j];
				// SÔÌ£
				double dist = abs(p1-p2);
				// ð_ª³¯êÎ»ÌÜÜI¹
				if(dist>2||EQ(dist,2))
					continue;

				// ñ_ðÊéPÊxNg
				P e = (p1-p2);
				e = P(-e.imag(),e.real());
				e/=abs(e);
				
				double b = sqrt(1-(abs(p1-p2)/2)*(abs(p1-p2)/2));

				vector<P> vp;
				// ñ_ðßé		
				P tp = p1+p2;
				tp/=2;
				for(int k = 0;  k < 2; k++){
					vp.push_back(e*b+tp);
					e=-e;
				}
				// »ê¼êÌ_ÉÂ¢ÄA¢­ÂÌ~ÌãÉÚÁÄ¢é©²×é
				for(int k = 0; k < vp.size(); k++){
					int cnt=2;
					if(!((vp[k].real()>0||EQ(vp[k].real(),0))
						&&(vp[k].real()<10||EQ(vp[k].real(),10))
						&&(vp[k].imag()>0||EQ(vp[k].imag(),0))
						&&(vp[k].imag()<10||EQ(vp[k].imag(),10))
						)){
						continue;
					}
					for(int l = 0; l < n; l++){
						if(l==i||l==j)
							continue;
						// àµ~ÌàÉ éÌÈçÎ
						if(((ps[l].real()-vp[k].real())*(ps[l].real()-vp[k].real())
							+(ps[l].imag()-vp[k].imag())*(ps[l].imag()-vp[k].imag())<1)
							||EQ((ps[l].real()-vp[k].real())*(ps[l].real()-vp[k].real())
							+(ps[l].imag()-vp[k].imag())*(ps[l].imag()-vp[k].imag()),1)){
								cnt++;
						}
					}
					maxDot=max(maxDot,cnt);
				}
			}
		}
		cout<<maxDot<<endl;
	}

	return 0;
}

Measured memory_bytes: 0