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("MISS");
                }
                if (Triangle.isOnTriangle(bariar1, bariar2, bariar3, v)) {
                    Console.WriteLine("MISS");
                } else Console.WriteLine("HIT");
            
        }
 
    }
 
     
    class Plane {
        Vector f;
 
        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 ((pla >= 0 && plb >= 0)||(pla <= 0 && plb <= 0)) {
                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);
            double in23 = Vector.innerProduct(c2, c3, 3);
 
            if (in12 >= 0 && in13 >= 0 && in23 >= 0 || in12 <= 0 && in13 <= 0 && in23 <= 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));
        }
    }
     
}