Problem: Hit n nails one by one at the coordinates P1 (x1, y1), P2 (x2, y2), P3 (x3, y3), ..., Pn (xn, yn) on the flat plate, and put them on the rubber band ring. Surround it with a single rubber band so that all the nails fit inside. At this time, the rubber bands must not intersect.

Create a program that reads the coordinates of the nails and outputs the number of nails that are not in contact with the rubber band when the nail is surrounded by the rubber band as described above. The rubber band shall expand and contract sufficiently. You may not hit more than one nail at the same coordinates. In addition, it is assumed that the nails covered with rubber bands are connected by a straight line, and that no more than three nails are lined up on the straight line. For example, there can be no input as shown in Figure 1. As shown in Figure 2, it is possible for nails without rubber bands to line up in a straight line.

<image> | <image>
--- | ---
Figure 1 | Figure 2



However, each coordinate value is a real number between -1000.0 and 1000.0. Also, n is an integer between 3 and 100.

Hint

Below is a diagram for the second sample input.

<image>
---



Input

Given multiple datasets. Each dataset is given in the following format:


n
x1, y1
x2, y2
...
...
xn, yn


When n is 0, it indicates the end of input. The number of datasets does not exceed 50.

Output

For each dataset, output the number of nails that are not in contact with the rubber. For example, if there is an input representing the four nails shown in Fig. 3, it will be surrounded as shown in Fig. 4, so the number of nails that are not in contact with the rubber band is one.

<image> | <image>
--- | ---
Figure 3 | Figure 4


Example

Input

4
1.0,0.0
0.0,1.0
2.0,1.0
1.0,2.0
9
-509.94,892.63
567.62,639.99
-859.32,-64.84
-445.99,383.69
667.54,430.49
551.12,828.21
-940.2,-877.2
-361.62,-970
-125.42,-178.48
0


Output

0
3

Solution (in CPP):

Solution:
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>
#include <numeric>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <string.h>
#include <complex>
using namespace std;

typedef long double D;
const D EPS = 1e-8,INF = 1e12;

template<typename T> int sig(T a,T b=0){return a<b-EPS?-1:a>b+EPS?1:0;}
template<typename T> bool eq(T a,T b){ return sig(abs(a-b))==0;}
template<typename T> D norm(T a){ return a*a;}

typedef complex<D> P;
#define X real()
#define Y imag()


#define ALL(c) (c).begin(),(c).end()
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define IN(l,v,r) ((l)<=(v) && (v)<(r))

#define ISEQ(c) (c).begin(), (c).end()
typedef long long ll;

typedef vector<P> Poly,ConvexPoly;
#define prev(as, i) as[(i-1+as.size())%as.size()]
#define curr(as, i)  as[i]
#define next(as, i) as[(i+1)%as.size()]


// a×b
D cross(const P& a,const P& b){
  return imag(conj(a)*b);
}
// a・b
D dot(const P& a,const P& b) {
  return real(conj(a)*b);
}

int ccw(const P& a,P b,P c){
  b -= a; c -= a;
  if (cross(b,c) > 0)   return +1;       // counter clockwise
  if (cross(b,c) < 0)   return -1;       // clockwise
  if (dot(b,c) < 0)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

//浮動小数点modで非負の値のみかえす．
D pfmod(D v,D M=2*M_PI){
  return fmod(fmod(v,M)+M,M);
}

//[0,PI)
D AbsArg(D a){
  D ret=pfmod(max(a,-a),2);
  return min(ret,2*M_PI-ret);
}

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

//
P O=P(0,0);
P s,g;


// verified by 
// 事前にs-g
// O-s → O-gの回転方向に関してソート．
// (同角度の場合、距離が遠い方が前)
bool CompArg(const P& p1,const P&p2){
  if(abs(ccw(O,p1,p2))!=1)return abs(p1)>abs(p2);//sameline
  return ccw(O,p1,p2)==ccw(O,s,g);
}

//!!
//角度ソート
P dir;//基準方向
bool Comp(const P& p1,const P&p2){
  if(sig(pfmod(arg(p1)-arg(dir)),pfmod(arg(p2)-arg(dir)))==0)return abs(p1)>abs(p2);
  return sig(pfmod(arg(p1)-arg(dir)),pfmod(arg(p2)-arg(dir)));
}


enum { OUT, ON, IN };
int contains(const Poly& ps, const P& p) {
  bool in = false;
  REP(i,ps.size()){
    P a = curr(ps,i) - p, b = next(ps,i) - p;
    if (a.Y > b.Y) swap(a, b);
    if (a.Y <= 0 && 0 < b.Y)
      if (cross(a, b) < 0) in = !in;
    if (cross(a, b) == 0 && dot(a, b) <= 0) return ON;
  }
  return in ? IN : OUT;
}

D area2(const Poly& ps){
  D S=0;
  REP(i,ps.size())S+=cross(curr(ps,i),next(ps,i));
  return S;
}

//凸包
//O(n logn)
ConvexPoly convex_hull(Poly ps) {
  int n = ps.size(), k = 0;
  sort(ALL(ps));
  Poly ch(2*n);
  REP(i,n){ // lower-hull
    while (k >= 2 && ccw(ch[k-2],ch[k-1],ps[i]) <= 0) --k;
    ch[k++]=ps[i];
  }
  for(int i=n-2,t=k+1;i>=0;i--){// upper-hull
    while (k >= t && ccw(ch[k-2],ch[k-1],ps[i]) <= 0) --k;
    ch[k++]=ps[i];
  }
  ch.resize(k-1);
  return ch;
}


int main() {
  while (true) {
    int n;
    cin >> n;
    if (n == 0) break;
    Poly p;
    for (int i = 0; i < n; i++) {
      double x, y;
      scanf("%lf,%lf", &x, &y);
      p.push_back(P(x,y));
    }
    sort(ISEQ(p));
    ConvexPoly cp = convex_hull(p);
    //    for (int i = 0; i < cp.size(); i++) {
    //      printf("%f, %f\n", cp[i].X, cp[i].Y);
    //    }
    cout << n - cp.size() << endl;
  }
}