#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>
#include <deque>
#include <set>
#include <climits>
#include <complex>

#define rep_(v, f, l) for (int v = (f); v < (l); ++v)
#define rep(v, n) rep_(v, 0, n)

using namespace std;

typedef long long int lint;
typedef complex<double> P, point;
template<typename T> inline bool in(T& x){ return cin >> x; }
template<typename T> inline T in(){T x; cin >> x; return x; }

const double EPS = 1e-7;

int get_maximal_clique(const vector<vector<int> >& graph, unsigned int bgraph[128][4], int v)
{
    unsigned int b[4] = {};
    rep(i, 4) b[i] = bgraph[v][i];
    rep(i, graph[v].size()){
        rep(j, 4) b[j] &= bgraph[graph[v][i]][j];
    }
    int count = 0;
    rep(i, 4) count += __builtin_popcount(b[i]);
    return (count);
}

int main()
{
    int n;
    while (in(n), n){
        vector<P> seals;
        rep(i, n){
            double x, y;
            scanf("%lf,%lf", &x, &y);
            seals.push_back(P(x, y));
        }
        unsigned int bgraph[128][4] = {};
        vector<vector<int> > graph;
        rep(i, n){
            vector<int> edges;
            bgraph[i][i >> 5] |= 1 << (i & 31);
            rep(j, n){
                if (i == j) continue;
                if (abs(seals[i] - seals[j]) < 2.0 + EPS){
                    edges.push_back(j);
                    bgraph[i][j >> 5] |= 1 << (j & 31);
                }
            }
            graph.push_back(edges);
        }
        int maxi = 1;
        rep(i, graph.size()){
            if (maxi < graph[i].size()){
                maxi = max(maxi, get_maximal_clique(graph, bgraph, i));
            }
        }
        printf("%d\n", maxi);
    }

	return (0);
}