#include<iostream>
#include<vector>
#include<array>
#include<cmath>

using namespace std;

typedef array<double,3> P3;

P3 operator-(P3 p){
  return P3{-p[0],-p[1],-p[2]};
}

P3 operator+(P3 a,P3 b){
  return P3{a[0]+b[0],a[1]+b[1],a[2]+b[2]};
}

P3 operator-(P3 a,P3 b){
  return a+-b;
}

P3 operator-=(P3 &a,P3 b){
  return a=a-b;
}
  
P3 operator*(P3 p,double d){
  return P3{p[0]*d,p[1]*d,p[2]*d};
}
  
P3 operator/(P3 p,double d){
  return p*(1/d);
}

double dot(P3 a,P3 b){
  return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
}

double abs(P3 p){
  return sqrt(dot(p,p));
}

P3 cross(P3 a,P3 b){
  return P3{a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]};
}
  
P3 Rodrigues(P3 r,P3 base,double phy){
  P3 n=base/abs(base);
  P3 nnr=n*dot(n,r);
  return nnr+(r-nnr)*cos(phy)+cross(n,r)*sin(phy);
}

P3 closest_to_origin(P3 a,P3 b){
  P3 x=a-b;
  return b+x*-dot(b,x)/dot(x,x);
}

vector<P3> intersection(P3 p,double r,P3 a,P3 b){
  a-=p;
  b-=p;
  P3 cp=closest_to_origin(a,b);
  double d=abs(cp);
  if(d>r){
    return {};
  }else{
    P3 x=a-b;
    double f=sqrt(r*r-d*d)/abs(x);
    return {cp+x*f+p,cp+x*-f+p};
  }
}


int main(){
  for(int N;cin>>N,N;){
    double u,v,w;
    cin>>u>>v>>w;
    P3 p[100];
    int r[100];
    for(int i=0;i<N;i++){
      double x,y,z;
      cin>>x>>y>>z>>r[i];
      p[i]=P3{x,y,z};
    }
    P3 f{0,0,0},t{u,v,w};
    for(;;){
      double d=1e99;
      P3 nf,nt;
      for(int i=0;i<N;i++){
	if(dot(t-f,p[i]-f)>0){
	  auto res=intersection(p[i],r[i],t,f);
	  for(auto e:res){
	    if(abs(e-f)<d){
	      d=abs(e-f);
	      nf=e;
	      nt=Rodrigues(f-nf,nf-p[i],2*acos(0))+nf;
	    }
	  }
	}
      }
      if(d>1e98)break;
      f=nf;
      t=nt;
    }
    for(int i=0;i<3;i++){
      cout.precision(9);
      cout<<fixed<<f[i]<<" \n"[i==2];
    }
  }
}
 