Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Diagnostics;
- namespace EfficientPoint2DMinDIstance
- {
- public static class Utils
- {
- public static T MinBy<T, R>(this IEnumerable<T> source, Func<T, R> f) where R : IComparable<R>
- {
- IEnumerator<T> e = source.GetEnumerator();
- if (!e.MoveNext())
- {
- throw new Exception("You need to provide at least one element.");
- }
- T min = e.Current;
- R minf = f(min);
- while (e.MoveNext())
- {
- T x = e.Current;
- R xf = f(x);
- if (minf.CompareTo(xf) > 0)
- {
- min = x;
- minf = xf;
- }
- }
- return min;
- }
- }
- class Point
- {
- public readonly int id;
- public float x;
- public float y;
- public Point(int id, float x, float y)
- {
- this.id = id;
- this.x = x;
- this.y = y;
- }
- public float Distance(Point p)
- {
- float dx = this.x - p.x;
- float dy = this.y - p.y;
- return (float)Math.Sqrt(dx * dx + dy * dy);
- }
- }
- class Program
- {
- enum Version
- {
- CommuSoft,
- IpavluA1,
- IpavluA2,
- IpavluB,
- IvanStoev
- }
- static void Main()
- {
- Console.WriteLine();
- Point p = new Point(3, 0.6f, 0.0f);
- Point p_rslt = null;
- int t_tests = 5;
- var list_a = BuildList(3);
- var list_b = BuildList(3000000);
- for (int t = 0; t < t_tests; ++t)
- {
- Batch(10000000, list_a, p, out p_rslt);
- }
- for (int t = 0; t < t_tests; ++t)
- {
- Batch(1, list_b, p, out p_rslt);
- }
- Console.ReadKey();
- }
- static List<Point> BuildList(int items)
- {
- var list = new List<Point>();
- //Random r = new Random();
- bool odd_even = false;
- for (int i = 0; i < items; i++, odd_even = !odd_even)
- {
- var multiply = odd_even ? 1.0 : 2.0;
- //var rnd = (float)(r.NextDouble() * multiply);
- var rnd = (float)(0.6 * multiply);
- list.Add(new Point(i, rnd, 0.0f));
- }
- return list;
- }
- static void Compute(int batch_iterations, Version version, Point p, List<Point> list, out Point rslt)
- {
- Stopwatch sw = new Stopwatch();
- rslt = null;
- switch (version)
- {
- case Version.CommuSoft:
- sw.Start();
- for (int b = 0; b < batch_iterations; b++)
- {
- rslt = CommuSoft(list, p);
- }
- sw.Stop();
- break;
- case Version.IpavluA1:
- sw.Start();
- for (int b = 0; b < batch_iterations; b++)
- {
- rslt = ipavlu_VersionA1(list, p);
- }
- sw.Stop();
- break;
- case Version.IpavluA2:
- sw.Start();
- for (int b = 0; b < batch_iterations; b++)
- {
- rslt = ipavlu_VersionA2(list, p);
- }
- sw.Stop();
- break;
- case Version.IpavluB:
- sw.Start();
- for (int b = 0; b < batch_iterations; b++)
- {
- rslt = ipavlu_VersionB(list, p);
- }
- sw.Stop();
- break;
- case Version.IvanStoev:
- sw.Start();
- for (int b = 0; b < batch_iterations; b++)
- {
- rslt = IvanStoev(list, p);
- }
- sw.Stop();
- break;
- }
- Console.Write("{0}: {1} ", version.ToString(), sw.ElapsedMilliseconds);
- }
- static void Batch(int batch_iterations, List<Point> list, Point p, out Point p_rslt)
- {
- Console.Write("B[{0}] I[{1}]: ", batch_iterations, list.Count);
- Compute(batch_iterations, Version.CommuSoft, p, list, out p_rslt);
- Compute(batch_iterations, Version.IpavluA1, p, list, out p_rslt);
- Compute(batch_iterations, Version.IpavluA2, p, list, out p_rslt);
- Compute(batch_iterations, Version.IpavluB, p, list, out p_rslt);
- Compute(batch_iterations, Version.IvanStoev, p, list, out p_rslt);
- Console.Write("\n");
- }
- static Point CommuSoft(List<Point> list, Point p)
- {
- return
- list
- .Where(x => x.Distance(p) <= 1.0)
- .OrderBy(x => x.Distance(p))
- .FirstOrDefault()
- ;
- }
- static Point ipavlu_VersionA1(List<Point> list, Point p)
- {
- //version A, most efficient memory and cpu usage
- Point closest_to_p = null;
- float shortest_d = float.MaxValue;
- list.ForEach(point =>
- {
- var d = point.Distance(p);
- if (d > 1.0f) return;
- if (closest_to_p == null || shortest_d > d)
- {
- closest_to_p = point;
- shortest_d = d;
- }
- });
- return closest_to_p;
- }
- static Point ipavlu_VersionA2(List<Point> list, Point p)
- {
- //version A, most efficient memory and cpu usage, better than A1
- Point closest_to_p = null;
- float shortest_d = float.MaxValue;
- int max = list.Count;
- for (int i = 0; i < max; ++i)
- {
- var point = list[i];
- var d = point.Distance(p);
- if (d > 1.0f) continue;
- if (closest_to_p == null || shortest_d > d)
- {
- closest_to_p = point;
- shortest_d = d;
- }
- }
- return closest_to_p;
- }
- static Point ipavlu_VersionB(List<Point> list, Point p)
- {
- KeyValuePair<Point,float> null_point = new KeyValuePair<Point,float>(null, float.PositiveInfinity);
- var rslt_point =
- list
- .Select(xp =>
- {
- var d = xp.Distance(p);
- return d <= 1.0f ? new KeyValuePair<Point, float>(xp, d) : null_point;
- })
- .Aggregate(null_point, (a, b) =>
- {
- if (a.Key == null) return b;
- if (b.Key == null) return a;
- return a.Value > b.Value ? b : a;
- }, x => x.Key);
- return rslt_point;
- }
- static Point IvanStoev(List<Point> list, Point p)
- {
- var closest =
- list
- .Select(item => new { item, distance = item.Distance(p) })
- .Aggregate((a, b) => a.distance <= b.distance ? a : b)
- ;
- var closestPt = closest.distance <= 1.0 ? closest.item : null;
- return closestPt;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement