Problem:
The Phantom
Mr. Hoge is in trouble. He just bought a new mansion, but it’s haunted by a phantom. He asked a famous conjurer
Dr. Huga to get rid of the phantom. Dr. Huga went to see the mansion, and found that the phantom is scared by
its own mirror images. Dr. Huga set two flat mirrors in order to get rid of the phantom.
As you may know, you can make many mirror images even with only two mirrors. You are to count up the
number of the images as his assistant. Given the coordinates of the mirrors and the phantom, show the number
of images of the phantom which can be seen through the mirrors.
Input
The input consists of multiple test cases. Each test cases starts with a line which contains two positive integers,
p
x
and
p
y
(1 ≤
p
x
,
p
y
≤ 50), which are the
x
- and
y
-coordinate of the phantom. In the next two lines, each line
contains four positive integers
u
x
,
u
y
,
v
x
and
v
y
(1 ≤
u
x
,
u
y
,
v
x
,
v
y
≤ 50), which are the coordinates of the mirror.
Each mirror can be seen as a line segment, and its thickness is negligible. No mirror touches or crosses with
another mirror. Also, you can assume that no images will appear within the distance of 10
-5
from the endpoints
of the mirrors.
The input ends with a line which contains two zeros.
Output
For each case, your program should output one line to the standard output, which contains the number of images
recognized by the phantom. If the number is equal to or greater than 100, print “TOO MANY” instead.
Sample Input
4 4
3 3 5 3
3 5 5 6
4 4
3 3 5 3
3 5 5 5
0 0
Output for the Sample Input
4
TOO MANY

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <utility>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e12;
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS  && dot(s[0]-p, s[1]-p)<EPS;
}

P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
P reflection(const L& l, const P& p) {
    return p + 2.0*(projection(l, p) -p);
}
L reflection(const L& l, const L& m){
    return L(reflection(l, m[0]), reflection(l, m[1]));
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}

const int maxrep = 1300;

int main(){
    while(1){
        int sx,sy;
        cin >> sx >> sy;
        if(sx == 0) break;

        P s(sx, sy);
        vector<L> mirror(2);
        for(int d=0; d<2; d++){
            int xs,ys,xt,yt;
            cin >> xs >> ys >> xt >> yt;
            mirror[d] = L(P(xs, ys), P(xt, yt));
        }

        //反射後の鏡・幽霊の位置
        vector<vector<L> > w(2, vector<L>(maxrep));
        vector<vector<P> > p(2, vector<P>(maxrep));
        for(int d=0; d<2; d++){
            w[d][0] = mirror[1-d];
            w[d][1] = mirror[d];
            p[d][0] = s;
            p[d][1] = reflection(w[d][1], p[d][0]);
            for(int i=2; i<maxrep; i++){
                w[d][i] = reflection(w[d][i-1], w[d][i-2]);
                p[d][i] = reflection(w[d][i], p[d][i-1]);
            }
        }
        
        int ans = 0;
        for(int d=0; d<2; d++){
            for(int i=1; i<maxrep && ans<100; i++){
                L ray(p[d][0], p[d][i]);
                //コーナーケース:別の鏡に遮られる
                if(!isParallel(ray, w[d][0]) && intersectSS(ray, w[d][0])){
                    L ray2(crosspointLL(ray, w[d][0]), ray[1]);
                    if(intersectSS(ray2, w[d][1])) continue;
                }
                //順番に通過していればよい
                bool ok = true;
                for(int j=1; j<=i; j++){
                    if(isParallel(ray, w[d][j]) || !intersectSS(ray, w[d][j])){
                        ok = false;
                        break;
                    }
                    ray[0] = crosspointLL(ray, w[d][j]);
                }
                if(ok){
                    ans++;
                }
            }
        }
        if(ans >= 100){
            cout << "TOO MANY" << endl;
        }else{
            cout << ans << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3280
final_rank: 1

code_snippet: #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 EPS (1e-7)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

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

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

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

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}

bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}

bool intersectLP(Line l,Point p) { return abs(cross(l.p2-p, l.p1-p)) < EPS; }

bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}

bool intersectSP(Line s, Point p) { return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; }

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}

Point reflection(Line l,Point p) { return p + (projection(l, p) - p) * 2; }

double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //???????????°??????????????????
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}

// --------

inline bool LT(double a,double b) { return !equals(a,b) && a < b; }
inline bool LTE(double a,double b) { return equals(a,b) || a < b; }

const double PI2 = M_PI * 2.0;
struct AngleRange {
  Point o; // ?????????, ???????????????????§???? ????????¨???????????????????????????,????????????
  double mini,maxi; // mini <= maxi | 0 <= mini,maxi <= 720
  // ?????°?????????????????§abs(maxi-mini)???180??????

  AngleRange( Point p, Segment seg ) {
    o = p;
    seg.p1 = seg.p1 - o, seg.p2 = seg.p2 - o;
    complex<double> p1(seg.p1.x,seg.p1.y);
    complex<double> p2(seg.p2.x,seg.p2.y);
    double tmp = arg( p1 / p2 ); // ???????????? p1 ??¨ p2 ??????????§? arg( p1 / p2 )
    mini = LT(0.0,tmp) ? arg(p2) : arg(p1);
    if( LT(mini,0) ) mini += PI2;
    maxi = abs(tmp) + mini;
  }

  bool fail(){ return equals(mini,maxi); }

  // mini < a < maxi
  bool contains(double a) const { 
    return ( LT(mini,a-PI2) && LT(a-PI2,maxi) ) || ( LT(mini,a) && LT(a,maxi) )  || ( LT(mini,a+PI2) && LT(a+PI2,maxi) );
  }

  bool contains(Point p) const {
    p = p - o;
    complex<double> cp(p.x,p.y);
    return contains(arg(cp));
  }

  void update( AngleRange ar ) {
    if( contains(ar.mini) ) {
      if( contains(ar.maxi) ) mini = ar.mini, maxi = ar.maxi;
      else                    mini = ar.mini;
    } else { 
      if(        contains(ar.maxi) ) maxi = ar.maxi;
      else  if( !ar.contains(mini) && !equals(mini,ar.mini) ) maxi = mini;
    }
    if( LT(maxi-mini,0)    ) maxi += PI2;
    if( LTE(PI2,maxi-mini) ) maxi -= PI2;
  }

};

ostream& operator << (ostream& os,const AngleRange& a){ os << "[ " << a.mini*180.0/M_PI << " , " << a.maxi*180.0/M_PI << " ]"; }

Segment reflection(Line line, Segment seg){
  return Segment(reflection(line,seg.p1),reflection(line,seg.p2));
}

double distance(Segment s,Point p1,Point p2){
  Segment t = Segment(p1,p2);
  Point cp = crosspoint(s,Line(p1,p2));
  return abs(p1-cp);
}

Point vp;
double distance2(Segment s,double rad){
  Vector e = Point(10,0);
  e = rotate(e,rad);
  Point cp = crosspoint(s,Line(vp,vp+e));
  return abs(cp-vp);
}

const int loop_limit = 100000;
void compute(Point phantom,Segment mirror1,Segment mirror2){
  
  vp = phantom;

  Point iPhantom[2] = { reflection(mirror1,phantom), reflection(mirror2,phantom) }; 
  Segment nmirror[2] = { mirror1, mirror2 };
  AngleRange range[2] = { AngleRange(phantom,mirror1), AngleRange(phantom,mirror2) };
  int cnt = 0;
  int i = 0;
  while( i < loop_limit && cnt <= 100 && !( range[0].fail() && range[1].fail() ) ){
    if( !range[0].fail() )
    if( !intersectSS(Segment(phantom,iPhantom[0]),mirror2) || !LT(distance(mirror2,phantom,iPhantom[0]),distance(mirror1,phantom,iPhantom[0])) ) {
      if( range[0].contains(iPhantom[0]) ) ++cnt;
    }

    if( !range[1].fail() )
     if( !intersectSS(Segment(phantom,iPhantom[1]),mirror1) || !LT(distance(mirror1,phantom,iPhantom[1]),distance(mirror2,phantom,iPhantom[1])) ) {
      if( range[1].contains(iPhantom[1]) ) ++cnt;
    }
    
    Segment tmp1 = reflection(mirror1,nmirror[1]);
    Segment tmp2 = reflection(mirror2,nmirror[0]);
    Point   tmp3 = reflection(mirror1,iPhantom[1]);
    Point   tmp4 = reflection(mirror2,iPhantom[0]);

    AngleRange tmpR(phantom,tmp1);
    range[0].update(tmpR);
    tmpR = AngleRange(phantom,tmp2);
    range[1].update(tmpR);

    double mid = ( range[0].mini + range[0].maxi ) / 2;
    if( !range[0].fail() && LT(distance2(tmp1,mid),distance2(nmirror[0],mid)) ) range[0].mini = range[0].maxi = 0;
    mid = ( range[1].mini + range[1].maxi ) / 2;
    if( !range[1].fail() && LT(distance2(tmp2,mid),distance2(nmirror[1],mid)) ) range[1].mini = range[1].maxi = 0;

    nmirror[0] = tmp1;
    nmirror[1] = tmp2;
    iPhantom[0] = tmp3;
    iPhantom[1] = tmp4;

    ++i;
    
  }

  if( cnt > 100 ) puts("TOO MANY");
  else cout << cnt << endl;
}

int main(){
  int sx,sy;
  while( cin >> sx >> sy, sx | sy ){
    Point sp = Point(sx,sy);
    Segment segs[2];
    rep(i,2) cin >> segs[i].p1.x >> segs[i].p1.y >> segs[i].p2.x >> segs[i].p2.y;
    compute(sp,segs[0],segs[1]);
  }
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 1336
final_rank: 1

code_snippet: #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 EPS (1e-7)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

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

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

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

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //???????????°??????????????????
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}


//cross product of pq and pr
double cross3p(Point p,Point q,Point r) { return (r.x-q.x) * (p.y -q.y) - (r.y - q.y) * (p.x - q.x); }
  
//returns true if point r is on the same line as the line pq
bool collinear(Point p,Point q,Point r) { return fabs(cross3p(p,q,r)) < EPS; }
  
//returns true if point t is on the left side of line pq
bool ccwtest(Point p,Point q,Point r){
  return cross3p(p,q,r) > 0; //can be modified to accept collinear points
}
 
bool onSegment(Point p,Point q,Point r){
  return collinear(p,q,r) && equals(sqrt(pow(p.x-r.x,2)+pow(p.y-r.y,2)) + sqrt(pow(r.x-q.x,2) + pow(r.y-q.y,2) ),sqrt(pow(p.x-q.x,2)+pow(p.y-q.y,2)) ) ;
}

// --------

inline bool LT(double a,double b) { return !equals(a,b) && a < b; }
inline bool LTE(double a,double b) { return equals(a,b) || a < b; }


const double PI2 = M_PI * 2.0;
struct AngleRange {
  Point o; // ?????????, ???????????????????§???? ????????¨???????????????????????????,????????????
  double mini,maxi; // mini <= maxi | 0 <= mini,maxi <= 720
  // ?????°?????????????????§abs(maxi-mini)???180??????

  AngleRange( Point p, Segment seg ) {
    o = p;
    seg.p1 = seg.p1 - o, seg.p2 = seg.p2 - o;
    complex<double> p1(seg.p1.x,seg.p1.y);
    complex<double> p2(seg.p2.x,seg.p2.y);
    double tmp = arg( p1 / p2 ); // ???????????? p1 ??¨ p2 ??????????§? arg( p1 / p2 )
    mini = LT(0.0,tmp) ? arg(p2) : arg(p1);
    if( LT(mini,0) ) mini += PI2;
    maxi = abs(tmp) + mini;
  }

  bool fail(){ return equals(mini,maxi); }

  // mini < a < maxi
  bool contains(double a) const { 
    return ( LT(mini,a-PI2) && LT(a-PI2,maxi) ) || ( LT(mini,a) && LT(a,maxi) )  || ( LT(mini,a+PI2) && LT(a+PI2,maxi) );
  }

  bool contains(Point p) const {
    p = p - o;
    complex<double> cp(p.x,p.y);
    return contains(arg(cp));
  }

  void update( AngleRange ar ) {
    if( contains(ar.mini) ) {
      if( contains(ar.maxi) ) mini = ar.mini, maxi = ar.maxi;
      else                    mini = ar.mini;
    } else { 
      if(        contains(ar.maxi) ) maxi = ar.maxi;
      else  if( !ar.contains(mini) && !equals(mini,ar.mini) ) maxi = mini;
    }
    if( LT(maxi-mini,0)    ) maxi += PI2;
    if( LTE(PI2,maxi-mini) ) maxi -= PI2;
  }

};


ostream& operator << (ostream& os,const AngleRange& a){ os << "[ " << a.mini*180.0/M_PI << " , " << a.maxi*180.0/M_PI << " ]"; }

Segment reflection(Line line, Segment seg){
  return Segment(reflection(line,seg.p1),reflection(line,seg.p2));
}

double distance(Segment s,Point p1,Point p2){
  Segment t = Segment(p1,p2);
  Point cp = crosspoint(s,Line(p1,p2));
  return abs(p1-cp);
}

Point vp;
double distance2(Segment s,double rad){
  Vector e = Point(10,0);
  e = rotate(e,rad);
  Point cp = crosspoint(s,Line(vp,vp+e));
  return abs(cp-vp);
}

const int loop_limit = 100000;
void compute(Point phantom,Segment mirror1,Segment mirror2){
  

  vp = phantom;

  Point iPhantom[2] = { reflection(mirror1,phantom), reflection(mirror2,phantom) }; 
  Segment nmirror[2] = { mirror1, mirror2 };
  AngleRange range[2] = { AngleRange(phantom,mirror1), AngleRange(phantom,mirror2) };
  int cnt = 0;
  /*
    puts("------------");
    cout << "mirror1     = " << mirror1 << endl;
    cout << "nmirror[0]  = " << nmirror[0] << endl;
    cout << "iPhantom[0] = " << iPhantom[0] << endl;
    cout << "range[0]    = " << range[0] << endl;
    cout << "mirror2     = " << mirror2 << endl;
    cout << "nmirror[1]  = " << nmirror[1] << endl;
    cout << "iPhantom[1] = " << iPhantom[1] << endl;
    cout << "range[1]    = " << range[1] << endl;
  */
  int i = 0;
  while( i < loop_limit && cnt <= 100 && !( range[0].fail() && range[1].fail() ) ){
    //cout << "nmirror[0]  = " << nmirror[0] << endl;
    //cout << "nmirror[1]  = " << nmirror[1] << endl;
    //puts("");
    if( !range[0].fail() )
    if( !intersectSS(Segment(phantom,iPhantom[0]),mirror2) || !LT(distance(mirror2,phantom,iPhantom[0]),distance(mirror1,phantom,iPhantom[0])) ) {
    //if( !intersectSS(Segment(phantom,iPhantom[0]),mirror2) ) {
      if( range[0].contains(iPhantom[0]) ) {
	//cout << "iPhantom[0] success!!!" << endl;
	++cnt;
      }
    }

    if( !range[1].fail() )
     if( !intersectSS(Segment(phantom,iPhantom[1]),mirror1) || !LT(distance(mirror1,phantom,iPhantom[1]),distance(mirror2,phantom,iPhantom[1])) ) {
    //if( !intersectSS(Segment(phantom,iPhantom[1]),mirror1) ) {
      if( range[1].contains(iPhantom[1]) ) {
	//cout << "iPhantom[1] success!!!" << endl;
	++cnt;
      }
    }
    
    Segment tmp1 = reflection(mirror1,nmirror[1]);
    Segment tmp2 = reflection(mirror2,nmirror[0]);
    Point   tmp3 = reflection(mirror1,iPhantom[1]);
    Point   tmp4 = reflection(mirror2,iPhantom[0]);

    AngleRange tmpR(phantom,tmp1);
    range[0].update(tmpR);
    tmpR = AngleRange(phantom,tmp2);
    range[1].update(tmpR);

    double mid = ( range[0].mini + range[0].maxi ) / 2;
    /*
    cout << "tmp = " << tmp1 << endl;
    cout << "mir = " << nmirror[0] << endl;
    cout << distance2(tmp1,mid) << " and " << distance2(nmirror[0],mid) << endl;
    */
    if( !range[0].fail() && LT(distance2(tmp1,mid),distance2(nmirror[0],mid)) ) range[0].mini = range[0].maxi = 0;
    mid = ( range[1].mini + range[1].maxi ) / 2;
    if( !range[1].fail() && LT(distance2(tmp2,mid),distance2(nmirror[1],mid)) ) range[1].mini = range[1].maxi = 0;

    nmirror[0] = tmp1;
    nmirror[1] = tmp2;
    iPhantom[0] = tmp3;
    iPhantom[1] = tmp4;
    /*
    AngleRange tmpR(phantom,nmirror[0]);
    range[0].update(tmpR);
    tmpR = AngleRange(phantom,nmirror[1]);
    range[1].update(tmpR);
    */
    

    ++i;
    
  }
  //cout << "cnt = " << cnt << endl;
  if( cnt > 100 ) puts("TOO MANY");
  else cout << cnt << endl;
}

int main(){
  /*
  Segment s;
  cin >> s.p1.x >> s.p1.y >> s.p2.x >>s.p2.y;
  AngleRange range(Point(0,0),s);
  cout << "[" << range.mini*180.0/M_PI << "," << range.maxi*180.0/M_PI << "]" << endl;
  while(1){
    Segment t;
    cin >> t.p1.x >> t.p1.y >> t.p2.x >> t.p2.y;
    AngleRange trange(Point(0,0),t);
    cout << "* [" << trange.mini*180.0/M_PI << "," << trange.maxi*180.0/M_PI << "]" << endl;
    range.update(trange);
    cout << "= [" << range.mini*180.0/M_PI << "," << range.maxi*180.0/M_PI << "]" << endl;
  }
  return 0;
  */
  int sx,sy;
  while( cin >> sx >> sy, sx | sy ){
    Point sp = Point(sx,sy);
    Segment segs[2];
    rep(i,2) cin >> segs[i].p1.x >> segs[i].p1.y >> segs[i].p2.x >> segs[i].p2.y;
    compute(sp,segs[0],segs[1]);
  }
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 1336
final_rank: 1