// Arup Guha
// 6/11,12/2014
// Solution to 2012 World Finals Problem: Asteroid Ranger

import java.util.*;

public class a {

	public static TreeSet<state> critPts;
	public static HashSet<Integer> curMST;
	public static HashSet<Integer> nextMST;

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		int loop = 1;

		while (stdin.hasNext()) {

			// Get points.
			int n = stdin.nextInt();
			pt[] points = new pt[n];
			for (int i=0; i<n; i++) {
				double[] start = new double[3];
				for (int j=0; j<3; j++) start[j] = stdin.nextDouble();
				double[] vec = new double[3];
				for (int j=0; j<3; j++) vec[j] = stdin.nextDouble();
				points[i] = new pt(start, vec);
			}

			// Create all edges and calculate all critical pts.
			ArrayList<edge> allEdges = getAllEdges(points);
			critPts = new TreeSet<state>();
			updateCritPts(allEdges, points);

			// Get initial MST.
			setDistance(allEdges, points, 0);
			ArrayList<edge> mst = getMST(allEdges, n);
			curMST = nextMST;

			// Will store our final result.
			int res = 1;

			// Go through each possible point in time with a change.
			while (critPts.size() > 0) {

				// Get next critical point and change in edges.
				state next = critPts.pollFirst();
				int e1ID = 100*next.e1.v1+next.e1.v2;
				int e2ID = 100*next.e2.v1+next.e2.v2;
				boolean status1 = curMST.contains(e1ID);
				boolean status2 = curMST.contains(e2ID);

				// No change is occurring here.
				if (status1 && status2) continue;
				if (!status1 && !status2) continue;

				// Just add the new potential edge to the MST.
				if (!status1) mst.add(next.e1);
				if (!status2) mst.add(next.e2);

				// Update just these distances and get the new MST.
				setDistance(mst, points, next.t);
				mst = getMST(mst, n);

				// If there was a change, update our counter!
				if (diff(curMST, nextMST)) {
					res++;
					curMST = nextMST;
				}
			}

			// Print final answer.
			System.out.println("Case "+loop+": "+res);
			loop++;
		}
	}

	// Returns true iff b contains each element in a.
	public static boolean diff(HashSet<Integer> a, HashSet<Integer> b) {
		for (Integer x: a)
			if (!b.contains(x))
				return true;
		return false;
	}

	// Just creates all connections. Distances to be set later.
	public static ArrayList<edge> getAllEdges(pt[] points) {
		ArrayList<edge> list = new ArrayList<edge>();
		for (int i=0; i<points.length; i++)
			for (int j=i+1; j<points.length; j++)
				list.add(new edge(i,j));
		return list;
	}

	// Updates all critical points.
	public static void updateCritPts(ArrayList<edge> allEdges, pt[] points) {

		// Must loop through all pairs of EDGES.
		for (int i=0; i<allEdges.size(); i++) {
			for (int j=i+1; j<allEdges.size(); j++) {

				// Just so it's easier to read.
				int e1v1 = allEdges.get(i).v1;
				int e1v2 = allEdges.get(i).v2;
				int e2v1 = allEdges.get(j).v1;
				int e2v2 = allEdges.get(j).v2;

				// Get expressions for the lengths of these edges in time.
				pt start = points[e1v1].diff(points[e1v2]);
				pt end = points[e2v1].diff(points[e2v2]);

				// Get all crossover points. There are never more than 2. Add to list.
				ArrayList<Double> pts = start.update(end);
				for (int k=0; k<pts.size(); k++)
					critPts.add(new state(allEdges.get(i), allEdges.get(j), pts.get(k)));
			}
		}
	}

	// Sets all of the distances in the edge list to be what the distances are at time t.
	public static void setDistance(ArrayList<edge> allEdges, pt[] points, double t) {
		for (int i=0; i<allEdges.size(); i++) {
			edge cur = allEdges.get(i);
			cur.distance = points[cur.v1].distance(points[cur.v2], t);
		}
	}

	// Return the length of the sum of the edges in the mst of the graph
	// of n vertices represented in allEdges.
	public static ArrayList<edge> getMST(ArrayList<edge> allEdges, int n) {

		// So we don't mess up our original list.
		PriorityQueue<edge> pq = new PriorityQueue<edge>();
		for (edge e: allEdges)
			pq.offer(e);

		// Set up MST.
		dset mydset = new dset(n);
		ArrayList<edge> ans = new ArrayList<edge>();
		nextMST = new HashSet<Integer>();

		int numedges = 0;

		// Keep on going until we get the right number of edges.
		while (numedges < n-1) {

			// Next edge to try.
			edge next = pq.poll();

			// We add this edge.
			if (mydset.union(next.v1, next.v2)) {
				ans.add(next);
				nextMST.add(next.hash);
				numedges++;
			}
		}

		return ans;
	}
}

class pt {

	public double[] p;
	public double[] v;

	public pt(double[] myp, double[] myv) {
		p = myp;
		v = myv;
	}

	// Distance between this and other at time t.
	public double distance(pt other, double t) {
		double[] delta = new double[3];
		for (int i=0; i<3; i++)
			delta[i] = p[i] + t*v[i] - (other.p[i] + t*other.v[i]);
		double sumsq = 0;
		for (int i=0; i<3; i++) sumsq += Math.pow(delta[i], 2);
		return Math.sqrt(sumsq);
	}

	// Returns a representation of the length of the edge this to other, that can be
	// evaluated at any time t.
	public pt diff(pt other) {
		double[] newp = new double[3];
		double[] newv = new double[3];
		for(int i=0; i<3; i++) {
			newp[i] = p[i] - other.p[i];
			newv[i] = v[i] - other.v[i];
		}
		return new pt(newp, newv);
	}

	// Updates the list of critical points for times when this and other are of equal distances.
	public ArrayList<Double> update(pt other) {

		double a = 0, b = 0, c = 0;
		for (int i=0; i<3; i++) {
			a += (v[i]*v[i] - other.v[i]*other.v[i]);
			b += (2*(p[i]*v[i] - other.p[i]*other.v[i]));
			c += (p[i]*p[i] - other.p[i]*other.p[i]);
		}

		ArrayList<Double> ans = new ArrayList<Double>();

		// Linear equation case.
		if (a == 0) {

			// Really annoying...
			if (b == 0) return ans;

			// This is the only answer.
			double t1 = -c/b;
			if (t1 > 0) ans.add(t1+5e-7);
			return ans;
		}

		// Avoid sqrt(neg)...
		double disc = b*b - 4*a*c;
		if (disc < 0) return ans;

		// Solve both and add if necessary.
		double t1 = (-b+Math.sqrt(disc))/(2*a);
		double t2 = (-b-Math.sqrt(disc))/(2*a);
		if (t1 > 0) ans.add(t1+5e-7);
		if (t2 > 0) ans.add(t2+5e-7);
		return ans;
	}
}

// Manages an edge for Kruskal's.
class edge implements Comparable<edge> {

	public int v1;
	public int v2;
	public int hash;
	public double distance;

	public edge(int i, int j) {
		v1 = Math.min(i,j);
		v2 = Math.max(i,j);
		hash = 100*v1 + v2;
	}

	public int compareTo(edge other) {
		if (this.distance < other.distance-1e-9) return -1;
		else if (this.distance > other.distance+1e-9) return 1;
		return 0;
	}
}


//  Just used for the Disjoint set class.
class pair {
	public int parent;
	public int height;

	public pair(int a, int b) {
		parent = a;
		height = b;
	}
}

// Basic Disjoint Set without path compression.
class dset {

	private pair[] parents;

	public dset(int n) {
		parents = new pair[n];
		for (int i=0; i<n; i++)
			parents[i] = new pair(i,0);
	}

	public int find(int child) {
		while (parents[child].parent != child)
			child = parents[child].parent;
		return child;
	}

	public boolean union(int c1, int c2) {
		int root1 = find(c1);
		int root2 = find(c2);

		// Nothing to union.
		if (root1 == root2)
			return false;

		// Root 1 stays parent.
		if (parents[root1].height > parents[root2].height) {
			parents[root2].parent = root1;
		}

		// Tie case get assigned to root 1 also.
		else if (parents[root1].height == parents[root2].height) {
			parents[root2].parent = root1;
			parents[root1].height++;
		}

		// Must use root 2 here.
		else {
			parents[root1].parent = root2;
		}

		return true;
	}
}

class state implements Comparable<state> {

	public edge e1;
	public edge e2;
	public double t;

	public state(edge first, edge second, double mytime) {
		e1 = first;
		e2 = second;
		t = mytime;
	}

	// This is key, to differentiate states that have the same time but different pairs of edges, so that
	// our TreeSet stores the same time twice, considering each pair of edges.
	public int compareTo(state other) {
		if (this.t < other.t-1e-9) return -1;
		else if (this.t > other.t+1e-9) return 1;
		return this.e1.hash - this.e2.hash;
	}
}