#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 = 0; i < c; ++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 (;cIt != ceIt; ++cIt, ++lap) {
					for (std::vector<int>::iterator op = cIt; !curVec.empty(); op = curVec.begin()) {
						std::vector<int>::iterator vIt = curVec.begin(), veIt = curVec.end();
						std::vector<int>::iterator sIt = iList.at(*op).begin(), seIt = iList.at(*op).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;
}