Problem:
Distance

For given two segments s1 and s2, print the distance between them.

s1 is formed by end points p0 and p1, and
s2 is formed by end points p2 and p3.

Input

The entire input looks like:

q (the number of queries)
1st query
2nd query
...
qth query

Each query consists of integer coordinates of end points of s1 and s2 in the following format:

xp0 yp0 xp1 yp1 xp2 yp2 xp3 yp3

Output

For each query, print the distance. The output values should be in a decimal fraction with an error less than 0.00000001.

Constraints

1 ≤ q ≤ 1000

-10000 ≤ xpi, ypi ≤ 10000

p0 ≠ p1 and
p2 ≠ p3.

Sample Input

3
0 0 1 0 0 1 1 1
0 0 1 0 2 1 1 2
-1 0 1 0 0 1 0 -1

Sample Output

1.0000000000
1.4142135624
0.0000000000

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using static System.Console;
using static System.Math;
using static MyIO;
using static MyUtil;

using static Geometory;
using Vector = Geometory.Point;
using Line = Geometory.Segment;

public class D
{
	public static void Main() => (new Solver()).Solve();
}

public class Solver
{
	public void Solve()
	{
		int Q = GetInt();
		var ans = new string[Q];
		for(int i = 0; i < Q; i++)
			ans[i] = solve();

		WriteLine(string.Join("\n", ans));
	}

	private string solve()
	{
		var p1 = new Point(GetDouble(), GetDouble());
		var p2 = new Point(GetDouble(), GetDouble());
		var p3 = new Point(GetDouble(), GetDouble());
		var p4 = new Point(GetDouble(), GetDouble());
		var s1 = new Segment(p1, p2);
		var s2 = new Segment(p3, p4);
		return $"{GetDistance(s1, s2):F12}";
	}
}

public static class Geometory
{
	private const double EPS = 1e-10;
	public static bool Equals(double a, double b) => Math.Abs(a - b) < EPS;

	public class Point
	{
		public double X;
		public double Y;		
		public Point(double x, double y)
		{
			X = x;
			Y = y;
		}
	
		public static Point operator+(Point p, Point q) => new Point(p.X + q.X, p.Y + q.Y);
		public static Point operator-(Point p, Point q) => new Point(p.X - q.X, p.Y - q.Y);
		public static Point operator*(Point p, double a) => new Point(a * p.X, a * p.Y);
		public static Point operator*(double a, Point p) => new Point(a * p.X, a * p.Y);
		public static Point operator/(Point p, double a) => new Point(p.X / a, p.Y / a);
	}

	public class Segment
	{
		public Point P1;
		public Point P2;
		public Segment(Point p1, Point p2)
		{
			P1 = p1;
			P2 = p2;
		}
	}

	public static double Abs(Vector a) => Math.Sqrt(Norm(a));
	public static double Norm(Vector a) => a.X * a.X + a.Y * a.Y;
	public static double Dot(Vector a, Vector b) => a.X * b.X + a.Y * b.Y;
	public static double Cross(Vector a, Vector b) => a.X * b.Y - a.Y * b.X;

	public static bool IsOrthogonal(Vector a, Vector b) => Equals(Dot(a, b), 0.0);
	public static bool IsOrthogonal(Point a1, Point a2, Point b1, Point b2) => IsOrthogonal(a1 - a2, b1 - b2);
	public static bool IsOrthogonal(Segment s1, Segment s2) => Equals(Dot(s1.P2 - s1.P1, s2.P2 - s2.P1), 0.0);
	public static bool IsParallel(Vector a, Vector b) => Equals(Cross(a, b), 0.0);
	public static bool IsParallel(Point a1, Point a2, Point b1, Point b2) => IsParallel(a1 - a2, b1 - b2);
	public static bool IsParallel(Segment s1, Segment s2) => Equals(Cross(s1.P2 - s1.P1, s2.P2 - s2.P1), 0.0);

	public static Point Project(Segment s, Point p)
	{
		Vector b = s.P2 - s.P1;
		double r = Dot(p - s.P1, b) / Norm(b);
		return s.P1 + b * r;
	}
	public static Point Reflect(Segment s, Point p) => p + (Project(s, p) - p) * 2.0;

	public static double GetDistance(Point a, Point b) => Abs(a - b);
	public static double GetDistanceLP(Line l, Point p) => Math.Abs(Cross(l.P2 - l.P1, p - l.P1) / Abs(l.P2 - l.P1));
	public static double GetDistanceSP(Segment s, Point p)
	{
		if(Dot(s.P2 - s.P1, p - s.P1) < 0.0) return Abs(p - s.P1);
		if(Dot(s.P1 - s.P2, p - s.P2) < 0.0) return Abs(p - s.P2);
		return GetDistanceLP(s, p);
	}
	public static double GetDistance(Segment s1, Segment s2)
	{
		if(Intersect(s1, s2)) return 0.0;
		return Math.Min(Math.Min(GetDistanceSP(s1, s2.P1), GetDistanceSP(s1, s2.P2)),
		                Math.Min(GetDistanceSP(s2, s1.P1), GetDistanceSP(s2, s1.P2)));
	}

	public const int COUNTER_CLOCKWISE = 1;
	public const int CLOCKWISE = -1;
	public const int ONLINE_BACK = 2;
	public const int ONLINE_FRONT = -2;
	public const int ON_SEGMENT = 0;
	public static int Ccw(Point p0, Point p1, Point p2)
	{
		Vector a = p1 - p0;
		Vector b = p2 - p0;
		if(Cross(a, b) > EPS) return COUNTER_CLOCKWISE;
		if(Cross(a, b) < -EPS) return CLOCKWISE;
		if(Dot(a, b) < -EPS) return ONLINE_BACK;
		if(Norm(a) < Norm(b)) return ONLINE_FRONT;
		return ON_SEGMENT;
	}
	public static bool Intersect(Point p1, Point p2, Point p3, Point p4)
	{
		return (Ccw(p1, p2, p3) * Ccw(p1, p2, p4) <= 0 && 
		        Ccw(p3, p4, p1) * Ccw(p3, p4, p2) <= 0);
	}
	public static bool Intersect(Segment s1, Segment s2) => Intersect(s1.P1, s1.P2, s2.P1, s2.P2);
}

public static class MyIO
{
	private static string[] args = null;
	private static int num = -1;
	private static int used = -1;

	private static string getArg()
	{
		if(used == num)
		{
			args = Console.ReadLine().Split(' ');
			num = args.Length;
			used = 0;
		}
		return args[used++];
	}

	public static int GetInt() => int.Parse(getArg());
	public static long GetLong() => long.Parse(getArg());
	public static double GetDouble() => double.Parse(getArg());
	public static decimal GetDecimal() => decimal.Parse(getArg());
	public static string GetString() => getArg();
	public static char GetChar() => getArg()[0];
	public static int[] GetInts(long N) => Enumerable.Range(0, (int)N).Select(_ => GetInt()).ToArray();
	public static long[] GetLongs(long N) => Enumerable.Range(0, (int)N).Select(_ => GetLong()).ToArray();
	public static double[] GetDoubles(long N) => Enumerable.Range(0, (int)N).Select(_ => GetDouble()).ToArray();
	public static decimal[] GetDecimals(long N) => Enumerable.Range(0, (int)N).Select(_ => GetDecimal()).ToArray();
	public static string[] GetStrings(long N) => Enumerable.Range(0, (int)N).Select(_ => GetString()).ToArray();
}

public static class MyUtil
{
	public static void chmax<T>(ref T x, T y) where T : IComparable<T>
	{
		if(x.CompareTo(y) < 0)
			x = y;
	}

	public static void chmin<T>(ref T x, T y) where T : IComparable<T>
	{
		if(x.CompareTo(y) > 0)
			x = y;
	}

	public static void swap<T>(ref T x, ref T y)
	{
		T tmp = x;
		x = y;
		y = tmp;
	}
}