Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

凸？

平面上の異なる 4 点　$A (x_a, y_a)$, $B (x_b, y_b)$, $C (x_c, y_c)$, $D(x_d, y_d)$ の座標を読み込んで、それら 4 点を頂点とした四角形 $ABCD$ に凹みがなければ YES、凹みがあれば NO と出力するプログラムを作成してください。

凹みのある四角形とは図 1 のような四角形です。

Input

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

$x_a$,$y_a$,$x_b$,$y_b$,$x_c$,$y_c$,$x_d$,$y_d$

$x_a$, $y_a$, $x_b$, $y_b$, $x_c$, $y_c$, $x_d$, $y_d$ はそれぞれ -100 以上 100 以下であり、実数で与えられます。

1 直線上に 3 つ以上点が並ぶことはないものとします。また、入力順に点を結んでいけば、四角形になる順番に点の座標が入力されるものとします。（つまり、図 2 のような形になる順番で点が与えられることはありません。)

データセットの数は 100 を超えません。

Output

各データセットごとに、YES または NO を１行に出力します。

Sample Input

0.0,0.0,1.0,0.0,1.0,1.0,0.0,1.0
0.0,0.0,3.0,0.0,1.0,1.0,1.0,3.0

Output for the Sample Input

YES
NO

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
					
public class my
{	
	public static void Main()
	{
		string s;
		
		while( null != ( s = Console.ReadLine()) ) {
			var E = my.GetDoubleArray(',', s);
			
			Vector A,B,C,D;
			
			A.X = E[0];
			A.Y = E[1];
			B.X = E[2];
			B.Y = E[3];
			C.X = E[4];
			C.Y = E[5];
			D.X = E[6];
			D.Y = E[7];
			
			bool isConvex = false;
			
			// Convex ---> P is in triangle
			isConvex |= my.IsInTriangle(A,B,C,D);
			isConvex |= my.IsInTriangle(D,A,B,C);
			isConvex |= my.IsInTriangle(C,D,A,B);
			isConvex |= my.IsInTriangle(B,C,D,A);
			
			Console.WriteLine(!isConvex? "YES":"NO");
		}
	}
	
	private static bool IsInTriangle(Vector A, Vector B, Vector C, Vector P)
	{
		Vector AP = my.SubVecter(A, P);
		Vector BP = my.SubVecter(B, P);
		Vector CP = my.SubVecter(C, P);
		
		Vector AB = my.SubVecter(A, B);
		Vector BC = my.SubVecter(B, C);
		Vector CA = my.SubVecter(C, A);
		
		//Cross Product(only z)
		var c1 = AB.X * BP.Y - AB.Y * BP.X;
		var c2 = BC.X * CP.Y - BC.Y * CP.X;
		var c3 = CA.X * AP.Y - CA.Y * AP.X;
		
		return (c1 > 0 && c2 > 0 && c3 > 0 || c1 < 0 && c2 < 0 && c3 < 0);
	}
	
	private static void Swap(int[] A, int i, int j)
	{
		int tmp = A[i];
		A[i] = A[j];
		A[j] = tmp;
	}
	
	private static int GetInt()
	{
		return int.Parse(Console.ReadLine());
	}
	
	private static int[] GetIntArray()
	{
		return Array.ConvertAll(Console.ReadLine().Split(' '), int.Parse);
	}

	private static int[] GetIntArray(int n)
	{
		var A = new int[n];
		var s = Console.ReadLine().Split(' ');

		for(int i = 0; i < n; i++) {
			A[i] = int.Parse(s[i]);
		}
		return A;
	}
	
	private static int[] GetIntArray(int n, string t)
	{
		var A = new int[n];
		var s = t.Split(' ');

		for(int i = 0; i < n; i++) {
			A[i] = int.Parse(s[i]);
		}
		return A;
	}

	private static int[] GetIntArray(char c)
	{
		return Array.ConvertAll(Console.ReadLine().Split(c), int.Parse);
	}
	
	private static int[] GetIntArray(char c, string s)
	{
		return Array.ConvertAll(s.Split(c), int.Parse);
	}
	
	private static int[] GetIntArray(string s)
	{
		return Array.ConvertAll(s.Split(' '), int.Parse);
	}
	
	private static double[] GetDoubleArray()
	{
		return Array.ConvertAll(Console.ReadLine().Split(' '), double.Parse);
	}
	private static double[] GetDoubleArray(char c, string s)
	{
		return Array.ConvertAll(s.Split(c), double.Parse);
	}
	
	public static string Reverse(string s)
	{
		var c = s.ToCharArray();
		Array.Reverse(c);
		
		return new String(c);
	}
	
	private static void WriteArray(int[] a)
	{
		Console.WriteLine(string.Join(" ", Array.ConvertAll( a, x=>x.ToString() ) ) );
	}

	private static void WriteArray(long[] a)
	{
		Console.WriteLine(string.Join(" ", Array.ConvertAll( a, x=>x.ToString() ) ) );
	}
	
	private static void WriteVector(Vector v)
	{
		Console.WriteLine("{0:f8} {1:f8}", v.X, v.Y);
	}
	
	private static Vector SubVecter(Vector A, Vector B)
	{
		Vector ret;
		
		ret.X = A.X -B.X;
		ret.Y = A.Y- B.Y;
		
		return ret;
	}
}

public struct Vector
{
	public double X,Y;
}