#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);

typedef complex<double> P;
namespace std{
	bool operator < (const P& a, const P& b){
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}
}
double cross(const P& a, const P& b){
	return imag(conj(a)*b);
}
double dot(const P& a, const P& b){
	return real(conj(a)*b);
}

struct C{
	P p; double r;
	C(){}
	C(const P &p, double r) : p(p), r(r){}
};

double dist(double x1, double y1, double z1, double x2, double y2, double z2){
	x1 -= x2;
	y1 -= y2;
	z1 -= z2;
	return sqrt(x1 * x1 + y1 * y1 + z1 * z1);
}

struct sphere{
	double x, y, z, r;
	sphere(){}
	sphere(double x, double y, double z, double r) :x(x), y(y), z(z), r(r){}
};

int intersectCC(const C &c1, const C &c2){
	double d = std::abs(c1.p - c2.p), r1 = c1.r, r2 = c2.r;
	if(r1 + r2 < d) return 0;                   // ??¢????????????
	if(std::abs(r1 + r2 - d) < EPS) return -2;  // ?????\
	if(std::abs(d + r1 - r2) < EPS) return +1;  // c1 ??? c2 ????????§?????\
	if(std::abs(d + r2 - r1) < EPS) return -1;  // c2 ??? c1 ????????§?????\
	if(d + r1 < r2) return +3;                  // c1 ??? c2 ??????
	if(d + r2 < r1) return -3;                  // c2 ??? c1 ??????
	return 2;                                    // 2?????????????????????
}

bool contain(sphere s1, sphere s2){
	double d = dist(s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
	double r1 = s1.r, r2 = s2.r;
	return d + r2 < r1;
}

C cut(sphere s, double z){
	if(s.z - s.r > z) return C({ 0, 0 }, -1);
	if(s.z + s.r < z) return C({ 0, 0 }, -1);
	double r = sqrt(s.r * s.r - (z - s.z) * (z - s.z));
	if(r < EPS) return C({ 0, 0 }, -1);
	return C({ s.x, s.y }, r);
}

int n;
typedef pair<double, double> Pdd;
typedef pair<double, int> Pdi;

Pdd f(sphere s1, sphere s2){
	double d = dist(s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
	if(d > s1.r + s2.r){
		return { INF, INF };
	}

	double vx = s2.x - s1.x;
	double vy = s2.y - s1.y;
	double vz = s2.z - s1.z;
	vx *= s1.r / d;
	vy *= s1.r / d;
	vz *= s1.r / d;
	double cz = s1.z + vz;
	assert(dist(s1.x + vx, s1.y + vy, s1.z + vz, s2.x, s2.y, s2.z) < s2.r + EPS);
	double ng = -1e9, ok = cz;
	for(int loop = 0; loop < 100; loop++){
		double mid = (ng + ok) / 2.0;
		C c1 = cut(s1, mid);
		C c2 = cut(s2, mid);
		if(c1.r > 0 && c2.r > 0 && intersectCC(c1, c2) != 0) ok = mid;
		else ng = mid;
	}
	double lz = ok;

	ok = cz, ng = 1e9;
	for(int loop = 0; loop < 100; loop++){
		double mid = (ng + ok) / 2.0;
		C c1 = cut(s1, mid);
		C c2 = cut(s2, mid);
		if(c1.r > 0 && c2.r > 0 && intersectCC(c1, c2) != 0) ok = mid;
		else ng = mid;
	}
	double rz = ok;

	return { lz, rz };
}

struct UnionFind{
	vector<int> par;
	int cnt;
	UnionFind(int size_) : par(size_, -1), cnt(size_){}
	void unite(int x, int y){
		if((x = find(x)) != (y = find(y))){
			if(par[y] < par[x]) swap(x, y);
			par[x] += par[y]; par[y] = x; cnt--;
		}
	}
	bool same(int x, int y){ return find(x) == find(y); }
	int find(int x){ return par[x] < 0 ? x : par[x] = find(par[x]); }
	int size(int x){ return -par[find(x)]; }
	int size(){ return cnt; }
};

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
#ifdef LOCAL
	std::ifstream in("in");
	std::cin.rdbuf(in.rdbuf());
#endif

	while(cin >> n, n){
		vector<sphere> s(n);
		for(int i = 0; i < n; i++){
			double  x, y, z, r;
			cin >> x >> y >> z >> r;
			s[i] = sphere(x, y, z, r);
		}
		int NG[100] = { 0 };
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				if(i == j) continue;
				if(contain(s[i], s[j])){
					NG[j] = 1;
				}
			}
		}
		vector<sphere> tmp;
		for(int i = 0; i < n; i++){
			if(!NG[i]) tmp.push_back(s[i]);
		}
		s = tmp;
		n = tmp.size();

		vector<Pdd> seg;
		vector<pair<int, int>> edge;
		for(int i = 0; i < n; i++){
			for(int j = i + 1; j < n; j++){
				Pdd res = f(s[i], s[j]);
				if(res.first == INF) continue;
				seg.push_back(res);
				edge.push_back({ i, j });
			}
		}

		vector<Pdi> p;
		for(int i = 0; i < n; i++){
			p.push_back({ s[i].z - s[i].r, i });
			p.push_back({ s[i].z + s[i].r, i });
		}
		for(int i = 0; i < seg.size(); i++){
			p.push_back({ seg[i].first, i + n });
			p.push_back({ seg[i].second, i + n });
		}
		sort(p.begin(), p.end());

		string ans;
		vector<int> inseg(seg.size());
		vector<int> insphere(n);
		int prenum = 0;
		for(int i = 0; i < p.size();){
			double z = p[i].first;
			while(i < p.size() && abs(p[i].first - z) < 0.0001){
				int idx = p[i].second;
				// sphere
				if(idx < n){
					if(insphere[idx]){
						insphere[idx] = 0;
					}
					else{
						insphere[idx] = 1;
					}
				}
				// seg
				else{
					idx -= n;
					if(inseg[idx]){
						inseg[idx] = 0;
					}
					else{
						inseg[idx] = 1;
					}
				}
				i++;
			}

			UnionFind uf(n);
			for(int i = 0; i < seg.size(); i++){
				if(inseg[i]) uf.unite(edge[i].first, edge[i].second);
			}
			int num = 0;
			for(int i = 0; i < n; i++){
				if(insphere[i] && uf.find(i) == i) num++;
			}

			if(prenum < num) ans += "1";
			if(prenum > num) ans += "0";
			prenum = num;
		}
		cout << ans.size() << endl;
		cout << ans << endl;
	}
}

Measured memory_bytes: 3112