Language: C++

#include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define IINF (INT_MAX)
#define EPS (1e-7)
#define equals(a,b) (fabs((a)-(b))<EPS)

using namespace std;

//作成中 どれもVirifyしてない
class Point3d{
public:
  double x,y,z;

  Point3d(double x=0,double y=0,double z=0):x(x),y(y),z(z){}

  Point3d operator + (const Point3d& a){
    return Point3d(x+a.x,y+a.y,z+a.z);
  }
  Point3d operator - (const Point3d& a){
    return Point3d(x-a.x,y-a.y,z-a.z);
  }
  Point3d operator * (const double& d){
    return Point3d(x*d,y*d,z*d);
  }
  Point3d operator / (const double& d){
    return Point3d(x/d,y/d,z/d);
  }

  bool operator < (const Point3d& p)const{
    return !equals(x,p.x)?x<p.x:((!equals(y,p.y))?y<p.y:z<p.z);
  }

  bool operator == (const Point3d& p)const{
    return equals(x,p.x) && equals(y,p.y) && equals(z,p.z);
  }

};

struct Segment3d{
  Point3d p[2];
  Segment3d(Point3d p1=Point3d(),Point3d p2=Point3d()){
    p[0] = p1, p[1] = p2;
  }
  bool operator == (const Segment3d& seg)const{
    return p[0] == seg.p[0] && p[1] == seg.p[1];
  }
};

typedef Point3d Vector3d;
typedef Segment3d Line3d;




ostream& operator << (ostream& os,const Point3d& p){
  os << "(" << p.x << "," << p.y << "," << p.z << ")";
}

ostream& operator << (ostream& os,const Segment3d& seg){
  os << "(" << seg.p[0] << "," << seg.p[1] << ")";
}

double dot(const Point3d& a,const Point3d& b){
  return a.x*b.x + a.y*b.y + a.z*b.z;
}

Vector3d cross(const Point3d& a,const Point3d& b){
  return Vector3d(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}

inline double norm(const Point3d &p){
  return p.x*p.x + p.y*p.y + p.z*p.z;
}

inline double abs(const Point3d &p){
  return sqrt(norm(p));
}

inline double toRad(double theta){
  return theta * M_PI / 180.0;
}



bool on_line3d(Line3d line,Point3d p){
  cout << cross(p-line.p[0],line.p[1]-line.p[0]) << endl;
  return equals(abs(cross(p-line.p[0],line.p[1]-line.p[0])),0);
}

bool on_segment3d(Segment3d seg,Point3d p){
  if( !on_line3d(seg,p) ) return false;
  double dist[3] = { abs(seg.p[1]-seg.p[0]), abs(p-seg.p[0]), abs(p-seg.p[1]) };  
  cout << dist[0] << " " << dist[1] << " " << dist[2] << endl;
  return on_line3d(seg,p) && equals(dist[0],dist[1]+dist[2]);
}

bool point_on_the_triangle3d(Point3d tri1,Point3d tri2,Point3d tri3,Point3d p){

  if( on_segment3d(Segment(tri1,tri2),p) ) return true;
  if( on_segment3d(Segment(tri2,tri3),p) ) return true;
  if( on_segment3d(Segment(tri3,tri1),p) ) return true;

  Vector3d v1 = tri2 - tri1;
  Vector3d v2 = tri3 - tri2;
  Vector3d v3 = tri1 - tri3;
  /*
  bool res  = ( cross(v1,p-tri1).z >= 0 ); //線分上にある場合もtrue,　線分上にある場合は駄目とするならば > 0 とすること
  bool res2 = ( cross(v2,p-tri2).z >= 0 );
  bool res3 = ( cross(v3,p-tri3).z >= 0 );
  return res == res2 && res2 == res3;
  */
  //Vector3d cp[3] = { cross(v1,p-tri2), cross(v2,p-tri3), cross(v3,p-tri1) };
  Vector3d cp[3] = { cross(v1,p-tri1), cross(v2,p-tri2), cross(v3,p-tri3) };
  //cout << cp[0] << " | " << cp[1] << " | " << cp[2] << endl;
  double d1 = dot(cp[0],cp[1]);
  double d2 = dot(cp[0],cp[2]);
  if( d1 >= 0 && d2 >= 0 ) return true;
  return false;
}

inline Point3d rotateX(Point3d p,double rad){
  return Point3d(p.x,p.y*cos(rad)-p.z*sin(rad),p.y*sin(rad)+p.z*cos(rad));
}

inline Point3d rorateY(Point3d p,double rad){
  return Point3d(p.x*cos(rad)+p.z*sin(rad),p.y,-p.x*sin(rad)+p.z*cos(rad));
}

inline Point3d rorateZ(Point3d p,double rad){
  return Point3d(p.x*cos(rad)-p.y*sin(rad),p.x*sin(rad)+p.y*cos(rad),p.z);
}

inline Point3d rotateEuler(Point3d p,double alpha,double beta,double gamma){
  return Point3d( (cos(alpha)*cos(beta)*cos(gamma)-sin(alpha)*sin(gamma)) * p.x + (-cos(alpha)*cos(beta)*sin(gamma)-sin(alpha)*cos(gamma)) * p.y + (cos(alpha)*sin(beta)) * p.z,
		  (sin(alpha)*cos(beta)*cos(gamma)+cos(alpha)*sin(gamma)) * p.x + (-sin(alpha)*cos(beta)*sin(gamma)+cos(alpha)*cos(gamma)) * p.y + (sin(alpha)*sin(beta)) * p.z,
		  (-sin(beta)*cos(gamma)) * p.x + (sin(beta)*sin(gamma)) * p.y + (cos(beta)) * p.z);
}

inline Point3d rotateRollPitchYaw(Point3d p,double roll,double pitch,double yaw){
  return Point3d( ( cos(roll) * cos(pitch) ) * p.x + ( cos(roll) * sin(pitch) * sin(yaw) - sin(roll) * cos(yaw) ) * p.y + ( cos(roll) * sin(pitch) * cos(yaw) + sin(roll) * sin(yaw) ) * p.z,
		  ( sin(roll) * cos(pitch) ) * p.x + ( sin(roll) * sin(pitch) * sin(yaw) + cos(roll) * cos(yaw) ) * p.y + ( sin(roll) * sin(pitch) * cos(yaw) - cos(roll) * sin(yaw) ) * p.z,
		  -sin(pitch) * p.x + cos(pitch) * sin(yaw) * p.y + cos(pitch) * cos(yaw) * p.z);
}


class Plane3d{
public:
  Point3d normal_vector; //法線ベクトル
  double d; // 平面方程式 normal_vector.x * x + normal_vector.y * y + normal_vector.z * z + d = 0

  Plane3d(Point3d normal_vector=Point3d(),double d=0):normal_vector(normal_vector),d(d){}
  Plane3d(Vector3d a,Vector3d b,Vector3d c){
    Vector3d v1 = b - a;
    Vector3d v2 = c - a;
    Vector3d tmp = cross(v1,v2);
    normal_vector = tmp / abs(tmp);
    set_d(a);
  }

  //法線ベクトルnormal_vectorと平面上の１点からdを計算する
  void set_d(Point3d p){
    d = dot(normal_vector,p);
  }

  //平面と点pの距離を求める
  double distanceP(Point3d p){
    Point3d a = normal_vector * d;//平面上の適当な点をつくる
    return abs( dot(p-a,normal_vector) );
  }

  //平面上でもっとも点pと近い点を求める
  Point3d nearest_point(Point3d p){
    Point3d a = normal_vector * d;
    return p - ( normal_vector * dot(p-a,normal_vector) );
  }

  //平面と線分が交差するか
  bool intersectS(Segment3d seg){
    Point3d a = normal_vector * d;
    double res1 = dot(a-seg.p[0],normal_vector);
    double res2 = dot(a-seg.p[1],normal_vector);
    if( res1 > res2 ) swap(res1,res2);
    //cout << res1 << " < " << res2 << endl;
    if( res1 <= 0 && res2 >= 0 ) return true;
    return false;
  }

  //平面と線分の交点を求める
  Point3d crosspointS(Segment3d seg){
    Point3d a = normal_vector * d;
    double dot_p0a = fabs(dot( seg.p[0]-a,normal_vector ));
    double dot_p1a = fabs(dot( seg.p[1]-a,normal_vector ));
    if( dot_p0a+dot_p1a == 0 ) return seg.p[0];
    return seg.p[0] + ( seg.p[1] - seg.p[0] ) * ( dot_p0a / ( dot_p0a + dot_p1a ) );
  }

};

Point3d crosspointTS(Point3d tri1,Point3d tri2,Point3d tri3,Segment3d seg){
  Vector3d normal_vector = cross(tri2-tri1,tri3-tri1); 
  normal_vector = normal_vector / abs( normal_vector );
  double dist1 = dot(seg.p[1]-seg.p[0],normal_vector);
  double dist2 = dot(tri1-seg.p[0],normal_vector);
  double t = dist2 / dist1;
  Point3d e = (seg.p[1]-seg.p[0]) / abs(seg.p[1]-seg.p[0]);
  return seg.p[0] + e * t;
}

const string Y="HIT", N = "MISS";
int main(){
  /*
  Point3d p(12,51,9);
  double a = toRad(121), b = toRad(31), c = toRad(19);
  cout << rotateEuler(p,a,b,c) << endl;
  cout << rotateRollPitchYaw(p,a,b,c) << endl;
  */
  /*
  Point3d a(0,0,0);
  Point3d b(10,0,0);
  Point3d c(0,10,0);
  Point3d p(1,1,10);
  cout << point_on_the_triangle3d(a,b,c,p) << endl;
  */
  /*
  Segment3d seg(Point3d(0,0,0),Point3d(10,0,0));
  Point3d p(4,0,0);
  cout << on_segment3d(seg,p) << endl;
  */
  Point3d tri[3],S,G;
  cin >> S.x >> S.y >> S.z;
  cin >> G.x >> G.y >> G.z;
  rep(i,3)cin >> tri[i].x >> tri[i].y >> tri[i].z;


  /*
  bool error1 = false, error2 = false;
  rep(i,3){
    if( S == tri[i] )error1 = true;
    if( G == tri[i] )error2 = true;
  }

  if( error1 ){
    cout << N << endl;
    return 0;
  } 
  if( error2 ){
    cout << N << endl;
    return 0;
  }
  */
  Plane3d plane(tri[0],tri[1],tri[2]);
  /*
  double tmp = fabs(dot(G-S,plane.normal_vector));

  if( equals(tmp,0) ){
    cout << N << endl;
    return 0;
  }
  */
  //cout << plane.normal_vector.x << "x + " << plane.normal_vector.y << "y + " << plane.normal_vector.z << "z + " << plane.d << endl;
  //cout << plane.normal_vector << endl;
  //cout << "d = " << plane.d << endl;
  //cout << "a = " << plane.normal_vector * plane.d << endl;
  Segment3d seg(S,G);

  if( !plane.intersectS(seg) ){
    cout << Y << endl;
    return 0;
  }

  Point3d cp = /*crosspointTS(tri[0],tri[1],tri[2],Segment3d(S,G));*/plane.crosspointS(seg);
  //cout << cp << " " << plane.crosspointS(seg)<< endl;
  //cout << "cp = " << cp << endl;
  cout << (point_on_the_triangle3d(tri[0],tri[1],tri[2],cp)?N:Y) << endl;
  return 0;
}

Compiler output:
a.cc: In function 'std::ostream& operator<<(std::ostream&, const Point3d&)':
a.cc:59:1: warning: no return statement in function returning non-void [-Wreturn-type]
   59 | }
      | ^
a.cc: In function 'std::ostream& operator<<(std::ostream&, const Segment3d&)':
a.cc:63:1: warning: no return statement in function returning non-void [-Wreturn-type]
   63 | }
      | ^
a.cc: In function 'bool point_on_the_triangle3d(Point3d, Point3d, Point3d, Point3d)':
a.cc:101:20: error: 'Segment' was not declared in this scope; did you mean 'Segment3d'?
  101 |   if( on_segment3d(Segment(tri1,tri2),p) ) return true;
      |                    ^~~~~~~
      |                    Segment3d
a.cc:102:20: error: 'Segment' was not declared in this scope; did you mean 'Segment3d'?
  102 |   if( on_segment3d(Segment(tri2,tri3),p) ) return true;
      |                    ^~~~~~~
      |                    Segment3d
a.cc:103:20: error: 'Segment' was not declared in this scope; did you mean 'Segment3d'?
  103 |   if( on_segment3d(Segment(tri3,tri1),p) ) return true;
      |                    ^~~~~~~
      |                    Segment3d