C#の案件

C#の案件が増えつつある。誘導しているんだけど。
C#開発者をどのように増やすかを考える必要がある。


純粋関数型雑記帳 id:tanakh:20040925 から。
同じ大きさのいくつかの円の面積を求める。63個までしか計算できないし、指数オーダになっている。

public class Calc
{
	static void Test()
	{
		ArrayList a = new ArrayList();
		Random r = new Random(1);
		for (int i=0;i<10;++i)
			a.Add(new double[]{r.NextDouble()*5,r.NextDouble()*5});
		Console.WriteLine("{0:F3}",GetCircleArea(a,1));
		Console.WriteLine("{0:F3}",GetCircleArea2(a,1));
	}
	public static double GetCircleArea(ArrayList center, double rad)
	{
		ArrayList cnt = (ArrayList)center.Clone();
		for (int i=0;i<cnt.Count-1;++i)
		{
			double[] d1 = (double[])cnt[i];
			int j = i+1;
			while (j < cnt.Count)
			{
				double[] d2 = (double[])cnt[j];
				if (d1[0] == d2[0] && d1[1] == d2[1])
					cnt.RemoveAt(j);
				else ++j;
			}
		}
		if (cnt.Count > 63) throw new ApplicationException("サイズが大きすぎます");
		ulong ui, umx = 1UL << cnt.Count;
		double[,][][] pos = new double[cnt.Count,cnt.Count][][];
		for (int i=0;i<cnt.Count-1;++i)
		{
			double[] d1 = (double[])cnt[i];
			for (int j=i+1;j<cnt.Count;++j)
			{
				double[] d2 = (double[])cnt[j];
				double x = d2[0]-d1[0], y = d2[1] - d1[1];
				double a = rad*rad/(x*x+y*y)-0.25;
				if (a <= 0) continue;
				a = Math.Sqrt(a);
				double xx = (d1[0]+d2[0])/2, yy = (d1[1]+d2[1])/2;
				pos[i,j] = pos[j,i] = new double[][]{
					new double[]{xx+a*y, yy-a*x, i, j}, new double[]{xx-a*y, yy+a*x, i , j}};
			}
		}
		ArrayList lst = new ArrayList();
		double res = 0;
		for (ui=1UL;ui<umx;++ui)
		{
			int n = 0;
			lst.Clear();
			for (int i=0;i<cnt.Count;++i)
			{
				if ((ui & (1UL<<i)) == 0) continue;
				++n;
				for (int j=i+1;j<cnt.Count;++j)
				{
					if ((ui & (1UL<<j)) == 0) continue;
					if (pos[i,j] == null) goto last;
					for (int k=0;k<2;++k)
					{
						int	l;
						for (l=0;l<cnt.Count;++l)
						{
							if (l == i || l == j) continue;
							if ((ui & (1UL<<l)) == 0) continue;
							if (pos[i,l] == null || pos[j,l] == null) goto not_found;
							double[] d3 = (double[])cnt[l];
							double x = d3[0] - pos[i,j][k][0], y = d3[1] - pos[i,j][k][1];
							if (x*x+y*y > rad*rad) goto not_found;
						}
						lst.Add(pos[i,j][k]);
					not_found:;
					}
				}
			}
			if (lst.Count == 0)
			{
				if (n == 1) res += Math.PI*rad*rad;
				continue;
			}
			double v1 = ((double[])lst[0])[2];
			double v2 = ((double[])lst[0])[3];
			for (int i=1;i<lst.Count;++i)
			{
				int j;
				for (j=i;j<lst.Count;++j)
				{
					double vv1 = ((double[])lst[j])[2];
					double vv2 = ((double[])lst[j])[3];
					if (v1 == vv1) {v1 = vv2; break;}
					if (v1 == vv2) {v1 = vv1; break;}
				}
				if (j == lst.Count) throw new ApplicationException("Not found");
				object tmp = lst[i]; lst[i] = lst[j]; lst[j] = tmp;
			}
			if (v1 != v2) throw new ApplicationException("Not match");
			double	s,a,b,c, d = 0;
			if (lst.Count > 2)
			{
				c = GetLength((double[])lst[0], (double[])lst[1]);
				for (int i=2;i<lst.Count;++i) 
				{
					a = c;
					b = GetLength((double[])lst[i], (double[])lst[i-1]);
					c = GetLength((double[])lst[i], (double[])lst[0]);
					s = (a+b+c)/2;
					d += Math.Sqrt(s*(s-a)*(s-b)*(s-c));
				}
			}
			for (int i=0;i<lst.Count;++i)
			{
				double x = GetLength((double[])lst[i], (double[])lst[(i+1)%lst.Count]);
				d += Math.Asin(x/rad/2)*rad*rad - x/2*Math.Sqrt(rad*rad-x*x/4);
			}
			res += n%2 == 1 ? d : -d;
		last:;
		}
		return res;
	}
	public static double GetLength(double[] d1, double[] d2)
	{
		double x = d1[0]-d2[0];
		double y = d1[1]-d2[1];
		return Math.Sqrt(x*x+y*y);
	}
	public static double GetCircleArea2(ArrayList center, double rad)
	{
		double	res = 0, d = 1e-2, l, t, r, b;
		l = b = double.MaxValue;
		t = r = double.MinValue;
		foreach (double[] dd in center)
		{
			if (dd[0] < l) l = dd[0];
			if (dd[0] > r) r = dd[0];
			if (dd[1] < b) b = dd[1];
			if (dd[1] > t) t = dd[1];
		}
		l -= rad;
		b -= rad;
		t += rad;
		r += rad;
		for (double x=l;x<=r;x+=d)
		{
			for (double y=b;y<=t;y+=d)
			{
				foreach (double[] dd in center)
				{
					double xx = x-dd[0];
					double yy = y-dd[1];
					if (xx*xx+yy*yy < rad*rad)
					{
						res += d*d;
						break;
					}
				}
			}
		}
		return res;
	}
}