Problem:
宇宙船 UAZ アドバンス号

恒星歴 2005.11.5。あなたは宇宙船 UAZ アドバンス号の艦長として敵の宇宙船と交戦しようとしています。 幸い敵の宇宙船はまだこちらに気付かずに静止しています。また、すでに敵の宇宙座標は判明しており強力な直線のビームを放つ「フェザー砲」は発射準備を完了しています。あとは、発射命令を出すばかりです。

ところが、宇宙空間には、敵の設置したエネルギーバリアが存在しています。バリアは三角形をしており「フェザー砲」のビームをはね返してしまいます。また、ビームがバリアに当たれば敵に気付かれて逃げられてしまいます。事前に命中すると判定できなければ、発射命令は出せません。

そこで、UAZ アドバンス号、敵、バリアの位置の宇宙座標(3次元座標 x, y, z) を入力して、ビームがバリアをさけて敵に命中する場合は "HIT"、バリアに当たってしまう場合"MISS"と出力するプログラムを作成してください。

ただし、バリアはアドバンス号から 3 角形に見えるものだけが対象であり、線分につぶれて見えるものはないものとします。また、バリアは 3 角形の頂点を含む境界でも有効であり、ビームをはね返すものとします。また、敵がバリア内にいる場合は"MISS"と出力して下さい。

Input

入力データの形式は以下のとおりです：

1 行目は、UAZ アドバンス号の座標 (x, y, z) (整数、半角空白区切り)

2 行目は、敵の座標 (x, y, z) (整数、半角空白区切り)

3 行目は、バリアの頂点 1 の座標 (x, y, z) (整数、半角空白区切り)

4 行目は、バリアの頂点 2 の座標 (x, y, z ) (整数、半角空白区切り)

5 行目は、バリアの頂点 3 の座標 (x, y, z ) (整数、半角空白区切り)

Output

HIT または MISS と１行に出力してください。

Constraints

-100 ≤ x, y, z ≤ 100

UAZ アドバンス号と敵が同じ位置にいることはない。

Sample Input 1

-10 0 0
10 0 0
0 10 0
0 10 10
0 0 10

Output for the Sample Input 1

HIT

Sample Input 2

-10 6 6
10 6 6
0 10 0
0 10 10
0 0 10

Output for the Sample Input 2

MISS

Solution in C# (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication11 {
    class Program {


        static void Main(string[] args) {
            new Program().solve();
        }

        void solve() {

                string input1 = Console.ReadLine();
                string input2 = Console.ReadLine();
                string input3 = Console.ReadLine();
                string input4 = Console.ReadLine();
                string input5 = Console.ReadLine();
                Vector myButtler = new Vector(input1);
                Vector opponent = new Vector(input2);
                Vector bariar1 = new Vector(input3);
                Vector bariar2 = new Vector(input4);
                Vector bariar3 = new Vector(input5);


                Plane p = new Plane(bariar1, bariar2, bariar3);
                Vector v = p.calcIntersection(myButtler, opponent);
                if (v.getComp(0) == int.MinValue) {
                    Console.WriteLine("HIT");
                }
                if (Triangle.isOnTriangle(bariar1, bariar2, bariar3, v)) {
                    Console.WriteLine("MISS");
                } else Console.WriteLine("HIT");
            
        }

    }

    
    class Plane {
        Vector f;
        const double eps = 1e-5;

        public Plane(Vector a, Vector b, Vector c) {
            Vector d = new Vector(3);
            var ab = b - a;
            var bc = c - b;
            d = Vector.normalize(Vector.outerProduct(ab, bc, 3));

            double q = Vector.innerProduct(a,d,3);
            f = new Vector(4);
            for (int i = 0; i < 3; i++) {
                f.setComp(d.getComp(i), i);
            }
            f.setComp(q, 3);
        }

        public Vector calcIntersection(Vector a, Vector b){
            Vector p = new Vector(3, f.getComp(0) * f.getComp(3), f.getComp(1) * f.getComp(3), f.getComp(2) * f.getComp(3));
            Vector pa = new Vector(3, a.getComp(0) - p.getComp(0), a.getComp(1) - p.getComp(1), a.getComp(2) - p.getComp(2));
            Vector pb = new Vector(3, b.getComp(0) - p.getComp(0), b.getComp(1) - p.getComp(1), b.getComp(2) - p.getComp(2));

            double pla = Vector.innerProduct(pa,f,3);
            double plb = Vector.innerProduct(pb,f,3);

            if (Math.Abs(pla) < eps) { pla = 0.0; }
            if (Math.Abs(plb) < eps) { plb = 0.0; }

            if (pla == 0.0 && plb == 0.0) {
                return new Vector(3, int.MinValue, int.MinValue, int.MinValue);
            } else if ((pla  <= 0.0 && plb >= 0.0) || (pla >= 0.0 && plb <= 0.0)) {
            } else return new Vector(3, int.MinValue, int.MinValue, int.MinValue);

            Vector ab = new Vector(3, b.getComp(0) - a.getComp(0), b.getComp(1) - a.getComp(1), b.getComp(2) - a.getComp(2));
            double rate = Math.Abs(pla)/(Math.Abs(pla)+Math.Abs(plb));

            return new Vector(3, a.getComp(0) + ab.getComp(0) * rate, a.getComp(1) + ab.getComp(1) * rate, a.getComp(2) + ab.getComp(2) * rate);
        }
    }
    class Triangle {
        public static bool isOnTriangle(Vector a, Vector b, Vector c, Vector v) {
            Vector ab = b - a;
            Vector bc = c - b;
            Vector ca = a - c;
            Vector av = v - a;
            Vector bv = v - b;
            Vector cv = v - c;

            Vector c1 = Vector.outerProduct(ab, bv, 3);
            Vector c2 = Vector.outerProduct(bc, cv, 3);
            Vector c3 = Vector.outerProduct(ca, av, 3);

            double in12 = Vector.innerProduct(c1, c2, 3);
            double in13 = Vector.innerProduct(c1, c3, 3);

            if (in12 >= 0 && in13 >= 0) {
                return true;
            }
            return false;
        }
    }

    class Vector {
        double[] x;

        public Vector(int length) {
            x = new double[length];
        }

        

        public Vector(int length,double a, double b,double c) {
            x = new double[length];
            x[0] = a;
            x[1] = b;
            x[2] = c;
        }

        public Vector(string input) {
            x = new double[3];
            string[] splited = input.Split(' ');
            for (int i = 0; i < x.Length; i++) {
                x[i] = double.Parse(splited[i]);
            }
        }

        public void setComp(double t,int idx) {
            x[idx] = t;
        }

        public double getComp(int idx) {
            return x[idx];
        }

        public static double innerProduct(Vector a, Vector b,int length) {
            double t = 0;
            for (int i = 0; i < length; i++) {
                t += a.getComp(i) * b.getComp(i);
            }
            return t;
        }

        public static Vector outerProduct(Vector a, Vector b,int length) {
            return new Vector(length, a.getComp(1) * b.getComp(2) - a.getComp(2) * b.getComp(1), a.getComp(2) * b.getComp(0) - a.getComp(0) * b.getComp(2), a.getComp(0) * b.getComp(1) - a.getComp(1) * b.getComp(0));
        }

        public static Vector normalize(Vector a) {
            double s = Math.Sqrt(Math.Pow(a.getComp(0), 2) + Math.Pow(a.getComp(1), 2) + Math.Pow(a.getComp(2), 2));
            return new Vector(3, a.getComp(0) / s, a.getComp(1) / s, a.getComp(2) / s);
        }

        public static Vector operator -(Vector a, Vector b) {
            return new Vector(3, a.getComp(0) - b.getComp(0), a.getComp(1) - b.getComp(1), a.getComp(2) - b.getComp(2));
        }
    }
    
}