#include <bits/stdc++.h>
using namespace std;
template <class T>
bool operator<(const complex<T> &a, const complex<T> &b) {
  return a.real() == b.real() ? a.imag() < b.imag() : a.real() < b.real();
}
double dot(complex<double> a, complex<double> b) {
  return (a * conj(b)).real();
}
double cross(complex<double> a, complex<double> b) {
  return (a * conj(b)).imag();
}
vector<complex<double> > points;
deque<complex<double> > selected;
int max_count;
void search(int index, complex<double> pre_select) {
  if (index > points.size()) return;
  int selected_size = selected.size();
  bool is_all_overlap = true;
  if (selected_size >= 2 && selected_size > max_count) {
    vector<complex<double> > copied_selected;
    copy(selected.begin(), selected.end(), back_inserter(copied_selected));
    for (int i = 0; i < selected_size; ++i) {
      for (int j = 0; j < selected_size; ++j) {
        if (i == j) continue;
        if (abs(copied_selected[i] - copied_selected[j]) > 2.0 + 1e-10) {
          is_all_overlap = false;
          break;
        }
      }
      if (!is_all_overlap) {
        break;
      }
    }
    copied_selected.clear();
    copied_selected.shrink_to_fit();
  }
  if (is_all_overlap) {
    if (selected_size > max_count) {
      max_count = selected_size;
    }
    complex<double> p = points[index];
    if (pre_select == complex<double>(-1, -1) ||
        abs(pre_select - p) <= 2.0 + 1e-10) {
      selected.push_front(p);
      search(index + 1, p);
      selected.pop_front();
    }
    search(index + 1, pre_select);
  }
}
int main() {
  int n;
  while (cin >> n) {
    if (n == 0) break;
    points.clear();
    points.shrink_to_fit();
    selected.clear();
    selected.shrink_to_fit();
    max_count = 0;
    for (char i = 0; i < n; ++i) {
      double x;
      double y;
      scanf("%lf,%lf", &x, &y);
      complex<double> p = complex<double>(x, y);
      points.push_back(p);
    }
    search(0, complex<double>(-1, -1));
    cout << max_count << endl;
  }
  return 0;
}
