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: Accepted)

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);

                Line l = new Line(myButtler, opponent);
                
                if (Triangle.isOnTriangle(bariar1, bariar2, bariar3, l)) {//????????¢????????????????????§??¬???????????????
                    Console.WriteLine("MISS");
                } else Console.WriteLine("HIT");//?????¢??¨????????????????????¢??¨??????????????????????????????
                Console.ReadLine();
        }

    }

    class Line {
        Vector o;//????????????
        Vector d;//??????????????????

        public Line(Vector a, Vector b) {
            o = new Vector(3, a.getComp(0), a.getComp(1), a.getComp(2));
            d = b - a;
        }

        public Vector getDirection() {
            return d;
        }

        public Vector getOne() {
            return o;
        }
    }
    
    
    class Triangle {
        const double EPS = 1e-8;

        public static bool isOnTriangle(Vector a, Vector b, Vector c, Line l) {
            Vector edge1 = b - a;
            Vector edge2 = c - a;
            Vector reverseD = new Vector(3, -l.getDirection().getComp(0), -l.getDirection().getComp(1), -l.getDirection().getComp(2));

            double den = det(edge1, edge2, reverseD);
            if (Math.Abs(den) < EPS) {
                return false;
            }

            double u = det(l.getOne() - a, edge2, reverseD) / den;
            if (u < 0 || u > 1) {
                return false;
            }

            double t = det(edge1, l.getOne() - a, reverseD) / den;
            if (t < 0 || u + t > 1) {
                return false;
            }

            double dist = det(edge1, edge2, l.getOne() - a) / den;
            if (dist < 0 || dist > 1) {
                return false;
            }

            return true;
        }

        static double det(Vector a, Vector b, Vector c) {
            return a.getComp(0) * b.getComp(1) * c.getComp(2) - a.getComp(0) * b.getComp(2) * c.getComp(1)
                + a.getComp(1) * b.getComp(2) * c.getComp(0) - a.getComp(1) * b.getComp(0) * c.getComp(2)
                + a.getComp(2) * b.getComp(0) * c.getComp(1) - a.getComp(2) * b.getComp(1) * c.getComp(0);
        }


    }

    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));
        }
    }
    
}