Problem:
Problem H:
Top Spinning
Spinning tops are one of the most popular and the most traditional toys. Not only spinning
them, but also making one’s own is a popular enjoyment.
One of the easiest way to make a top is to cut out a certain shape from a cardboard and pierce
an axis stick through its center of mass. Professionally made tops usually have three dimensional
shapes, but in this problem we consider only two dimensional ones.
Usually, tops have rotationally symmetric shapes, such as a circle, a rectangle (with 2-fold
rotational symmetry) or a regular triangle (with 3-fold symmetry). Although such symmetries
are useful in determining their centers of mass, they are not definitely required; an asymmetric
top also spins quite well if its axis is properly pierced at the center of mass.
When a shape of a top is given as a path to cut it out from a cardboard of uniform thickness,
your task is to find its center of mass to make it spin well. Also, you have to determine whether
the center of mass is on the part of the cardboard cut out. If not, you cannot pierce the axis
stick, of course.
Input
The input consists of multiple datasets, each of which describes a counterclockwise path on a
cardboard to cut out a top. A path is indicated by a sequence of command lines, each of which
specifies a line segment or an arc.
In the description of commands below, the
current
position is the position to start the next cut,
if any. After executing the cut specified by a command, the
current position
is moved to the
end position of the cut made.
The commands given are one of those listed below. The command name starts from the first
column of a line and the command and its arguments are separated by a space. All the command
arguments are integers.
start
x
y
Specifies the start position of a path. This command itself does not specify any cutting;
it only sets the
current position
to be (
x
,
y
).
line
x y
Specifies a linear cut along a straight line from the
current position
to the position (
x
,
y
),
     which is not identical to the
current position
.
arc
x y r
Specifies a round cut along a circular arc. The arc starts from the
current position
and
     ends at (
x
,
y
), which is not identical to the
current position
. The arc has a radius of |
r
|.
     When
r
is negative, the center of the circle is to the left side of the direction of this round
     cut; when it is positive, it is to the right side (Figure 1). The absolute value of
r
is greater
     than the half distance of the two ends of the arc. Among two arcs connecting the start
     and the end positions with the specified radius, the arc specified is one with its central
     angle less than 180 degrees.
close
Closes a path by making a linear cut to the initial start position and terminates a dataset.
     If the
current position
is already at the start position, this command simply indicates the
     end of a dataset.
The figure below gives an example of a command sequence and its corresponding path. N
...(truncated)

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define LOOP 50000

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

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

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

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

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

	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

struct Circle{
	Point center;
	double r;
};

char buf[10];

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

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

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

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

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

Point project(Line l,Point p){

	Vector base = l.p[1]-l.p[0];
	double r = dot(p-l.p[0],base)/norm(base);
	return l.p[0]+base*r;
}


//円と直線の交点を求める関数
vector<Point> getCrossPoints(Circle c,Line l){

	vector<Point> ret;

	Vector pr = project(l,c.center);
	Vector e = (l.p[1]-l.p[0])/abs(l.p[1]-l.p[0]);

	double base;

	if(fabs(c.r*c.r-norm(pr-c.center)) < EPS){

		base = 0;
	}else{
		base = sqrt(c.r*c.r-norm(pr-c.center));
	}

	ret.push_back(Point(pr+e*base));
	ret.push_back(Point(pr-e*base));

	return ret;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

double calc_S(Polygon g){

	int N = g.size();
	double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -1;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector 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(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

bool isSame(Point a,Point b){

	return abs(a-b) < EPS;
}

double arg(Vector p){
	return atan2(p.y,p.x);
}

Vector polar(double a,double r){
	return Point(cos(r)*a,sin(r)*a);
}

//円と円の交点
vector<Point> getCrossPoints(Circle c1,Circle c2){

	vector<Point> res;

	double d = abs(c1.center-c2.center);
	double a = acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
	double t = arg(c2.center-c1.center);

	res.push_back(Point(c1.center+polar(c1.r,t+a)));
	res.push_back(Point(c1.center+polar(c1.r,t-a)));

	return res;
}

//点moveをbaseを中心にradラジアン回転させる
Point rotate(Point base,Point move,double rad){

	Point ret;
	move = move-base;

	ret.x = move.x*cos(rad)-move.y*sin(rad);
	ret.y = move.x*sin(rad)+move.y*cos(rad);

	ret = ret+base;

	return ret;
}

//ポリゴンの重心を求める
Point calc_center_of_gravity(Polygon P){

	Point base_p = Point(0,0);
	int N = P.size();

	Point ret = Point(0,0);
	double sum_S = 0;

	for(int i = 0; i < N; i++){

		Polygon work;
		work.push_back(P[i]);
		work.push_back(P[(i+1)%N]);
		work.push_back(base_p);

		double tmp_S = calc_S(work);

		Point tmp_center = P[i]+P[(i+1)%N]+base_p;
		tmp_center = tmp_center/3; //三角形の重心

		tmp_center = tmp_center*tmp_S;
		ret = ret+tmp_center;

		sum_S += tmp_S;
	}

	ret = ret/sum_S;

	return ret;
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}


void func(){

	bool is_first = true;
	Polygon P;

	double x,y,r;

	Point pre,next,calc_center;
	Circle C1,C2;

	while(true){
		if(is_first){ //必ずstartコマンド

			scanf("%lf %lf",&x,&y);
			P.push_back(Point(x,y));
			is_first = false;
			continue;
		}
		scanf("%s",buf);

		if(buf[0] == 'l'){

			scanf("%lf %lf",&x,&y);
			P.push_back(Point(x,y));

		}else if(buf[0] == 'a'){ //円弧命令

			scanf("%lf %lf %lf",&x,&y,&r);

			pre = P[P.size()-1];
			next = Point(x,y);

			C1.center = pre;
			C1.r = fabs(r);

			C2.center = next;
			C2.r = fabs(r);

			//pre.debug();
			//next.debug();

			vector<Point> crossV = getCrossPoints(C1,C2);

			if(r < 0){

				if(ccw(pre,next,crossV[0]) == COUNTER_CLOCKWISE){

					calc_center = crossV[0];

				}else{

					calc_center = crossV[1];
				}

			}else{ //r > 0

				if(ccw(pre,next,crossV[0]) == CLOCKWISE){

					calc_center = crossV[0];

				}else{

					calc_center = crossV[1];
				}
			}

			//printf("calc_center:");
			//calc_center.debug();

			Vector vec1 = pre-calc_center;
			Vector vec2 = next-calc_center;

			double rad = acos(dot(vec1,vec2)/(abs(vec1)*abs(vec2)));
			double base_rad = rad/LOOP;
			if(r > 0)base_rad *= -1; //時計回り

			//点preを、calc_centerの周りにLOOP回回転させる
			for(int i = 0; i < LOOP; i++){

				Point tmp_p = rotate(calc_center,pre,base_rad*(i+1));
				P.push_back(tmp_p);
			}
			P.push_back(next);

		}else if(buf[0] == 'c'){ //close

			break;
		}
	}

	Point center = calc_center_of_gravity(P);

	bool is_in = (contains(P,center) != 0);

	char ch = '-';
	if(is_in){

		ch = '+';
	}

	printf("%.10lf %.10lf %c\n",center.x,center.y,ch);
}


int main(){

	while(true){

		scanf("%s",buf);
		if(buf[0] == 'e')break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 1500
memory_kb: 33684
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double PI = acos(-1);
const double EPS = 1e-7; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

using Vec = Point;

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
// !!! 誤差に注意 !!! (掛け算したものとかなり小さいものを比べているので)
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 直線と線分
bool isecLS(Point a1, Point a2, Point b1, Point b2) {
  return cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS;
}


// 2直線の交点
Point crosspointLL(Point a1, Point a2, Point b1, Point b2) {
  double d1 = cross(b2-b1, b1-a1);
  double d2 = cross(b2-b1, a2-a1);
  if (EQ(d1, 0) && EQ(d2, 0)) return a1;  // same line
  assert(!EQ(d2, 0)); // 交点がない
  return a1 + d1/d2 * (a2-a1);
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 多角形の符号付面積
double area(const VP& ps) {
  double a = 0;
  rep (i, ps.size()) a += cross(ps[i], ps[(i+1) % ps.size()]);
  return a / 2;
}

// 多角形の幾何学的重心
Point centroid(const VP& ps) {
  int n = ps.size();
  double aSum = 0;
  Point c;
  rep (i, n) {
    double a = cross(ps[i], ps[(i+1) % n]);
    aSum += a;
    c += (ps[i] + ps[(i+1) % n]) * a;
  }
  return 1 / aSum / 3 * c;
}

// aからbへの回転角（中心(0,0)）[-pi,+pi]
double angle(Point a,Point b){
  double t = arg(b)-arg(a);
  while(t>+PI) t-=2*PI;
  while(t<-PI) t+=2*PI;
  return t;
}

bool on_arc(Point c, Point a, Point b, Point p){
    b -= c;
    a -= c;
    p -= c;
    c -= c;

    double ta = atan2(a.Y,a.X), tb = atan2(b.Y,b.X);
    while(tb - ta < 0){
        tb += 2*PI;
    }
    if(tb - ta > PI){
        swap(ta,tb);
    }
    while(tb - ta < 0){
        tb += 2*PI;
    }

    for(int i=-2; i<=2; ++i){
        double tmp = atan2(p.Y,p.X) + i*2*PI;
        if(ta-EPS<tmp && tmp<tb+EPS) return true;
    }
    return false;
}

double cb(double x){
    return x*x*x;
}

Point READ(){
    int x,y;
    cin >>x >>y;
    return Point(x,y);
}

int main(){
    string s;
    while(cin >>s, (s=="start")){
        Point start = READ();

        VP poly;
        vector<int> arc;

        poly.pb(start);
        while(cin >>s){
            if(s == "close"){
                arc.pb(0);
                break;
            }

            poly.pb(READ());

            int rr = 0;
            if(s == "arc") cin >>rr;
            arc.pb(rr);
        }

        int n = poly.size();

        // calc center of mass
        Point pg = centroid(poly);
        double poly_area = area(poly);

        Point g = poly_area*pg;
        double mm = poly_area;

        VP arc_center(n);
        rep(i,n)if(arc[i]!=0){
            Point a = poly[i], b = poly[(i+1)%n];
            Point mid = (a+b)*0.5;

            Vec v = b-a;
            Vec h = {-v.Y, v.X};
            double hsz = abs(h);
            h = {h.X/hsz, h.Y/hsz};

            double chord = abs(b-a);
            double theta = asin(chord/2/abs(arc[i]));
            double len = abs(arc[i])*cos(theta);

            // determine the center of the arc
            Point c1 = mid + len*h;
            Point c2 = mid - len*h;
            if(arc[i]<0){
                if( angle(a-c1, b-c1) > EPS) arc_center[i] = c1;
                else arc_center[i] = c2;
            }
            else{
                if( angle(a-c1, b-c1) < -EPS) arc_center[i] = c1;
                else arc_center[i] = c2;
            }

            VP cross_points = crosspointLC(arc_center[i], mid, arc_center[i], abs(arc[i]));
            for(Point tmp:cross_points){
                if(on_arc(arc_center[i], a, b, tmp)){
                    double A = arc[i]*arc[i]*(2*theta - sin(2*theta))/2;
                    double y = 2*cb(abs(arc[i]))*cb(sin(theta))/3/A;
                    Point tgp = arc_center[i] + (mid-arc_center[i])*(y/abs(mid-arc_center[i]));

                    double mul = 1;
                    if(arc[i]>0) mul = -1;
                    g += tgp*(A*mul);
                    mm += A*mul;
                    break;
                }
            }
        }
        g *= (1.0/mm);

        // is center inside?
        int yct = 0;
        for(int yy=-200; yy<=200; ++yy){

            Point GP(200, yy);
            // dbg(GP);
            VP cps;
            rep(i,n){
                Point a = poly[i], b = poly[(i+1)%n];
                if(arc[i] == 0){
                    // dbg(a);
                    // dbg(b);
                    if(isecLS(g,GP,a,b)){
                        Point cp = crosspointLL(g,GP,a,b);
                        // dbg(cp);
                        if(cp.X - g.X > 0) cps.pb(cp);
                    }
                }
                else{
                    for(Point cp:crosspointLC(g,GP,arc_center[i],abs(arc[i]))){
                        if(on_arc(arc_center[i],a,b,cp)){
                            if(cp.X - g.X > 0) cps.pb(cp);
                        }
                    }
                }
            }

            VP uniq_cps;
            for(Point p:cps){
                bool ok = true;
                for(Point q:uniq_cps){
                    if(abs(p-q)<EPS) ok = false;
                }
                if(ok) uniq_cps.pb(p);
            }
            // dbg(uniq_cps);
            if(uniq_cps.size()%2==0) ++yct;
            else --yct;
        }
        // dbg(yct);

        char inside = '+';
        if(yct>0) inside = '-';

        printf("%.10f %.10f %c\n", g.X, g.Y, inside);
    }
    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 3564
final_rank: 6

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
#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(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r) : p(p), r(r) {}
    C(){}
};

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
}

P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

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

VP crosspointCC(C a, C b){
    VP ret;
    if(a.r < b.r) swap(a,b);
    double dist = abs(b.p-a.p);
    P dir = a.r*unit(b.p-a.p);
    if(EQ(dist, a.r+b.r) || EQ(dist, a.r-b.r)){
        ret.push_back(a.p +dir);
    }else if(a.r-b.r < dist && dist < a.r+b.r){
        double cos = (a.r*a.r +dist*dist -b.r*b.r)/(2*a.r*dist);
        double sin = sqrt(1 -cos*cos);
        ret.push_back(a.p +dir*P(cos, sin));
        ret.push_back(a.p +dir*P(cos, -sin));
    }
    return ret;
}

P centroid(VP &poly){
    int n = poly.size();
    P ret = P(0, 0);
    double total = 0;
    for(int i=0; i<n; i++){
        P &curr = poly[i], &next = poly[(i+1)%n];
        ret += (curr +next) *cross(curr, next);
        total += cross(curr, next);
    }
    return ret /total /3.0;
}

int in_poly(const P &p, const VP &poly){
    int n = poly.size();
    int ret = -1;
    for(int i=0; i<n; i++){
        P a = poly[i]-p;
        P b = poly[(i+1)%n]-p;
        if(a.Y > b.Y) swap(a,b);
        if(intersectSP(L(a,b), P(0,0))) return 0;
        if(a.Y<=0 && b.Y>0 && cross(a,b)<0) ret = -ret;
    }
    return ret;
}

int main(){
    while(1){
        string s;
        cin >> s;
        if(s == "end") break;

        double x,y;
        cin >> x >> y;
        VP poly;
        poly.emplace_back(x, y);
        while(1){
            string s;
            cin >> s;
            if(s == "close") break;
            if(s == "line"){
                double x,y;
                cin >> x >> y;
                poly.emplace_back(x, y);
            }
            if(s == "arc"){
                double x,y,r;
                cin >> x >> y >> r;
                int sign = (r > 0)? -1: 1;
                P curr = poly.back(), next = P(x, y);
                C c[2] = {C(curr, abs(r)), C(next, abs(r))};
                VP cp = crosspointCC(c[0], c[1]);
                P center = (ccw(curr, next, cp[0]) == sign)? cp[0]: cp[1];
                double angle = arg((next-center) /(curr-center));
                int split = 10000;
                for(int i=1; i<=split; i++){
                    poly.push_back(center +rotate(curr -center, angle *i/split));
                }
            }
        }

        P center = centroid(poly);
        string in = (in_poly(center, poly) >= 0)? "+" :"-";
        cout << fixed << setprecision(5);
        cout << center.X << " " << center.Y << " " << in << endl;

    }
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 10396
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef complex<double> P;
typedef pair<P,P> L;

const double EPS = 1e-7;

struct Circle{
  P c;
  double r;
  Circle(P c=P(0,0), double r=0):c(c),r(r){}
};

struct Arc{
  double r, theta, area;
  P begin_p, end_p, cen;
  Arc(double r, double t, P bp, P ep, P c):r(r),theta(t),begin_p(bp),end_p(ep),cen(c){}
};

bool equal(double a, double b){ return fabs(a-b) < EPS; }

double dot(P a, P b){ return real(conj(a)*b); }

double cross(P a, P b){ return imag(conj(a)*b); }

int ccw(P a, P b, P c){
  b -= a;
  c -= a;
  if(cross(b,c) > EPS) return 1;
  if(cross(b,c) < -EPS) return -1;
  if(dot(b,c) < -EPS) return 2;
  if(norm(b) < norm(c)) return -2;
  return 0;
}

double area(vector<P> v){
  double sum = 0.0;
  int n = v.size();
  for(int i=0;i<n;i++) sum += (real(v[i]) - real(v[(i+1)%n])) * (imag(v[i]) + imag(v[(i+1)%n]));
  return fabs(sum) / 2;
};

double area(Arc ar){
  return ar.r * ar.r * (ar.theta - sin(ar.theta)) / 2.0;
}

P rotate(P p, double rad){
  double x = real(p) * cos(rad) - imag(p) * sin(rad);
  double y = real(p) * sin(rad) + imag(p) * cos(rad);
  return P(x,y);
}

bool isIntersect(L s1, L s2){
  
  if(max(real(s1.first), real(s1.second)) + EPS < min(real(s2.first), real(s2.second)) ||
     max(imag(s1.first), imag(s1.second)) + EPS < min(imag(s2.first), imag(s2.second)) ||
     max(real(s2.first), real(s2.second)) + EPS < min(real(s1.first), real(s1.second)) ||
     max(imag(s2.first), imag(s2.second)) + EPS < min(imag(s1.first), imag(s1.second))) return false;

  return ( ccw(s1.first,s1.second,s2.first) * ccw(s1.first,s1.second,s2.second) <= 0 &&
           ccw(s2.first,s2.second,s1.first) * ccw(s2.first,s2.second,s1.second) <= 0 );
}

enum {OUT, BORDER, IN};
int contains(vector<P> v, P p){ 
  bool in = false; 
  for(int i=0;i<v.size();i++){ 
    P a = v[i] - p; 
    P b = v[(i+1)%v.size()] - p; 
    if(imag(a) > imag(b)) swap(a,b); 
    if(imag(a) <= EPS && EPS < imag(b)) 
      if(cross(a,b) < -EPS) in = !in; 
    if(equal(cross(a,b), 0.0) && dot(a,b) < EPS) return 1; 
  } 
  return in ? 2 : 0; 
}

bool contains(Arc ar, P p){
  return abs(ar.cen - p) < ar.r - EPS && isIntersect(L(ar.cen, p), L(ar.begin_p, ar.end_p));
}

vector<P> getIntersectCC(Circle c1, Circle c2){
  vector<P> res;
  double r1 = c1.r, r2 = c2.r, d;
  P p1 = c1.c, p2 = c2.c;
  d = abs(p1-p2);

  if(d < EPS && abs(r1-r2) < EPS) return res;
  if(r1 + r2< d - EPS || d + EPS < abs(r1-r2)) return res;

  double a = (r1*r1 - r2*r2 + d*d) / (2*d);
  double h = sqrt(max(r1*r1 - a*a, 0.0));
  P tmp1 = p1 + a / d * (p2-p1);
  P tmp2 = h / d * (p2-p1);

  if(abs(tmp2) < EPS) res.push_back(tmp1);
  else {
    res.push_back(P(real(tmp1) - imag(tmp2), imag(tmp1) + real(tmp2)));
    res.push_back(P(real(tmp1) + imag(tmp2), imag(tmp1) - real(tmp2)));
  }
  return res;
}

P calc_g(vector<P> v){
  double a = 0;
  int n = v.size();
  P res = P(0, 0);
  for(int i=0;i<n;i++){
    double k = real(v[i]) * imag(v[(i+1)%n]) - real(v[(i+1)%n]) * imag(v[i]);
    res += k * (v[i] + v[(i+1)%n]);
    a += k;
  }
  //cout << res << ' ' << res / 3.0 << ' ' << res / 3.0 / a << endl;
  return res / 3.0 / a;
}

P calc_g(Arc ar){
  double A = ar.r * ar.r * (ar.theta - sin(ar.theta)) / 2.0;
  double y = 2.0 * ar.r * ar.r * ar.r * sin(ar.theta/2.0) * sin(ar.theta/2.0) * sin(ar.theta/2.0) / (3.0 * A);
  double theta = arg((ar.begin_p + ar.end_p) / 2.0 - ar.cen);
  
  return ar.cen + polar(y, theta);
}



vector<P> poly;
vector<Arc> ar_v;

void start(P p){
  poly.clear();
  ar_v.clear();
  poly.push_back(p);
}

void arc(P p, double r){
  bool assert_flg = false, rev_flg = false;
  Arc ar = Arc(abs(r), 0, poly[poly.size()-1], p, P());  
  vector<P> res_inter = getIntersectCC(Circle(ar.begin_p, ar.r), Circle(ar.end_p, ar.r));

  for(int i=0;i<res_inter.size();i++){
    if(ccw(ar.begin_p, ar.end_p, res_inter[i]) == -1 && r > -EPS ||
       ccw(ar.begin_p, ar.end_p, res_inter[i]) == 1 && r < EPS){
      ar.cen = res_inter[i];
      assert(!assert_flg);
      assert_flg = true;
    }
  }
  assert(assert_flg);

  
  ar.theta = arg(ar.end_p-ar.cen) - arg(ar.begin_p-ar.cen);
  while(ar.theta < -EPS) ar.theta += 2.0 * M_PI;
  if(ar.theta > M_PI + EPS) {
    ar.theta = 2.0 * M_PI - ar.theta;
    rev_flg = true;
  }

  //cout << ar.cen << endl;
  //printf("arg_en = %.5f, arg_be = %.5f, arg = %.5f\n", arg(ar.end_p-ar.cen)*180.0/M_PI, arg(ar.begin_p-ar.cen)*180.0/M_PI, ar.theta*180.0/M_PI);


  ar_v.push_back(ar);
  
  // g?????????????????£????????§?????¨????????????
  int LOOP = 3600;
  for(int i=0;i<LOOP;i++){
    if(rev_flg) poly.push_back(ar.cen + polar(ar.r, arg(ar.begin_p-ar.cen) - ar.theta * (double)i / LOOP));
    else poly.push_back(ar.cen + polar(ar.r, arg(ar.begin_p-ar.cen) + ar.theta * (double)i / LOOP));
  }  
  
  poly.push_back(p);
}

void line(P p){
  poly.push_back(p);
}

void close(){
  P ans = calc_g(poly) * area(poly);
  double sum_area = area(poly);

  for(int i=0;i<ar_v.size();i++){
    ar_v[i].area = area(ar_v[i]);
    if(contains(poly, calc_g(ar_v[i])) == IN) ar_v[i].area *= -1.0;
    //ans += calc_g(ar_v[i]) * ar_v[i].area;
    //sum_area += ar_v[i].area;
  }

  ans /= sum_area;

  if(equal(real(ans), 0.0)) ans = P(0, imag(ans));
  if(equal(imag(ans), 0.0)) ans = P(real(ans), 0);
  
  printf("%.4f %.4f ", real(ans), imag(ans));

  /*  
  for(int i=0;i<ar_v.size();i++){
    if(contains(ar_v[i], ans)){
      cout << (ar_v[i].area > EPS ? '+' : '-') << endl;
      return;
    }
  }
  */
  cout << (contains(poly, ans) == IN ? '+' : '-') << endl;
}

int main(){
  double x, y, r;
  string str;
  while(cin >> str){
    if(str == "start") {
      cin >> x >> y;
      start(P(x, y));
    }
    else if(str == "line"){
      cin >> x >> y;
      line(P(x, y));
    }
    else if(str == "arc"){
      cin >> x >> y >> r;
      arc(P(x, y), r);
    }
    else if(str == "close") close();
    else break;
  }
}
accuracy: 1
time_ms: 210
memory_kb: 5284
final_rank: 7

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	struct C : public P{
		C(){}
		C(const P& p, const R r):P(p), r(r){}
		R r;
		BOOL inside(const P& p)const { return less(norm(p-SELF), r*r);}
	};
	struct F : public C{
		R s, t;
		F(const C &c, R ss, R tt):C(c), s(ss), t(tt){
			if(PI < s) s -= 2*PI;
			if(PI < t) t -= 2*PI;
		}
		BOOL inside(const P& p)const {
			P v = p - SELF;
			if(!sig(norm(v))) return BORDER;
			R a = arg(v);
			if(t < s){
				if((!less(s, a) && !less(a, t)) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}else{
				if(!less(s, a) || !less(a, t) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		BOOL contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(S(at(i), at((i+1)%size())).online(p)) return BORDER;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return !!sig(sum);
		}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
		P gp()const {
			P r(.0, .0);
			REP(i, size()){
				const S &s = edge(i);
				r += (s[0]+s[1])*outp(s[0], s[1]);
			}
			return r / (6*area());
		}
		G convex_hull(bool online = false) {
			if(size() < 2) return *this;
			sort(ALL(*this));
			G r;
			r.resize((int)size()*2);
			int k=0;
			for(int i=0;i<size();r[k++]=at(i++))
				while(k>1 && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			int t = k;
			for(int i=(int)size()-1;i>=0;r[k++]=at(i--))
				while(k>t && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			r.resize(k-1);
			return r;
		}
		G cut(const L &l)const {
			G g;
			REP(i, size()){
				const S &s = edge(i);
				if(ccw(l[0], l[1], s[0], 0) >= 0) g.push_back(s[0]);
				if(ccw(l[0], l[1], s[0], 0) * ccw(l[0], l[1], s[1], 0) < 0)
					g.push_back(crosspoint(s, l));
			}
			return g;
		}
		G Voronoi(const vector<P> &p, const int t)const {
			G g = *this;
			REP(i, p.size())if(i!=t){
				const P m = (p[t]+p[i])*0.5;
				g = g.cut(L(m, m+(p[i]-p[t])*P(0, 1)));
			}
			return g;
		}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return 2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	R dist2(const L &l, const P &p){return norm(outp(l.dir(), p - l[0])) / norm(l.dir());}
	R dist2(const S &s, const P &p){
		if(inp(p-s[0],  s.dir()) < EPS) return norm(p - s[0]);
		if(inp(p-s[1], -s.dir()) < EPS) return norm(p - s[1]);
		return dist2((const L &)s, p);
	}
	R dist2(const S &s, const L &l){
		return intersect(s, l) ? .0 : min(dist2(l, s[0]), dist2(l, s[1]));
	}
	R dist2(const S &s, const S &t){
		return intersect(s, t) ? .0 : min(min(dist2(s, t[0]), dist2(t, s[0])), 
									   	  min(dist2(s, t[1]), dist2(t, s[1])));
	}
	template <class T> R dist2(const G &g, const T& t){ // todo: 内部に完全に含まれる場合
		R res = INF;
		REP(i, g.size()) res = min(res, dist2(g.edge(i), t));
		return res;
	}
	template<class S, class T> R dist(const S& s, const T& t){return sqrt(dist2(s, t));}
	inline BOOL intersect(const C &a, const C &b){
		return less((a.r-b.r)*(a.r-b.r), norm(a-b)) + less(norm(a-b), (a.r+b.r)*(a.r+b.r)) - 1;
	}
	inline BOOL intersect(const C &c, const L &l){
		return less(dist2(l, c), c.r*c.r);
	}
	inline BOOL intersect(const C &c, const S &s){
		int d = less(dist2(s, c), c.r*c.r);
		if(d != TRUE) return d;
		int p = c.inside(s[0]), q = c.inside(s[1]);
		return (p<0 || q<0) ? BORDER : p&q;
	}
	
	/*
	 * CCWでs[0]->s[1]にかけてが共通部分
	 */
	inline S crosspoint(const C &c1, const C &c2){
		if(!intersect(c1, c2)) return S();
		R d = abs(c1 - c2);
		R x = (c1.r*c1.r - c2.r*c2.r + d*d) / (2*d);
		R h = sqrt(max(0., c1.r*c1.r - x*x));
		P u = unit(c2-c1);
		return S(c1 + u*x + u*P(0,-1)*h, c1 + u*x + u*P(0,1)*h);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
		return m[0] + B / A * (m[1] - m[0]);
	}
	inline S crosspoint(const C &c, const L &l){
		R d2 = dist2(l, c);
		if(c.r*c.r+EPS < d2) return S();
		P m = proj(c, l);
		P u = unit(l[1]-l[0]);
		R d = sqrt(max(.0, c.r*c.r - d2));
		return S(m+u*d, m-u*d);
	}
	inline vector<P> crosspoint(const C &c, const S &s){
		vector<P> res = crosspoint(c, (const L&)s);
		RREP(i, res.size()){
			if(inp(res[i]-s[0], s.dir())*inp(res[i]-s[1], -s.dir())<EPS)
				res.erase(res.begin() + i);
		}
		return res;
	}
	inline R commonarea(const C &a, const C &b){
		if(less(norm(a-b), (a.r-b.r)*(a.r-b.r)) == TRUE) return min(a.r*a.r, b.r*b.r)*PI;
		if(less((a.r+b.r)*(a.r+b.r), norm(a-b)) == TRUE) return .0;
		double d = abs(a-b);
		double rc = (d*d + a.r*a.r - b.r*b.r) / (2*d);
		double theta = acos(rc / a.r);
		double phi = acos((d - rc) / b.r);
		return a.r*a.r*theta + b.r*b.r*phi - d*a.r*sin(theta);
	}
	vector<L> CommonTangent(C c1, C c2){
		if(c1.r > c2.r) swap(c1, c2);
		double d = abs(c1-c2);
		vector<L> res;
		if(d < EPS) return res;
		if(d + EPS > c1.r + c2.r){
			// 内接線
			P crs = (c1*c2.r + c2*c1.r) / (c1.r + c2.r);
			double rad = asin(c1.r/abs(crs-c1));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., rad)));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., -rad)));
		}
		if(c1.r + d + EPS > c2.r){
			// 外接線
			double rad = 0.5*PI+asin((c2.r-c1.r) / d);
			P v = unit(c2-c1)*polar(1., rad);
			if(c1.r + d - EPS < c2.r){
				res.push_back(L(c1+v*c1.r, c1+v*c1.r+(c1-c2)*P(0, 1)));
			}else{
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
				v = 2.*proj(v, c2-c1) - v;
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
			}
		}
		return res;
	}
	
	struct min_ball {
		P center;
		R radius2;
		min_ball(const vector<P>& p) {
			FOR(it, p) ps.push_back(*it);
		}
		min_ball& compile() {
			m = 0;
			center = P(0, 0);
			radius2 = -1;
			make_ball(ps.end());
			return *this;
		}
	private:
		list<P> ps;
		list<P>::iterator supp_end;
		int m;
		P v[3], c[3];
		R z[3], r[3];
		void pop() { --m; }
		void push(const P& p) {
			if (m == 0) {
				c[0] = p; r[0] = 0;
			} else {
				R e = norm(p-c[m-1]) - r[m-1];
				P delta = p - c[0];
				v[m] = p - c[0];
				for (int i = 1; i < m; ++i)
					v[m] -= v[i] * inp(v[i], delta) / z[i];
				z[m] = inp(v[m], v[m]);
				c[m] = c[m-1] + e*v[m]/z[m]*.5;
				r[m] = r[m-1] + e*e/z[m]*.25;
			}
			center	= c[m];
			radius2 = r[m]; ++m;
		}
		void make_ball(list<P>::iterator i) {
			supp_end = ps.begin();
			if (m == 3) return;
			for (list<P>::iterator k = ps.begin(); k != i; ) {
				list<P>::iterator j = k++;
				if (norm(*j-center) > radius2) {
					push(*j); make_ball(j); pop();
					move_to_front(j);
				}
			}
		}
		void move_to_front(list<P>::iterator j) {
			if (supp_end == j) ++supp_end;
			ps.splice (ps.begin(), ps, j);
		}
	};
	
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
/*
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		UnionFind uf;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()),uf(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
			uf.unionSet(s, t);
		}
		vector<G> poly;
		
		void add_polygon(int s, int t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			e->l = t;
			poly[t].push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		
		void toSpanningTree(){
			vector<pair<R, pii>> e;
			REP(i, n)REP(j, i)if(!uf.findSet(i, j))
				e.emplace_back(norm(p[i]-p[j]), pii(i, j));
			sort(ALL(e));
			REP(ii, e.size()){
				const int i = e[ii].second.first;
				const int j = e[ii].second.second;
				if(uf.findSet(i, j)) continue;
				const S s(p[i], p[j]);
				if([&](){
					REP(k, n)if(i!=k&&j!=k){
						FOR(it, g[k])
						if(intersect(s, S(p[k], p[it->v])) == TRUE) return 0;
					}
					return 1;
				}()) add_edge(i, j);
			}
		}
		
		vector<vi> dual(){
			toSpanningTree();
			
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			poly.emplace_back();
			add_polygon(s, poly.size()-1, -PI*.5);
			REP(i, n)REP(j, g[i].size())if(!g[i][j].f){
				poly.emplace_back();
				add_polygon(i, poly.size()-1, g[i][j].a+2.*EPS);
			}
			int m = poly.size();
			vector<vi> dg(m);
			vector<unordered_map<int, int>> rev(n);
			REP(i, n)REP(j, g[i].size()){
				int u = i, v = g[i][j].v, l = g[i][j].l;
				if(u>v) swap(u, v);
				if(rev[u].find(v) != rev[u].end()){
					if(l != rev[u][v]){
						dg[l].push_back(rev[u][v]);
						dg[rev[u][v]].push_back(l);
					}
				}
				else rev[u][v] = l;
			}
			REP(i, m){
				sort(ALL(dg[i]));
				UNIQUE(dg[i]);
			}
			return dg;
		}
	};
*/
#undef SELF
#undef at
}

using namespace geom;

int f = 0;
namespace std{
	bool operator<(const P &a, const P &b){return sig(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;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
	istream& operator>>(istream &is, L &l){l.resize(2);return is >> l[0] >> l[1];}
	istream& operator>>(istream &is, C &c){return is >> (P &)c >> c.r;}
	const double B = 200;
	const double Z = 80;
	ostream& operator<<(ostream &os, const C &c){return os << "circle("<<B+Z*(c.X)<<", "<<1000-B-Z*(c.Y)<<", "<<Z*(c.r)<<")";}
	ostream& operator<<(ostream &os, const P &p){return os << C(p, 2./Z);}
	ostream& operator<<(ostream &os, const S &s){return os << "line("<<B+Z*(s[0].X)<<", "<<1000-B-Z*(s[0].Y)<<", "<<B+Z*(s[1].X)<<", "<<1000-B-Z*(s[1].Y)<<")";}
	ostream& operator<<(ostream &os, const G &g){REP(i, g.size()) cout << g.edge(i) << endl;return os;}

}

int n;

const int BL = 100;

int main(){
	ios::sync_with_stdio(false);
	string com;
	while(1){
		P prev;
		G g;
		while(cin >> com, com != "close"){
			if(com == "end") return 0;
			if(com == "arc"){
				C c;
				cin >> c;
				P ort(0., c.r < 0 ? 1. : -1.);
				R r = sqrt(max(0., c.r*c.r - norm((c-prev)*.5)));
				P b = .5*(prev+c) + unit(c-prev)*ort*r;
				R s = arg(prev - b);
				R t = arg(c - b);
				if(t-s > PI) s += 2*PI;
				if(s-t > PI) t += 2*PI;
				REPS(i, BL-1){
					R m = (i*t + (BL-i)*s) / BL;
					g.push_back(b + polar(abs(c.r), m));
				}
				prev = c;
			}else{
				cin >> prev;
			}
			g.push_back(prev);
		}
		P gp = g.gp();
		printf("%.10f %.10f %c\n", gp.X, gp.Y, g.contains(gp) ? '+' : '-');
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1460
final_rank: 1

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	struct C : public P{
		C(){}
		C(const P& p, const R r):P(p), r(r){}
		R r;
		BOOL inside(const P& p)const { return less(norm(p-SELF), r*r);}
	};
	struct F : public C{
		R s, t;
		F(const C &c, R ss, R tt):C(c), s(ss), t(tt){
			if(PI < s) s -= 2*PI;
			if(PI < t) t -= 2*PI;
		}
		BOOL inside(const P& p)const {
			P v = p - SELF;
			if(!sig(norm(v))) return BORDER;
			R a = arg(v);
			if(t < s){
				if((!less(s, a) && !less(a, t)) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}else{
				if(!less(s, a) || !less(a, t) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		BOOL contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(S(at(i), at((i+1)%size())).online(p)) return BORDER;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return !!sig(sum);
		}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
		P gp()const {
			P r(.0, .0);
			REP(i, size()){
				const S &s = edge(i);
				r += (s[0]+s[1])*outp(s[0], s[1]);
			}
			return r / (6*area());
		}
		G convex_hull(bool online = false) {
			if(size() < 2) return *this;
			sort(ALL(*this));
			G r;
			r.resize((int)size()*2);
			int k=0;
			for(int i=0;i<size();r[k++]=at(i++))
				while(k>1 && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			int t = k;
			for(int i=(int)size()-1;i>=0;r[k++]=at(i--))
				while(k>t && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			r.resize(k-1);
			return r;
		}
		G cut(const L &l)const {
			G g;
			REP(i, size()){
				const S &s = edge(i);
				if(ccw(l[0], l[1], s[0], 0) >= 0) g.push_back(s[0]);
				if(ccw(l[0], l[1], s[0], 0) * ccw(l[0], l[1], s[1], 0) < 0)
					g.push_back(crosspoint(s, l));
			}
			return g;
		}
		G Voronoi(const vector<P> &p, const int t)const {
			G g = *this;
			REP(i, p.size())if(i!=t){
				const P m = (p[t]+p[i])*0.5;
				g = g.cut(L(m, m+(p[i]-p[t])*P(0, 1)));
			}
			return g;
		}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return 2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	R dist2(const L &l, const P &p){return norm(outp(l.dir(), p - l[0])) / norm(l.dir());}
	R dist2(const S &s, const P &p){
		if(inp(p-s[0],  s.dir()) < EPS) return norm(p - s[0]);
		if(inp(p-s[1], -s.dir()) < EPS) return norm(p - s[1]);
		return dist2((const L &)s, p);
	}
	R dist2(const S &s, const L &l){
		return intersect(s, l) ? .0 : min(dist2(l, s[0]), dist2(l, s[1]));
	}
	R dist2(const S &s, const S &t){
		return intersect(s, t) ? .0 : min(min(dist2(s, t[0]), dist2(t, s[0])), 
									   	  min(dist2(s, t[1]), dist2(t, s[1])));
	}
	template <class T> R dist2(const G &g, const T& t){ // todo: 内部に完全に含まれる場合
		R res = INF;
		REP(i, g.size()) res = min(res, dist2(g.edge(i), t));
		return res;
	}
	template<class S, class T> R dist(const S& s, const T& t){return sqrt(dist2(s, t));}
	inline BOOL intersect(const C &a, const C &b){
		return less((a.r-b.r)*(a.r-b.r), norm(a-b)) + less(norm(a-b), (a.r+b.r)*(a.r+b.r)) - 1;
	}
	inline BOOL intersect(const C &c, const L &l){
		return less(dist2(l, c), c.r*c.r);
	}
	inline BOOL intersect(const C &c, const S &s){
		int d = less(dist2(s, c), c.r*c.r);
		if(d != TRUE) return d;
		int p = c.inside(s[0]), q = c.inside(s[1]);
		return (p<0 || q<0) ? BORDER : p&q;
	}
	
	/*
	 * CCWでs[0]->s[1]にかけてが共通部分
	 */
	inline S crosspoint(const C &c1, const C &c2){
		if(!intersect(c1, c2)) return S();
		R d = abs(c1 - c2);
		R x = (c1.r*c1.r - c2.r*c2.r + d*d) / (2*d);
		R h = sqrt(max(0., c1.r*c1.r - x*x));
		P u = unit(c2-c1);
		return S(c1 + u*x + u*P(0,-1)*h, c1 + u*x + u*P(0,1)*h);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
		return m[0] + B / A * (m[1] - m[0]);
	}
	inline S crosspoint(const C &c, const L &l){
		R d2 = dist2(l, c);
		if(c.r*c.r+EPS < d2) return S();
		P m = proj(c, l);
		P u = unit(l[1]-l[0]);
		R d = sqrt(max(.0, c.r*c.r - d2));
		return S(m+u*d, m-u*d);
	}
	inline vector<P> crosspoint(const C &c, const S &s){
		vector<P> res = crosspoint(c, (const L&)s);
		RREP(i, res.size()){
			if(inp(res[i]-s[0], s.dir())*inp(res[i]-s[1], -s.dir())<EPS)
				res.erase(res.begin() + i);
		}
		return res;
	}
	inline R commonarea(const C &a, const C &b){
		if(less(norm(a-b), (a.r-b.r)*(a.r-b.r)) == TRUE) return min(a.r*a.r, b.r*b.r)*PI;
		if(less((a.r+b.r)*(a.r+b.r), norm(a-b)) == TRUE) return .0;
		double d = abs(a-b);
		double rc = (d*d + a.r*a.r - b.r*b.r) / (2*d);
		double theta = acos(rc / a.r);
		double phi = acos((d - rc) / b.r);
		return a.r*a.r*theta + b.r*b.r*phi - d*a.r*sin(theta);
	}
	vector<L> CommonTangent(C c1, C c2){
		if(c1.r > c2.r) swap(c1, c2);
		double d = abs(c1-c2);
		vector<L> res;
		if(d < EPS) return res;
		if(d + EPS > c1.r + c2.r){
			// 内接線
			P crs = (c1*c2.r + c2*c1.r) / (c1.r + c2.r);
			double rad = asin(c1.r/abs(crs-c1));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., rad)));
			res.push_back(L(crs, crs + (c1-crs)*polar(1., -rad)));
		}
		if(c1.r + d + EPS > c2.r){
			// 外接線
			double rad = 0.5*PI+asin((c2.r-c1.r) / d);
			P v = unit(c2-c1)*polar(1., rad);
			if(c1.r + d - EPS < c2.r){
				res.push_back(L(c1+v*c1.r, c1+v*c1.r+(c1-c2)*P(0, 1)));
			}else{
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
				v = 2.*proj(v, c2-c1) - v;
				res.push_back(L(c1+v*c1.r, c2+v*c2.r));
			}
		}
		return res;
	}
	
	struct min_ball {
		P center;
		R radius2;
		min_ball(const vector<P>& p) {
			FOR(it, p) ps.push_back(*it);
		}
		min_ball& compile() {
			m = 0;
			center = P(0, 0);
			radius2 = -1;
			make_ball(ps.end());
			return *this;
		}
	private:
		list<P> ps;
		list<P>::iterator supp_end;
		int m;
		P v[3], c[3];
		R z[3], r[3];
		void pop() { --m; }
		void push(const P& p) {
			if (m == 0) {
				c[0] = p; r[0] = 0;
			} else {
				R e = norm(p-c[m-1]) - r[m-1];
				P delta = p - c[0];
				v[m] = p - c[0];
				for (int i = 1; i < m; ++i)
					v[m] -= v[i] * inp(v[i], delta) / z[i];
				z[m] = inp(v[m], v[m]);
				c[m] = c[m-1] + e*v[m]/z[m]*.5;
				r[m] = r[m-1] + e*e/z[m]*.25;
			}
			center	= c[m];
			radius2 = r[m]; ++m;
		}
		void make_ball(list<P>::iterator i) {
			supp_end = ps.begin();
			if (m == 3) return;
			for (list<P>::iterator k = ps.begin(); k != i; ) {
				list<P>::iterator j = k++;
				if (norm(*j-center) > radius2) {
					push(*j); make_ball(j); pop();
					move_to_front(j);
				}
			}
		}
		void move_to_front(list<P>::iterator j) {
			if (supp_end == j) ++supp_end;
			ps.splice (ps.begin(), ps, j);
		}
	};
	
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
/*
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		UnionFind uf;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()),uf(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
			uf.unionSet(s, t);
		}
		vector<G> poly;
		
		void add_polygon(int s, int t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			e->l = t;
			poly[t].push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		
		void toSpanningTree(){
			vector<pair<R, pii>> e;
			REP(i, n)REP(j, i)if(!uf.findSet(i, j))
				e.emplace_back(norm(p[i]-p[j]), pii(i, j));
			sort(ALL(e));
			REP(ii, e.size()){
				const int i = e[ii].second.first;
				const int j = e[ii].second.second;
				if(uf.findSet(i, j)) continue;
				const S s(p[i], p[j]);
				if([&](){
					REP(k, n)if(i!=k&&j!=k){
						FOR(it, g[k])
						if(intersect(s, S(p[k], p[it->v])) == TRUE) return 0;
					}
					return 1;
				}()) add_edge(i, j);
			}
		}
		
		vector<vi> dual(){
			toSpanningTree();
			
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			poly.emplace_back();
			add_polygon(s, poly.size()-1, -PI*.5);
			REP(i, n)REP(j, g[i].size())if(!g[i][j].f){
				poly.emplace_back();
				add_polygon(i, poly.size()-1, g[i][j].a+2.*EPS);
			}
			int m = poly.size();
			vector<vi> dg(m);
			vector<unordered_map<int, int>> rev(n);
			REP(i, n)REP(j, g[i].size()){
				int u = i, v = g[i][j].v, l = g[i][j].l;
				if(u>v) swap(u, v);
				if(rev[u].find(v) != rev[u].end()){
					if(l != rev[u][v]){
						dg[l].push_back(rev[u][v]);
						dg[rev[u][v]].push_back(l);
					}
				}
				else rev[u][v] = l;
			}
			REP(i, m){
				sort(ALL(dg[i]));
				UNIQUE(dg[i]);
			}
			return dg;
		}
	};
*/
#undef SELF
#undef at
}

using namespace geom;

int f = 0;
namespace std{
	bool operator<(const P &a, const P &b){return sig(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;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
	istream& operator>>(istream &is, L &l){l.resize(2);return is >> l[0] >> l[1];}
	istream& operator>>(istream &is, C &c){return is >> (P &)c >> c.r;}
	const double B = 200;
	const double Z = 80;
	ostream& operator<<(ostream &os, const C &c){return os << "circle("<<B+Z*(c.X)<<", "<<1000-B-Z*(c.Y)<<", "<<Z*(c.r)<<")";}
	ostream& operator<<(ostream &os, const P &p){return os << C(p, 2./Z);}
	ostream& operator<<(ostream &os, const S &s){return os << "line("<<B+Z*(s[0].X)<<", "<<1000-B-Z*(s[0].Y)<<", "<<B+Z*(s[1].X)<<", "<<1000-B-Z*(s[1].Y)<<")";}
	ostream& operator<<(ostream &os, const G &g){REP(i, g.size()) cout << g.edge(i) << endl;return os;}

}

int n;

const int BL = 300;

int main(){
	ios::sync_with_stdio(false);
	string com;
	while(1){
		P prev;
		G g;
		while(cin >> com, com != "close"){
			if(com == "end") return 0;
			if(com == "arc"){
				C c;
				cin >> c;
				P ort(0., c.r < 0 ? 1. : -1.);
				R r = sqrt(max(0., c.r*c.r - norm((c-prev)*.5)));
				P b = .5*(prev+c) + unit(c-prev)*ort*r;
				R s = arg(prev - b);
				R t = arg(c - b);
				if(t-s > PI) s += 2*PI;
				if(s-t > PI) t += 2*PI;
				REPS(i, BL-1){
					R m = (i*t + (BL-i)*s) / BL;
					g.push_back(b + polar(abs(c.r), m));
				}
				prev = c;
			}else{
				cin >> prev;
			}
			g.push_back(prev);
		}
		P gp = g.gp();
		printf("%.10f %.10f %c\n", gp.X, gp.Y, g.contains(gp) ? '+' : '-');
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1524
final_rank: 3

code_snippet: #include <iostream>
#include <complex>
#include <cmath>
#include <vector>
#include <cstdio>
using namespace std;

typedef complex<double> P;

double cross(const P &a, const P &b){
	return a.real() * b.imag() - a.imag() * b.real();
}

vector<P> intersect(const P &p1, const P &p2, double r){
	double d = abs(p2 - p1);
	double phi = arg(p2 - p1);
	double theta = acos(0.5 * d / r);
	
	vector<P> ret(2);

	ret[0] = p1 + polar(r, phi + theta);
	ret[1] = p1 + polar(r, phi - theta);
	return ret;
}

bool contains(const vector<P> &plg, const P &pt){
	int cnt = 0;
	double y = imag(pt);

	for(int i = 0; i < plg.size(); ++i){
		int j = (i + 1 == plg.size() ? 0: i + 1);

		double dyi = imag(plg[i]) - y;
		double dyj = y - imag(plg[j]);
		double tx = (dyi * real(plg[j]) + dyj * real(plg[i])) / (dyi + dyj);

		if(imag(plg[i]) >= y && imag(plg[j]) < y){
			if( tx < real(pt) ) ++cnt;
		}
		else if(imag(plg[i]) < y && imag(plg[j]) >= y){
			if( tx < real(pt) ) ++cnt;
		}
	}
	
	return (cnt % 2 != 0);
}

P centroid(const vector<P> &p){
	double sum = 0.0;
	P c;
	int n = p.size();

	for(int i = 0; i < n; ++i){
		int next = (i + 1) % n;

		double crs = cross(p[i], p[next]);
		c += (p[i] + p[next]) * crs;
		sum += crs;
	}
	
	return c / (3.0 * sum);
}

int main(){
	double pi = acos(-1.0);

	vector<P> pt;
	pt.reserve(102000);
	
	string type;
	double x, y, r;

	while( cin >> type, type[0] != 'e' ){
		pt.clear();
		
		cin >> x >> y;
		pt.push_back( P(x, y) );

		while( cin >> type, type[0] != 'c' ){
			if( type[0] == 'l' ){
				cin >> x >> y;
				pt.push_back( P(x, y) );
			}
			else{
				cin >> x >> y >> r;
				double absr = abs(r);
				
				P p(x, y);
				vector<P> intr = intersect(pt.back(), p, absr);

				P c;
				double crs = cross(p - pt.back(), intr[0] - pt.back());
				if( (r < 0) == (crs > 0) ){
					c = intr[0];
				}
				else{
					c = intr[1];
				}

				double arg1 = arg(pt.back() - c);
				double arg2 = arg(p - c);
				if( arg1 > arg2 + pi ){	arg2 += 2.0 * pi;	}
				else if( arg2 > arg1 + pi ){	arg1 += 2.0 * pi;	}

				double darg = arg2 - arg1;
				for(int j = 1; j <= 1000; ++j){
					pt.push_back( c + polar(absr, arg1 + j * 0.001 * darg ) );
				}
			}
		}
		
		P cent = centroid(pt);
		bool cont = contains(pt, cent);
		
		printf("%f %f %c\n", cent.real(), cent.imag(), cont ? '+' : '-' );
	}
}
accuracy: 1
time_ms: 10
memory_kb: 1536
final_rank: 2

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

#include <complex>

typedef complex<double> Point;
typedef vector<Point> Polygon;

//static const double EPS = 1e-8;
static const double INF = 1e+10;

#define CURR(P, i) (P[i])
#define NEXT(P, i) (P[(i + 1) % P.size()])

struct Line : public vector<Point> {
  Line() {;}
  Line(Point a, Point b) { push_back(a); push_back(b); }
};

struct Circle {
  Point p;
  double r;
  Circle() {;}
  Circle(Point p, double r) : p(p), r(r) {;}
};


// usage:
// g++ -Wall -Dvisualize hoge.cpp
// ./a.out 2> data.js
// firefox Visualize.html
int zoom = 10;
#ifdef visualize
void ChangeColor(int r, int g, int b) {
  fprintf(stderr, "c.strokeStyle = 'rgb(%d, %d, %d)';\n", r, g, b);
}
void DrawPoint(const Point &p) {
  fprintf(stderr, "fillRect(%d, %d, %d, %d)\n",
      (int)(zoom*(p.real()-2)) + 1000, 1980-(int)(zoom*(p.imag() - 2)) - 1000,
      (int)(zoom*(p.real()+2)) + 1000, 1980-(int)(zoom*(p.imag() + 2)) - 1000);
}
void DrawLine(const Line &l) {
  fprintf(stderr, "line(%d, %d, %d, %d)\n",
      (int)(zoom*l[0].real()) + 1000, 1980-(int)(zoom*l[0].imag()) - 1000,
      (int)(zoom*l[1].real()) + 1000, 1980-(int)(zoom*l[1].imag()) - 1000);
}
void DrawPolygon(const Polygon &p) {
  const int n = p.size();
  for (int i = 0; i < n; i++) {
    DrawLine(Line(p[i], p[(i + 1) % n]));
  }
}
void DrawCircle(const Circle &c) {
  fprintf(stderr, "circle(%d, %d, %d)\n",
      (int)(zoom * c.p.real()) + 1000, 1980 - (int)(zoom * c.p.imag()) - 1000, (int)(zoom * c.r));
}
#else
void DrawPoint(const Point &p) {;}
void ChangeColor(int r, int g, int b) {;}
void DrawLine(Line l) {;}
void DrawPolygon(const Polygon &p) {;}
void DrawCircle(Circle c) {;}
#endif
//--------------------------------

namespace std {
  bool operator<(const Point &lhs, const Point &rhs) {
    return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real();
  }
}

inline double cross(const Point &a, const Point &b) {
  return imag(conj(a) * b);
}

inline double dot(const Point &a, const Point &b) {
  return real(conj(a) * b);
}

inline int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (cross(b, c) > 0) { return 1; }
  if (cross(b, c) < 0) { return -1; }
  if (dot(b, c) < 0) { return 2; }
  if (norm(b) < norm(c)) { return -2; }
  return 0;
}

enum { OUT, ON, IN };
int Contains(const Polygon& P, const Point& p) {
  bool in = false;
  for (int i = 0; i < (int)P.size(); ++i) {
    Point a = CURR(P,i) - p, b = NEXT(P,i) - p;
    if (imag(a) > imag(b)) swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b))
      if (cross(a, b) < 0) in = !in;
    if (cross(a, b) == 0 && dot(a, b) <= 0) return ON;
  }
  return in ? IN : OUT;
}

Point mass(const Polygon &p) {
  const int n = p.size();
  double weight = 0.0;
  Point g = Point(0.0, 0.0);
  REP(i, n) {
    Point lg = (CURR(p, i) + NEXT(p, i)) / 3.0;
    double w = cross(CURR(p, i), NEXT(p, i));
    g += lg * w;
    weight += w;
  }
  Point ret = g / weight;
  return ret;
}


Polygon poly;
char str[1000];

int main(int argc, char *argv[]) {
  if (argc > 1) { zoom = atoi(argv[1]); }
  double x, y;
  while (scanf("%s %lf %lf", str, &x, &y), str[0] != 'e') {
    poly.clear();
    poly.push_back(Point(x, y));
    while (true) {
      scanf("%s", str);
      if (str[0] == 'a') {
        double r;
        scanf("%lf %lf %lf", &x, &y, &r);
        Point c = Point(x + poly.back().real(), y + poly.back().imag()) / 2.0;
        Point vect = Point(x - poly.back().real(), y - poly.back().imag());
        vect /= abs(vect);
        vect *= Point(0, 1);
        int s = r > 0 ? 1 : -1;
        double l = abs(c- Point(x, y));
        double d = sqrt(r * r - l * l);
        d *= -s;
        Point center = c + vect * d;
        double arg1 = arg(poly.back() - center);
        double arg2 = arg(Point(x, y) - center);
        //cout << center << endl;
        if (r < 0 && arg2 < arg1) { arg2 += 2 * PI; }
        if (r > 0 && arg2 > arg1) { arg2 -= 2 * PI; }
        for (double theta = arg1; min(arg1, arg2) <= theta && theta <= max(arg1, arg2); theta += 0.001 * -s) {
          Point p = center + Point(cos(theta), sin(theta)) * abs(r);
          poly.push_back(p);
        }
        poly.push_back(Point(x, y));
      } else if (str[0] == 'l') {
        scanf("%lf %lf", &x, &y);
        poly.push_back(Point(x, y));
      } else if (str[0] == 'c') {
        break;
      }
    }
    Point p = mass(poly);
    ChangeColor(0, 0, 0);
    DrawPolygon(poly);
    ChangeColor(255, 0, 0);
    DrawPoint(p);
    if (Contains(poly, p) == OUT) {
      printf("%.8f %.8f -\n", p.real(), p.imag());
    } else {
      printf("%.8f %.8f +\n", p.real(), p.imag());
    }
  }
}
accuracy: 1
time_ms: 30
memory_kb: 1564
final_rank: 4

code_snippet: #include<iostream>
#include<cassert>
#include<algorithm>
#include<cmath>
#include<complex>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define pb         push_back
#define mp         make_pair

typedef complex<double> P;

const double eps = 1e-12;
const double pi  = acos(-1);

double cross(P a,P b){
  return a.real()*b.imag()-a.imag()*b.real();
}

double dot(P a,P b){
  return a.real()*b.real()+a.imag()*b.imag();
}

pair<P,P> CC_intersection(P a,P b,double r1,double r2){
  double l,m,n;
  double d = abs(a-b);
  double x,y;
  double p,q;
  l=(d*d-r2*r2+r1*r1)/(2*d);
  
  x=a.real()+(b.real()-a.real())*l/d;
  y=a.imag()+(b.imag()-a.imag())*l/d;
  
  n=sqrt(r1*r1-l*l);
  
  p=(b.imag()-a.imag())/d*n;
  q=(b.real()-a.real())/d*n;
  
  return mp(P(x+p,y-q),P(x-p,y+q));
}

const int CUT = 10000;
void compute_arg(P cur,P next,P circle,vector<P> &gon){
  double argA=arg(cur -circle);
  double argB=arg(next-circle);
  if (max(argA,argB)-min(argA,argB)>pi){
    if (argA<0)argA+=2*pi;
    else       argB+=2*pi;
  }
  double dif=(argB-argA)/(double)CUT;
  double cosx=cos(dif),sinx=sin(dif);
  P now=cur-circle;
  rep(i,CUT){
    double tx=cosx*now.real()-sinx*now.imag();
    double ty=sinx*now.real()+cosx*now.imag();

    now.real()=tx;
    now.imag()=ty;
    
    gon.pb(circle+now);
  }
}

P compute_centeroid(vector<P> &in,int n){
  double cx=0,cy=0;//center
  double a=0;//area of polygon
  rep(i,n){
    double cr=cross(in[i],in[(i+1)%n]);
    a+=cr;
    cx+=(in[i].real()+in[(i+1)%n].real())*cr;
    cy+=(in[i].imag()+in[(i+1)%n].imag())*cr;
  }
  a/=2.0;
  //  if (a < 0)a*=-1;//may be don't need
  cx/=(6.0*a);
  cy/=(6.0*a);
  return P(cx,cy);
}

double distance_ls_p(P a,P b,P c){
  if (dot(b-a,c-a)<eps)return abs(c-a);
  if (dot(a-b,c-b)<eps)return abs(c-b);
  return abs(cross(b-a,c-a))/abs(b-a);
}

void solve(double sx,double sy){
  vector<P> gon;
  gon.pb(P(sx,sy));
  string order;
  P cur(sx,sy);
  while(true){
    cin>>order;
    if (order == "line"){
      P next;
      cin>>next.real()>>next.imag();
      gon.pb(next);
      cur=next;
    }else if (order == "arc"){
      P next;
      double r;
      cin>>next.real()>>next.imag()>>r;
      pair<P,P> tmp=CC_intersection(cur,next,fabs(r),fabs(r));
      if (r < 0){
	if (cross(next-cur,tmp.first-cur)>0)compute_arg(cur,next,tmp.first ,gon);
	else                                compute_arg(cur,next,tmp.second,gon);
      }else if (r > 0){
	if (cross(next-cur,tmp.first-cur)<0)compute_arg(cur,next,tmp.first ,gon);
	else                                compute_arg(cur,next,tmp.second,gon);
      }
      cur=next;
    }else if (order == "close"){
      if (abs(gon[0]-gon[gon.size()-1])<eps)gon.erase(gon.begin()+gon.size()-1);
      //else gon.pb(gon[0]);
      break;
    }
  }

  P ans=compute_centeroid(gon,gon.size());


  
  int index = -1;
  double dist = 1e100;
  int n=gon.size();
  rep(i,gon.size()){
    double tmp = distance_ls_p(gon[i],gon[(i+1)%n],ans);
    if (tmp < dist){
      index=i;
      dist=tmp;
    }
  }

  char out;
  if (cross(gon[(index+1)%n]-gon[index],ans-gon[index])<-eps)out='-';
  else out='+';

  printf("%.4lf %.4lf %c\n",ans.real(),ans.imag(),out);
}

main(){
  string in;
  double sx,sy;
  while(cin>>in && in != "end"){
    cin>>sx>>sy;
    solve(sx,sy);
  }
}
accuracy: 1
time_ms: 100
memory_kb: 3940
final_rank: 5