#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;

const int MaxN = 105;
const double eps = 1e-8;
const double pi = acos(-1.0);

int dcmp(double x) {
	return x < -eps ? -1 : x > eps;
}
struct Point {
	double x, y, z;
	Point(){}
	Point(double x, double y, double z) : x(x), y(y), z(z) {}
	Point operator + (const Point &b) { return Point(x + b.x, y + b.y, z + b.z); }
	Point operator - (const Point &b) { return Point(x - b.x, y - b.y, z - b.z); }
	Point operator * (const Point &b) { return Point(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); }
	Point operator * (const double &b) { return Point(x * b, y * b, z * b); }
	Point rot(double ux, double uy, double uz, double d) {
		double cosd = cos(d);
		double sind = sin(d);
		double rx = x * (cosd + ux * ux * (1 - cosd)) + y * (ux * uy * (1-cosd) - uz * sind) + z * (ux * uz * (1 - cosd) + uy * sind);
		double ry = x * (uy * ux * (1 - cosd) + uz * sind) + y * (cosd + uy * uy * (1 - cosd)) + z * (uy * uz * (1 - cosd) - ux * sind);
		double rz = x * (uz * ux * (1 - cosd) - uy * sind) + y * (uz * uy * (1 - cosd) + ux * sind) + z * (cosd + uz * uz * (1-cosd));
		return Point(rx, ry, rz);
	}
	double operator % (const Point &b) { return x * b.x + y * b.y + z * b.z; }
	double len2() { return x * x + y * y + z * z; }
	double len() { return sqrt(x * x + y * y + z * z); }
	void init() {
		scanf("%lf%lf%lf", &x,&y,&z);
	}
} cc[MaxN];
double r[MaxN];
double get(Point c, double r, Point p1, Point p2) {
	if ((p2 - p1) % (c - p1) < -eps) return -1.;
	Point v = (p2 - p1); v = v * (1 / v.len());
	double x = (c - p1) % v;
	v = p1 + v * x;
	double d = (v - c).len2();
	if (dcmp(d - r * r) >= 0) return -1.;
	d = (p1 - v).len() - sqrt(r * r - d);
	return d;
}
void change(Point &o, Point &v, Point c, double r, double d) {
	double len = (v - o).len();
	v = o + (v - o) * (d / len);
	Point fvect = (v - c) * (o - v);
	fvect = fvect * (1. / fvect.len());
	double theta = acos((v - c) % (o - v) * (1. / ((c - v).len() * (v - o).len())));
	Point next = (o - v).rot(fvect.x, fvect.y, fvect.z, - 2. * theta);
	o = v;
	v = v + next;
}
int main() {
	//sfreopen("in","r",stdin);
	int n;
	while (scanf("%d",&n), n) {
		Point v; v.init();
		Point o = Point(0, 0, 0);
		for (int i = 0; i < n; ++i) {
			cc[i].init();
			scanf("%lf", r + i);
		}
		while (1) {
			int find = -1;
			double best = 1e10;
			for (int i = 0; i < n; ++i) {
				double d = get(cc[i], r[i], o, v);
				if (d >= 0 && (find == -1 || dcmp(d - best) < 0)) {
					best = d;
					find = i;
				}
			}
			if (find == -1) break;
			change(o, v, cc[find], r[find], best);
		}
		printf("%.10f %.10f %.10f\n", o.x, o.y, o.z);
	}
	return 0;
}