#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 100

enum Type{
	FROM_start,
	FROM_goal,
};


struct Point{
	Point(double arg_x,double arg_y,double arg_z){
		x = arg_x;
		y = arg_y;
		z = arg_z;
	}

	Point(){
		x = y = z = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y,z+p.z); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y,z-p.z);}
	Point operator * (double a){ return Point(a*x,a*y,a*z); }
	Point operator / (double a){ return Point(x/a,y/a,z/a); }

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS && fabs(z-p.z) < EPS;
	}
	double x,y,z;
};

typedef Point Vector;

struct Line{

	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

struct Info{
	Info(int arg_line_id,double arg_sum_dist){
		line_id = arg_line_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct Info &arg) const{
		return sum_dist > arg.sum_dist;
	}
	int line_id;
	double sum_dist;
};

int N;
Point start,goal;
Line line[NUM];
double dist[NUM][NUM],min_dist[NUM][2];

double norm(Vector a){
	return a.x*a.x+a.y*a.y+a.z*a.z;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y+a.z*b.z;
}

Point cross(Vector a,Vector b){
	return Point(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}

double calc_dist1(Line line,Point point){
    return abs(cross(line.p[1]-line.p[0],point-line.p[0]))/abs(line.p[1]-line.p[0]);
}

double calc_dist2(int a,int b){

	Vector u1 = line[a].p[1]-line[a].p[0];
	Vector u2 = line[b].p[1]-line[b].p[0];
	Vector u3 = line[b].p[0]-line[a].p[0];

	if(abs(cross(u1,u2)) < EPS){
		return calc_dist1(line[a],line[b].p[0]);
	}
	return abs(dot(cross(u1,u2),u3)/abs(cross(u1,u2)));
}

double calc_dist3(Point a,Point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}

void dijkstra(Type type){

	for(int i = 0; i < N; i++)min_dist[i][type] = DBL_MAX;

	priority_queue<Info> Q;

	Point base;

	if(type == FROM_start){
		base = start;
	}else{
		base = goal;
	}

	for(int i = 0; i < N; i++){
		min_dist[i][type] = calc_dist1(line[i],base);
		Q.push(Info(i,min_dist[i][type]));
	}

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().line_id][type]){
			Q.pop();
			continue;
		}

		for(int i = 0; i < N; i++){
			if(i == Q.top().line_id)continue;

			if(min_dist[i][type] > Q.top().sum_dist+dist[Q.top().line_id][i]){
				min_dist[i][type] = Q.top().sum_dist+dist[Q.top().line_id][i];
				Q.push(Info(i,min_dist[i][type]));
			}
		}
		Q.pop();
	}
}

void func(){

	scanf("%lf %lf %lf %lf %lf %lf",&start.x,&start.y,&start.z,&goal.x,&goal.y,&goal.z);

	for(int i = 0; i < N; i++){
		scanf("%lf %lf %lf %lf %lf %lf",&line[i].p[0].x,&line[i].p[0].y,&line[i].p[0].z,&line[i].p[1].x,&line[i].p[1].y,&line[i].p[1].z);
	}

	double tmp_dist;

	//2直線間の距離を計算
	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			tmp_dist = calc_dist2(i,k);
			dist[i][k] = tmp_dist;
			dist[k][i] = tmp_dist;
		}
	}

	dijkstra(FROM_start);
	dijkstra(FROM_goal);

	double ans = calc_dist3(start,goal); //直接の距離

	for(int i = 0; i < N; i++){
		ans = min(ans,min_dist[i][FROM_start]+min_dist[i][FROM_goal]);
	}

	printf("%.10lf\n",ans);
}

int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}



Measured memory_bytes: 3244