using System;
using System.Collections.Generic;
public struct Complex
{
public double Real;
public double Imaginary;
public Complex(double real, double imaginary)
{
Real = real;
Imaginary = imaginary;
}
public static Complex operator -(Complex a, Complex b)
{
return new Complex(a.Real - b.Real, a.Imaginary - b.Imaginary);
}
public static double Abs(Complex c)
{
return Math.Sqrt(c.Real * c.Real + c.Imaginary * c.Imaginary);
}
public static double Atan2(double y, double x)
{
return Math.Atan2(y, x);
}
}
public class Program
{
const int MAX_POINTS = 500;
// This function returns the maximum points that
// can lie inside the circle of radius 'r' being
// rotated about point 'i'
static int GetPointsInside(int i, double r, int n, Complex[] arr, double[,] dis)
{
// This list stores alpha and beta and flag
// is marked true for alpha and false for beta
List<(double, bool)> angles = new List<(double, bool)>();
for (int j = 0; j < n; j++)
{
if (i != j && dis[i, j] <= 2 * r)
{
// acos returns the arc cosine of the complex
// used for cosine inverse
double B = Math.Acos(dis[i, j] / (2 * r));
// arg returns the phase angle of the complex
double A = Complex.Atan2(arr[j].Imaginary - arr[i].Imaginary, arr[j].Real - arr[i].Real);
double alpha = A - B;
double beta = A + B;
angles.Add((alpha, true));
angles.Add((beta, false));
}
}
// angles list is sorted and traversed
angles.Sort(CompareAngles);
// count maintains the number of points inside
// the circle at certain value of theta
// res maintains the maximum of all count
int count = 1, res = 1;
foreach (var angle in angles)
{
// entry angle
if (angle.Item2)
count++;
// exit angle
else
count--;
if (count > res)
res = count;
}
return res;
}
// Returns count of maximum points that can lie
// in a circle of radius r.
static int MaxPoints(Complex[] arr, int n, int r)
{
// dis array stores the distance between every
// pair of points
double[,] dis = new double[n, n];
for (int i = 0; i < n - 1; i++)
for (int j = i + 1; j < n; j++)
// abs gives the magnitude of the complex
// number and hence the distance between
// i and j
dis[i, j] = dis[j, i] = Complex.Abs(arr[i] - arr[j]);
// This loop picks a point p
int ans = 0;
for (int i = 0; i < n; i++)
// maximum number of points for point arr[i]
ans = Math.Max(ans, GetPointsInside(i, r, n, arr, dis));
return ans;
}
// Custom comparer for sorting angles
static int CompareAngles((double, bool) A, (double, bool) B)
{
if (A.Item1 < B.Item1)
return -1;
else if (A.Item1 > B.Item1)
return 1;
else
return A.Item2.CompareTo(B.Item2);
}
// Driver code
public static void Main(string[] args)
{
Complex[] arr = {
new Complex(6.47634, 7.69628),
new Complex(5.16828, 4.79915),
new Complex(6.69533, 6.20378)
};
int r = 1;
int n = arr.Length;
Console.WriteLine("The maximum number of points are: " + MaxPoints(arr, n, r));
}
}