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;

namespace CSharpSample01
{

    class Vector2
    {
        public double x;
        public double y;

        public Vector2() { }
        public Vector2(double x, double y)
        {
            this.x = x;
            this.y = y;
        }

        //「射影」
        //点pからベクトルp1p2への射影ベクトルを求める
        public Vector2 Projection(Vector2 p1, Vector2 p2, Vector2 p)
        {

            Vector2 hypo = new Vector2(p.x - p1.x, p.y - p1.y);

            Vector2 ground = new Vector2(p2.x - p1.x, p2.y - p1.y);

            Vector2 shadow = new Vector2
            {
                x = p1.x + ground.x * (hypo.x * ground.x + hypo.y * ground.y) / (ground.x * ground.x + ground.y * ground.y),
                y = p1.y + ground.y * (hypo.x * ground.x + hypo.y * ground.y) / (ground.x * ground.x + ground.y * ground.y)
            };

            return shadow;
        }

        //内積
        public double Dot(Vector2 a, Vector2 b)
        {
            return a.x * b.x + a.y * b.y;
        }

        //外積
        public double Cross(Vector2 a, Vector2 b)
        {
            return a.x * b.y - a.y * b.x;
        }

        //ベクトルの大きさ
        public double Norm(Vector2 a)
        {
            return Math.Sqrt(a.x * a.x + a.y * a.y);
        }

        //「交差判定」
        //2つの線分p1p2 s1s2が交差しているかどうかの判定
        public bool IsCross(Vector2 p1, Vector2 p2, Vector2 s1, Vector2 s2)
        {

            Vector2 p1p2 = new Vector2(p2.x - p1.x, p2.y - p1.y);
            Vector2 s1s2 = new Vector2(s2.x - s1.x, s2.y - s1.y);
            Vector2 p1s1 = new Vector2(s1.x - p1.x, s1.y - p1.y);
            Vector2 p1s2 = new Vector2(s2.x - p1.x, s2.y - p1.y);

            //p1p2s1s2のうち同一点がある
            if (p1s1.x == 0 && p1s1.y == 0)
            {
                return true;
            }
            else if (p1s2.x == 0 && p1s2.y == 0)
            {
                return true;
            }

            double t1;
            double t2;

            //平行
            if (Cross(p1p2, s1s2) == 0)
            {
                
                t1 = p1s1.x / p1p2.x;
                t2 = p1s1.y / p1p2.y;

                if (t1 != t2)
                {
                    return false;
                }
                if (t1 < 0 || 1 < t1 || t2 < 0 || 1 < t2)
                {
                    return false;
                }

                t1 = p1s2.x / p1p2.x;
                t2 = p1s2.y / p1p2.y;

                if (t1 != t2)
                {
                    return false;
                }
                if (t1 < 0 || 1 < t1 || t2 < 0 || 1 < t2)
                {
                    return false;
                }

                return true;
            }

            //平行でない
            t2 = Cross(p1s1, p1p2) / Cross(p1p2, s1s2);
            t1 = Cross(p1s1, s1s2) / Cross(p1p2, s1s2);
            
            if (0 <= t1 && t1 <= 1 && 0 <= t2 && t2 <= 1)
            {
                return true;
            }
            else
            {
                return false;
            }

        }

        //線分p1p2と点sとの距離
        public double Distance(Vector2 p1, Vector2 p2, Vector2 s)
        {

            double dis;
            Vector2 p1s = new Vector2(s.x - p1.x, s.y - p1.y);
            Vector2 p1p2 = new Vector2(p2.x - p1.x, p2.y - p1.y);
            Vector2 p2s = new Vector2(s.x - p2.x, s.y - p2.y);
            Vector2 p2p1 = new Vector2(p1.x - p2.x, p1.y - p2.y);


            //内積の正負で確認
            if (Dot(p1s, p1p2) <= 0)
            {
                dis = Norm(p1s);
            }
            else if (Dot(p2s, p2p1) <= 0)
            {
                dis = Norm(p2s);
            }
            else
            {
                Vector2 shadow = Projection(p1, p2, s);
                dis = Norm(new Vector2(s.x - shadow.x, s.y - shadow.y));
            }

            return dis;
        }

    }


    class Program
    {


        static void Main(string[] args)
        {
            int q = int.Parse(Console.ReadLine());

            for (int i = 0; i < q; i++)
            {
                double[] data = Console.ReadLine().Split(' ').Select(x => double.Parse(x)).ToArray();

                Vector2 v = new Vector2();
                Vector2 p1 = new Vector2(data[0], data[1]);
                Vector2 p2 = new Vector2(data[2], data[3]);
                Vector2 s1 = new Vector2(data[4], data[5]);
                Vector2 s2 = new Vector2(data[6], data[7]);

                var list = new List<double>();
                double ans;

                if (v.IsCross(p1, p2, s1, s2))
                {
                    
                    ans = 0;
                }
                else
                {
                    list.Add(v.Distance(p1, p2, s1));
                    list.Add(v.Distance(p1, p2, s2));
                    list.Add(v.Distance(s1, s2, p1));
                    list.Add(v.Distance(s1, s2, p2));

                    list.Sort();

                    ans = list.First();
                }

                Console.WriteLine($"{ans:f10}");

            }

        }
    }
}