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: Wrong Answer)

using System;
using System.Collections.Generic;

namespace AOJ0068
{
    class Program
    {
        public bool[] inside;
        public void Proc()
        {
            while (true)
            {
                string input = Console.ReadLine();
                if (string.IsNullOrEmpty(input)) continue;
                int N = int.Parse(input);
                if (N == 0) break;
                List<Point> table = new List<Point>();
                int count = 0;

                for (int i = 0; i < N; i++)
                {
                    input = Console.ReadLine();
                    string[] num = input.Split(',');
                    table.Add(new Point(num[0], num[1]));
                }

                if (N == 3)
                {
                    Console.WriteLine(count);
                    continue;
                }

                decimal[,] dist = new decimal[N, N];
                this.inside = new bool[N];

                for (int i = 0; i < N; i++)
                {
                    for (int j = 0; j < N; j++)
                    {
                        dist[i, j] = getDistance(table[i], table[j]);
                    }
                }

                for (int i = 0; i < N; i++)
                {
                    decimal[,] NP = new decimal[3, 2];
                    NP[0, 1] = 4000000M; NP[1, 1] = 4000000M; NP[2, 1] = 4000000M;
                    for (int j = 0; j < N; j++)
                    {
                        if (dist[i, j].Equals(0)) continue;
                        if (this.inside[j]) continue;
                        if (dist[i,j] < NP[0,1])
                        {
                            NP[2, 0] = NP[1, 0];
                            NP[2, 1] = NP[1, 1];
                            NP[1, 0] = NP[0, 0];
                            NP[1, 1] = NP[0, 1];
                            NP[0, 0] = j;
                            NP[0, 1] = dist[i, j];
                        } else if (dist[i,j] < NP[1,1])
                        {
                            NP[2, 0] = NP[1, 0];
                            NP[2, 1] = NP[1, 1];
                            NP[1, 0] = j;
                            NP[1, 1] = dist[i, j];
                        } else if (dist[i, j] < NP[2, 1])
                        {
                            NP[2, 0] = j;
                            NP[2, 1] = dist[i, j];
                        }
                    }
                    Rectangle parts = new Rectangle(table[(int)NP[0,0]], table[(int)NP[1, 0]],table[(int)NP[2, 0]]);

                    if (parts.InterSection(table[i]))
                    {
                        this.inside[i] = true;
                        count++;
                    }
                }
                Console.WriteLine(count);
            }
        }

        static void Main(string[] args)
        {
            Program prg = new Program();
            prg.Proc();
        }

        public decimal getDistance(Point p, Point q)
        {
            return (p.X - q.X) * (p.X - q.X) + (p.Y - q.Y) * (p.Y - q.Y);
        }

        public struct Point
        {
            decimal x;
            decimal y;

            public Point(string x, string y)
            {
                this.x = decimal.Parse(x);
                this.y = decimal.Parse(y);
            }

            public decimal X
            {
                get { return this.x; }
                set { this.x = X; }
            }

            public decimal Y
            {
                get { return this.y; }
                set { this.y = Y; }
            }
        }

        public struct Vector
        {
            decimal vx;
            decimal vy;

            public Vector(Point a, Point b)
            {
                this.vx = b.X - a.X;
                this.vy = b.Y - a.Y;
            }

            public decimal VX
            {
                get { return this.vx; }
                set { this.vx = VX; }
            }

            public decimal VY
            {
                get { return this.vy; }
                set { this.vy = VY; }
            }
        }

        public struct Rectangle
        {
            Point a;
            Point b;
            Point c;

            public Rectangle(Point x, Point y, Point z)
            {
                this.a = x;
                this.b = y;
                this.c = z;
            }

            public bool InterSection(Point p)
            {
                Vector AB = new Vector(this.a, this.b);
                Vector BP = new Vector(this.b, p);

                Vector BC = new Vector(this.b, this.c);
                Vector CP = new Vector(this.c, p);

                Vector CA = new Vector(this.c, this.a);
                Vector AP = new Vector(this.a, p);

                decimal C1 = AB.VX * BP.VY - AB.VY * BP.VX;
                decimal C2 = BC.VX * CP.VY - BC.VY * CP.VX;
                decimal C3 = CA.VX * AP.VY - CA.VY * AP.VX;

                if ((C1 > 0 && C2 > 0 && C3 > 0) || (C1 < 0 && C2 < 0 && C3 < 0))
                {
                    return true;
                }
                return false;
            }
        }
    }
}