Problem:
輪ゴム

n 本の釘を平板上の座標 P1 (x1, y1), P2 (x2, y2), P3 (x3, y3),..., Pn (xn, yn) に１本ずつ打ち、輪ゴムの輪の中に全ての釘が入るように 1 本の輪ゴムで囲みます。このとき、輪ゴムが交差してはいけません。

釘の座標を読み込んで、上記のように釘を輪ゴムで囲んだときに輪ゴムに接していない釘の本数を出力するプログラムを作成してください。輪ゴムは充分に伸び縮みするものとします。同じ座標に 2 本以上の釘を打つことはないものとします。また、輪ゴムがかかった釘と釘の間は直線で結ばれるものとし、その直線上に 3 本以上の釘が並ぶことはないものとします。例えば、図 1 に示すような入力はありえません。図 2 に示すように輪ゴムがかかっていない釘が 1 直線上に並ぶことはありえます。

図１

図２

ただし、それぞれの座標値は -1000.0 以上1000.0 以下の実数です。また、n は 3 以上 100 以下の整数です。

Input

複数のデータセットが与えられます。各データセットは以下のような形式です与えられます。

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

n が 0 の時、入力の最後を示します。データセットの数は 50 を超えません。

Output

データセットごとに、ゴムと接していない釘の本数を出力してください。

例えば、図 3 に示す４つの釘を表す入力があった場合、図 4 のように囲まれるので、輪ゴムに接していない釘の本数は 1 本です。

図３

図４

Sample 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 for the Sample Input

0
3

Hint

以下は２つめのサンプル入力に対する図です。

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        struct Point
        {
            public double x;
            public double y;
        }

        static void Main()
        {
            StringBuilder sb = new StringBuilder();

            while (true)
            {
                int n = int.Parse(Console.ReadLine());

                if (n == 0) break;

                List<Point> pointList = new List<Point>();

                for (int i = 0; i < n; i++)
                {
                    double[] input = Array.ConvertAll(Console.ReadLine().Split(','), double.Parse);

                    Point inputP;
                    inputP.x = input[0];
                    inputP.y = input[1];
                    pointList.Add(inputP);
                }

                pointList = pointList.OrderBy(p => p.x).ThenBy(p => p.y).ToList();

                List<Point> selectList = new List<Point>();

                Point startP;
                startP.x = pointList[0].x;
                startP.y = pointList[0].y;

                Point nextP = new Point();

                double minRd = 1.0;

                for (int i = 1; i < pointList.Count; i++)
                {
                    double r = Math.Atan2((pointList[i].y - startP.y), (pointList[i].x - startP.x));

                    if (r < minRd)
                    {
                        nextP.x = pointList[i].x;
                        nextP.y = pointList[i].y;
                        minRd = r;
                    }
                }

                selectList.Add(nextP);

                Point target = new Point();

                do
                {
                    double maxRd = 0.0;

                    for (int i = 0; i < pointList.Count; i++)
                    {
                        if (pointList[i].x != startP.x || pointList[i].y != startP.y ||
                            pointList[i].x != nextP.x || pointList[i].y != nextP.y)
                        {
                            double rd = CalcAngle(startP, nextP, pointList[i]);

                            if (rd > maxRd)
                            {
                                maxRd = rd;

                                target.x = pointList[i].x;
                                target.y = pointList[i].y;
                            }
                        }
                    }

                    startP.x = nextP.x;
                    startP.y = nextP.y;
                    nextP.x = target.x;
                    nextP.y = target.y;

                    selectList.Add(target);

                } while (target.x != pointList[0].x || target.y != pointList[0].y);

                int ans = pointList.Count - selectList.Count;

                sb.AppendLine(ans.ToString());
            }
            Console.Write(sb);
        }

        static double CalcAngle(Point a, Point b, Point c)
        {
            double baX = a.x - b.x;
            double baY = a.y - b.y;
            double bcX = c.x - b.x;
            double bcY = c.y - b.y;

            double babc = baX * bcX + baY * bcY;
            double ban = baX * baX + baY * baY;
            double bcn = bcX * bcX + bcY * bcY;

            double rd = Math.Acos(babc / Math.Sqrt(ban * bcn));

            return rd;
        }
    }
}