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 Scala (judge verdict: Accepted)

object Main extends App{
  import scala.collection.mutable.ListBuffer._
  import scala.io.Source._
  import scala.io.StdIn._
  import scala.collection.mutable._
  val advance = Matrix(readLine().trim().split(" ").map{s => Rational(s.toInt)}.toList)
  val enemy = Matrix(readLine().trim().split(" ").map{s => Rational(s.toInt)}.toList)
  val barrier = Matrix(readLine().trim().split(" ").map{s => Rational(s.toInt)}.toList, readLine().trim().split(" ").map{s => Rational(s.toInt)}.toList, readLine().trim().split(" ").map{s => Rational(s.toInt)}.toList)
  val barrierVec = Matrix.inverse(Matrix(barrier.toList.map{l => l.zip(advance.toList.head).map{case (a, b) => a - b}}.toSeq:_*)).map(m => m * (enemy - advance))
  println(barrierVec match{
    case Some(m) => 
      if (m.toList.exists(_.exists{_ < 0}) || m.toList.map{l => l.reduce{(a, b) => a + b}}.reduce{_ + _} < 1)
        "HIT"
      else
        "MISS"
    case None => 
      "Miss"
  })
  object Rational{
    def apply(int:Int):Rational = {
      new Rational(int, 1)
    }
    def apply(num:BigInt, den:BigInt):Rational = {
      val n = if (num < 0) -num else num
      val d = if (den < 0) -den else den
      val sign = if (num * den < 0) -1 else 1
      val g = gcd(n, d)
      new Rational(sign * n / g, d / g)
    }
    
    private def gcd(a:BigInt, b:BigInt):BigInt = {
      b match{
        case _ if b == 0 => a
        case _ => gcd(b, a % b)
      }
    }
    implicit val toRational:Int => Rational = new Rational(_, 1)
  }
  class Rational(val numerator:BigInt, val denominator:BigInt){
    def +(other:Rational):Rational = Rational(numerator * other.denominator + denominator * other.numerator, denominator * other.denominator)
    def *(other:Rational):Rational = Rational(numerator * other.numerator, denominator * other.denominator)
    def -(other:Rational):Rational = this + -1 * other
    def /(other:Rational):Rational = Rational(numerator * other.denominator, denominator * other.numerator)
    def ==[A <% Rational](other:A):Boolean = numerator == other.numerator && denominator == other.denominator
    def <[A <% Rational](other:A):Boolean = (this - other).numerator < 0
    override def toString():String = s"$numerator/$denominator"
  }
  object Matrix{
    def apply(rat:List[Rational]*):Matrix = {
      new Matrix(rat.toList, rat.head.size, rat.size)
    }
    def swap[A](list:List[List[A]]):List[List[A]] = {
      list match{
        case Nil => Nil
        case l =>
          l.foldLeft((ListBuffer.empty[A], ListBuffer.empty[List[A]])){
          case ((hs, tb), (Nil)) => (hs, tb)
          case ((hs, tb), (h::Nil)) => (hs += h, tb)
          case ((hs, tb), (h::t)) => (hs += h, tb += t)
        } match {
          case (hb, tb) => hb.toList::swap(tb.toList)
        }
      }
      
    }
    def slice[A](lis:List[A]):List[List[A]] = {
      def merge(a:List[A], b:List[A]):List[A] = {
        a match{
          case Nil => b
          case h::t => merge(t, h::b)
        }
      }
      def sub(prev:List[A], next:List[A]):List[List[A]] = {
        next match{
          case Nil => Nil
          case h::t => merge(prev, t)::sub(h::prev, t)
        }
      }
      sub(Nil, lis)
    }
    def det(matrix:Matrix):Rational = {
      if (matrix.height != matrix.width) throw new Exception("Demension has not matched")
      if (matrix.height == 1) matrix.list.head.head
      else{
        swap(slice(matrix.list).head.map{a => slice(a)}).map{case a => det(new Matrix(a, matrix.height - 1, matrix.width - 1))}.zip(matrix.list.head).map{case (a, b) => a * b}.foldLeft((1, Rational(0))){case ((parity, sum),h) => (-1 * parity, sum + parity * h)}._2
      }
    }
    def inverse(matrix:Matrix):Option[Matrix] = {
      val determin = det(matrix)
      if (determin == 0)
        None
      else {
        val res = swap(matrix.list.map{slice(_)}).map{slice(_)}.map{a => a.map{b => det(new Matrix(b, matrix.height - 1, matrix.width - 1)) / determin}}.foldLeft((1, ListBuffer.empty[List[Rational]])){case ((parity, lb), l) => (-1 * parity, lb += l.foldLeft((parity, ListBuffer.empty[Rational])){case ((p, l), h) => (-1 * p, l += h * p)}._2.toList)}._2.toList
        Some(new Matrix(res, matrix.height, matrix.width))
      }
    }
  }
  class Matrix(private val list:List[List[Rational]], val height:Int, val width:Int){
    def +(other:Matrix):Matrix = {
      if (height != other.height || width!= other.width) throw new Exception("Demension has not match")
      new Matrix(list.zip(other.list).map{case (a, b) => a.zip(b).map{case (c, d) => c + d}}, height, width)
    }
    def -(other:Matrix):Matrix = {
      if (height != other.height || width != other.width) throw new Exception("Demension has not match")
      new Matrix(list.zip(other.list).map{case (a, b) => a.zip(b).map{case (c, d) => c - d}}, height, width)
    }
    def *(other:Matrix):Matrix = {
      if (width != other.height) throw new Exception("Demension has not match")
      new Matrix(Matrix.swap(list).map{s => other.list.map{o => s.zip(o).map{case (a, b) => a * b}.reduce{_ + _}}}, height, other.width)
    }
    def map(func:Rational => Rational):Matrix = {
      new Matrix(list.map{_.map(func)}, height, width)
    }
    def toList = list
    override def toString():String = (Matrix.swap(list).map{_.mkString(" ")}).mkString("\n")
  }
}