#include <iostream>
#include <complex>
#include <sstream>
#include <string>
#include <algorithm>
#include <deque>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <vector>
#include <set>
#include <limits>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
#define REP(i, j) for(int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for(int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
#define EQ(a,b) (abs((a)-(b)) < EPS)
typedef complex<double> P;
const double EPS = 1e-12;

class C {
  public:
  P p; double r;
  C(){}
  C(const P _p, double _r) { p = _p; r = _r; }
};

vector<P> crosspointCC(const C &c1, const C &c2){
  vector<P> res;
  double d = abs(c1.p - c2.p);
  double rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
  double dfr = c1.r * c1.r - rc * rc;
  if(EQ(dfr, 0.0)) dfr = 0.0;
  else if(dfr < 0.0) return res;
  double rs = sqrt(dfr);

  P diff = (c2.p - c1.p) / d;
  res.push_back(c1.p + diff * P(rc, rs));
  res.push_back(c1.p + diff * P(rc, -rs));
  return res;
}

int main() {
  int N;
  while(cin >>N && N){
    vector<C> cs(N);
    REP(i, N){
      double x, y;
      scanf("%lf,%lf", &x, &y);
      cs[i] = C(P(x, y), 1.0);
    }
    int ans = 0;
    REP(i, N){
      FOR(j, i + 1, N){
        vector<P> ps = crosspointCC(cs[i], cs[j]);
        ps.push_back(cs[i].p);
        REP(k, ps.size()){
          int cnt = 0;
          REP(l, N) if(abs(ps[k] - cs[l].p) < 1.0 + EPS) ++cnt;
          ans = max(ans, cnt);
        }
      }
    }
    cout <<ans <<endl;
  }
  return 0;
}