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

Measured memory_bytes: 1304