Language: C++

#include<cstdio>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<complex>
#include<stack>
#include<cmath>

using namespace std;

#define reps(i,f,n) for(int i=f;i<int(n);i++)
#define rep(i,n) reps(i,0,n)

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

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


double cross(P a,P b){return a.X*b.Y-a.Y*b.X;}
bool ccw(P a,P b,P c){return cross(b-a,c-a)>=0;}

vector<P> convex_VP(vector<P> p){
	
	sort(p.begin(),p.end());
	vector<P> ret(p.size()*2);
	
	int k=0;
	for(int i=0;i<p.size();i++){
		while(k>1 && !ccw(ret[k-2],ret[k-1],p[i]))k--;
		ret[k]=p[i];k++;
	}
	
	int t=k;
	for(int i=p.size()-2;i>=0;i--){
		while(k>t && !ccw(ret[k-2],ret[k-1],p[i]))k--;
		ret[k]=p[i];k++;
	}
	
	return vector<P>(ret.begin(), ret.begin()+k-1);
}

int main(){
	
	while(1){
		int n;
		cin>>n;
		if(n==0)break;
		
		vector<P> p;
		rep(i,n){
			double a,b;
			scanf("%lf,%lf",&a,&b);
			p.push_back(P(a,b));
		}
		
		vector<P> convex = convex_VP(p);
		rep(i,convex.size()){
			printf("%lf %lf\n",convex[i].X,convex[i].Y);
		}
		cout<<(int)p.size()-(int)convex.size()<<endl;
	}
}

Compiler output:
In file included from /usr/include/c++/14/bits/stl_algobase.h:71,
                 from /usr/include/c++/14/algorithm:60,
                 from a.cc:2:
/usr/include/c++/14/bits/predefined_ops.h: In instantiation of 'constexpr bool __gnu_cxx::__ops::_Iter_less_iter::operator()(_Iterator1, _Iterator2) const [with _Iterator1 = __gnu_cxx::__normal_iterator<std::complex<double>*, std::vector<std::complex<double> > >; _Iterator2 = __gnu_cxx::__normal_iterator<std::complex<double>*, std::vector<std::complex<double> > >]':
/usr/include/c++/14/bits/stl_algo.h:1777:14:   required from 'void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<complex<double>*, vector<complex<double> > >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
 1777 |           if (__comp(__i, __first))
      |               ~~~~~~^~~~~~~~~~~~~~
/usr/include/c++/14/bits/stl_algo.h:1817:25:   required from 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<complex<double>*, vector<complex<double> > >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
 1817 |           std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
      |           ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/stl_algo.h:1908:31:   required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<complex<double>*, vector<complex<double> > >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
 1908 |           std::__final_insertion_sort(__first, __last, __comp);
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/stl_algo.h:4772:18:   required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<complex<double>*, vector<complex<double> > >]'
 4772 |       std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
      |       ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.cc:30:6:   required from here
   30 |         sort(p.begin(),p.end());
      |         ~~~~^~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/predefined_ops.h:45:23: error: no match for 'operator<' (operand types are 'std::complex<double>' and 'std::complex<double>')
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/14/bits/stl_algobase.h:67:
/usr/include/c++/14/bits/stl_iterator.h:1241:5: note: candidate: 'template<class _IteratorL, class _IteratorR, class _Container> bool __gnu_cxx::operator<(const __normal_iterator<_IteratorL, _Container>&, const __normal_iterator<_IteratorR, _Container>&)'
 1241 |     operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1241:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const __gnu_cxx::__normal_iterator<_IteratorL, _Container>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1249:5: note: candidate: 'template<class _Iterator, class _Container> bool __gnu_cxx::operator<(const __normal_iterator<_Iterator, _Container>&, const __normal_iterator<_Iterator, _Container>&)'
 1249 |     operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1249:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const __gnu_cxx::__normal_iterator<_Iterator, _Container>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/14/bits/stl_algobase.h:64:
/usr/include/c++/14/bits/stl_pair.h:1045:5: note: candidate: 'template<class _T1, class _T2> constexpr bool std::operator<(const pair<_T1, _T2>&, const pair<_T1, _T2>&)'
 1045 |     operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_pair.h:1045:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const std::pair<_T1, _T2>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:448:5: note: candidate: 'template<class _Iterator> constexpr bool std::operator<(const reverse_iterator<_Iterator>&, const reverse_iterator<_Iterator>&)'
  448 |     operator<(const reverse_iterator<_Iterator>& __x,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:448:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const std::reverse_iterator<_Iterator>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:493:5: note: candidate: 'template<class _IteratorL, class _IteratorR> constexpr bool std::operator<(const reverse_iterator<_Iterator>&, const reverse_iterator<_IteratorR>&)'
  493 |     operator<(const reverse_iterator<_IteratorL>& __x,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:493:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const std::reverse_iterator<_Iterator>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1694:5: note: candidate: 'template<class _IteratorL, class _IteratorR> constexpr bool std::operator<(const move_iterator<_IteratorL>&, const move_iterator<_IteratorR>&)'
 1694 |     operator<(const move_iterator<_IteratorL>& __x,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1694:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const std::move_iterator<_IteratorL>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1760:5: note: candidate: 'template<class _Iterator> constexpr bool std::operator<(const move_iterator<_IteratorL>&, const move_iterator<_IteratorL>&)'
 1760 |     operator<(const move_iterator<_Iterator>& __x,
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_iterator.h:1760:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const std::move_iterator<_IteratorL>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/14/vector:66,
                 from a.cc:3:
/usr/include/c++/14/bits/stl_vector.h:2089:5: note: candidate: 'template<class _Tp, class _Alloc> bool std::operator<(const vector<_Tp, _Alloc>&, const vector<_Tp, _Alloc>&)'
 2089 |     operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
      |     ^~~~~~~~
/usr/include/c++/14/bits/stl_vector.h:2089:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const std::vector<_Tp, _Alloc>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/14/bits/memory_resource.h:47,
                 from /usr/include/c++/14/vector:87:
/usr/include/c++/14/tuple:2600:5: note: candidate: 'template<class ... _TElements, class ... _UElements> constexpr bool std::operator<(const tuple<_UTypes ...>&, const tuple<_Elements ...>&)'
 2600 |     operator<(const tuple<_TElements...>& __t,
      |     ^~~~~~~~
/usr/include/c++/14/tuple:2600:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'const std::tuple<_UTypes ...>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/14/bits/basic_string.h:47,
                 from /usr/include/c++/14/string:54,
                 from a.cc:4:
/usr/include/c++/14/string_view:673:5: note: candidate: 'template<class _CharT, class _Traits> constexpr bool std::operator<(basic_string_view<_CharT, _Traits>, basic_string_view<_CharT, _Traits>)'
  673 |     operator< (basic_string_view<_CharT, _Traits> __x,
      |     ^~~~~~~~
/usr/include/c++/14/string_view:673:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'std::basic_string_view<_CharT, _Traits>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
/usr/include/c++/14/string_view:680:5: note: candidate: 'template<class _CharT, class _Traits> constexpr bool std::operator<(basic_string_view<_CharT, _Traits>, __type_identity_t<basic_string_view<_CharT, _Traits> >)'
  680 |     operator< (basic_string_view<_CharT, _Traits> __x,
      |     ^~~~~~~~
/usr/include/c++/14/string_view:680:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h:45:23: note:   'std::complex<double>' is not derived from 'std::basic_string_view<_CharT, _Traits>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
/usr/include/c++/14/string_view:688:5: note: candidate: 'template<class _CharT, class _Traits> constexpr bool std::operator<(__type_identity_t<basic_string_view<_CharT, _Traits> >, basic_string_view<_CharT, _Traits>)'
  688 |     operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
      |     ^~~~~~~~
/usr/include/c++/14/string_view:688:5: note:   template argument deduction/substitution failed:
/usr/include/c++/14/bits/predefined_ops.h: