#include <iostream>
#include <string>
#include <vector>
#include <sstream>

typedef struct {double x, y;} POINT;

bool isOverlaped(POINT& a, POINT& b)
{
	const double pd = 4.0;
	double dx = a.x - b.x, dy = a.y - b.y;
	
	return (dx*dx + dy*dy <= pd);
}

POINT inputPoint()
{
	POINT p;
	
	std::string str;
	std::cin >> str;
	std::string::size_type comma = str.find(",");
	
	std::stringstream ss;
	ss << str.substr(0, comma);
	ss >> p.x;
	ss.clear();
	ss << str.substr(comma + 1);
	ss >> p.y;
	
	return p;
}

int main()
{
	int n;
	const int N = 100;
	POINT points[N];
	
	while (std::cin >> n, n) {
		std::vector< std::vector<int> > iList(n);
		
		unsigned laps = 1;
		
		for (int c = 0; c < n; ++c) {
			points[c] = inputPoint();
			std::vector<int> curList;
			
			for (int i = c - 1; i >= 0; --i) {
				if (isOverlaped(points[i], points[c])) {
					curList.push_back(i);
					
					// 更新可能性アリ
					if (curList.size() >= laps) {
						std::vector<int> curVec(curList.size());
						std::copy(curList.begin(), curList.end(), curVec.begin());
						
						unsigned lap = 1;
						std::vector<int>::iterator cIt = curList.begin(), ceIt = curList.end();
						for (; !curVec.empty() && cIt != ceIt; ++cIt, ++lap) {
							std::vector<int>::iterator vIt = curVec.begin(), veIt = curVec.end();
							std::vector<int>::iterator sIt = iList.at(*cIt).begin(), seIt = iList.at(*cIt).end();
							while (vIt != veIt && sIt != seIt) {
								if (*vIt == *sIt) {
									++vIt; ++sIt;
								} else if (*vIt < *sIt) {
									++sIt;
								} else {
									vIt = curVec.erase(vIt);
									veIt = curVec.end();
								}
							}
							if (vIt != veIt) curVec.erase(vIt, veIt);
						}
						if (lap > laps) laps = lap;
					}
				}
			}
			
			iList.at(c) = curList;
		}
		
		std::cout << laps << std::endl;
	}
	
	return 0;
}