#include <cstdio>
#include <cmath>
#include <vector>

// double
struct P{
    P(){}
    P(double _r, double _i):r(_r), i(_i){}
    void real(const double& v){r = v;}
    void imag(const double& v){i = v;}
    double r, i;
};

double real(const P& p){return p.r;}
double imag(const P& p){return p.i;}
double norm(const P& p){double r = real(p), i = imag(p); return r * r + i * i;}
double dist(const P& p){return std::sqrt(norm(p));}

P operator+(const P& lhs, const P& rhs){
    return P(real(lhs)+real(rhs), imag(lhs)+imag(rhs));
}
P operator-(const P& lhs, const P& rhs){
    return P(real(lhs)-real(rhs), imag(lhs)-imag(rhs));
}
P operator-(const P& p){
    return P(-real(p), -imag(p));
}

double cross(const P& lhs, const P& rhs){
    return real(lhs)*imag(rhs) - imag(lhs)*real(rhs);
}

double dot(const P& lhs, const P& rhs){
    return real(lhs)*real(rhs) + imag(lhs)*imag(rhs);
}

const double EPS = 1e-9, D_THETA = 0.06, D_R = 0.06;

int N;
P ps[100];
std::vector<P> is;

void addIntersection(int i, int j){
    if(dist(ps[i]-ps[j]) > 2.0){return;}
    
    P m{(real(ps[j])-real(ps[i])) / 2, (imag(ps[j])-imag(ps[i])) / 2}, n{-imag(m), real(m)};
    {
        double d = dist(n);
        n.real(real(n) / d);
        n.imag(imag(n) / d);
    }

    for(int k=-1;k<=1;k+=2){
        P p{0.5 * k * dist(m) * real(n), 0.5 * k * dist(m) * imag(n)};
        // P q = ps[i] + m + p;
        //printf("%.6f, %.6f\n", real(q), imag(q));
        is.push_back(ps[i] + m + p);
    }
}

int count(P p){
    int res = 0;
    for(int i=0;i<N;i++){
        if(dist(ps[i]-p) < 1.0 + EPS){res++;}
    }
    return res;
}

int main(){
    scanf("%d", &N);

    for(int i=0;i<N;i++){
        double x, y;
        scanf("%lf,%lf", &x, &y);

        ps[i].real(x);
        ps[i].imag(y);
    }

    for(int i=0;i<N;i++){
        for(int j=i+1;j<N;j++){
            addIntersection(i, j);
        }
    }
    
    int res = 0;
    for(auto i : is){
        res = std::max(res, count(i));
    }

    printf("%d\n", res);
}