#include <bits/stdc++.h>
using namespace std;
#define int long long   // <-----!!!!!!!!!!!!!!!!!!!

#define rep(i,n) for (int i=0;i<(n);++i)
#define rep2(i,a,b) for (int i=(a);i<(b);++i)
#define rrep(i,n) for (int i=(n)-1;i>=0;--i)
#define rrep2(i,a,b) for (int i=(a)-1;i>=b;--i)
#define chmin(a,b) (a)=min((a),(b));
#define chmax(a,b) (a)=max((a),(b));
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define printV(v) cout<<(#v)<<":";for(auto(x):(v)){cout<<" "<<(x);}cout<<endl;
#define printVS(vs) cout<<(#vs)<<":"<<endl;for(auto(s):(vs)){cout<<(s)<< endl;}
#define printVV(vv) cout<<(#vv)<<":"<<endl;for(auto(v):(vv)){for(auto(x):(v)){cout<<" "<<(x);}cout<<endl;}
#define printP(p) cout<<(#p)<<(p).first<<" "<<(p).second<<endl;
#define printVP(vp) cout<<(#vp)<<":"<<endl;for(auto(p):(vp)){cout<<(p).first<<" "<<(p).second<<endl;}

inline void output(){ cout << endl; }
template<typename First, typename... Rest>
inline void output(const First& first, const Rest&... rest) {
    cout << first << " "; output(rest...);
}

using ll = long long;
using Pii = pair<int, int>;
using TUPLE = tuple<int, int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
const int inf = 1e9;
const int mod = 1e9 + 9;
using Graph = vector<vector<int>>;

typedef complex<double> P;
typedef vector<P> G;
#define here(g, i) g[i]
#define next(g, i) g[(i + 1) % g.size()]
#define prev(g, i) g[(i - 1 + g.size()) % g.size()]
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
inline int sgn(double a, double b = 0) { return a < b - EPS ? -1 : a > b + EPS ? 1 : 0; }

struct C {
    P p;
    double r;
    C(){}
    C(P _p, double _r) : p(_p), r(_r) {}
    C(double _x, double _y, double _r) : p(_x, _y), r(_r) {}
    void print() {
        cerr << p.real() << " " << p.imag() << " " << r << endl;
    }
};

C readC() {
    double x, y, r;
    cin >> x >> y >> r;
    return C(x, y, r);
}

int relationCC(C c1, C c2) {
    double d = abs(c1.p - c2.p);
    if (sgn(d, c1.r + c2.r) == 1)       return 4; // distant
    if (sgn(d, c1.r + c2.r) == 0)       return 3; // touch outside
    if (sgn(d, abs(c1.r - c2.r)) == -1) return 0; // c1 in c2
    if (sgn(d, abs(c1.r - c2.r)) == 0)  return 1; // c1 touches in c2
    return 2; // two crosspoints
}

int n;
vvi id_by_color;
bool on[24][24];
bool visited[1 << 24];
int ans;

bool valid(int i, int state) {
    rep(k, i) {
        if ((state >> k & 1) && on[k][i]) return false;
    }
    return true;
}

void dfs(int state, int num) {
    if (visited[state]) return;
    visited[state] = true;
    chmax(ans, n - num);
    if (num <= 1) return;

    for (auto v_id : id_by_color) {
        int m = v_id.size();
        rep(i, m) {
            if (!(state >> v_id[i] & 1)) continue;
            rep2(j, i + 1, m) {
                if (!(state >> v_id[j] & 1)) continue;
                if (valid(v_id[i], state) && valid(v_id[j], state)) {
                    dfs((state & ~(1 << v_id[i])) & ~(1 << v_id[j]), num - 2);
                }
            }
        }
    }
}

main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    while (cin >> n, n) {
        vector<C> circles(n);
        id_by_color.clear(); id_by_color.resize(4);
        rep(i, n) {
            circles[i] = readC();
            int c;
            cin >> c;
            c--;
            id_by_color[c].emplace_back(i);
        }

        rep(i, n) {
            rep2(j, i + 1, n) {
                on[i][j] = (relationCC(circles[i], circles[j]) <= 2);
            }
        }

        rep(i, 1 << n) visited[i] = false;
        ans = 0;
        dfs((1 << n) - 1, n);
        cout << ans << endl;
    }
}

Measured memory_bytes: 19672