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.IO;
- using System.Threading.Tasks;
- using System.Net.Sockets;
- namespace Robotos.cs
- {
- class Program
- {
- static void Main(string[] args)
- {
- int port = 12005;
- TcpClient client;
- try
- {
- client = new TcpClient("ecovpn.dyndns.org", port);
- } catch (Exception e)
- {
- Console.Error.WriteLine(e.ToString());
- Console.ReadKey();
- return;
- }
- List<string> instructions = new List<string>();
- Point armPos = new Point(500, 500);
- string boxData = "";
- using (StreamReader data = new StreamReader("Robots.csv"))
- {
- data.ReadLine();
- boxData = data.ReadLine();
- }
- instructions.Add("start;BVe1wrvIuzvW;" + boxData);
- Point[] boxes = Point.StringToPoints(boxData);
- Point WF = MathX.Weiszfeld(boxes).GetRounded();
- List<Point> possibleCenter = new List<Point>();
- if (WF.Distance(Point.zero) > 300)
- possibleCenter.Add(WF);
- for (int i = 0; i < boxes.Length; i++)
- {
- for (int x = -(int)Math.Floor(boxes.Length / 2f); x < (int)Math.Ceiling(boxes.Length / 2f) - 1; x++)
- {
- Point cur = boxes[i] + Point.right * 100 * x;
- Point checkA = cur + Point.right * 100 * boxes.Length, checkB = cur + Point.right * 100 * -boxes.Length;
- float distA = checkA.Distance(Point.zero), distB = checkB.Distance(Point.zero);
- if (distA <= 1200 && distA > 300 && distB <= 1200 && distB > 300 && !possibleCenter.Contains(cur))
- possibleCenter.Add(cur);
- }
- for (int y = -(int)Math.Floor(boxes.Length / 2f); y < (int)Math.Ceiling(boxes.Length / 2f) - 1; y++)
- {
- Point cur = boxes[i] + Point.up * 100 * y;
- Point checkA = cur + Point.up * 100 * boxes.Length, checkB = cur + Point.up * 100 * -boxes.Length;
- float distA = checkA.Distance(Point.zero), distB = checkB.Distance(Point.zero);
- if (distA <= 1200 && distA > 300 && distB <= 1200 && distB > 300 && !possibleCenter.Contains(cur))
- possibleCenter.Add(cur);
- }
- }
- possibleCenter = possibleCenter.OrderBy(center => MathX.GetScore(boxes, center).a).ToList();
- Point best = possibleCenter[0];
- Pair<float, string> line = MathX.GetScore(boxes, best);
- List<Point> left;
- if (line.b == "X")
- left = boxes.OrderBy(box => Math.Abs(box.y)).ToList();
- else
- left = boxes.OrderBy(box => Math.Abs(box.x)).ToList();
- List<Point> posLeft = new List<Point>();
- for (int i = -(int)Math.Floor(boxes.Length / 2f); i < (int)Math.Floor(boxes.Length / 2f) - (boxes.Length % 2 == 0 ? 1 : 0); i++)
- {
- Point possible;
- if (line.b == "X")
- possible = best + Point.right * 50 * i;
- else
- possible = best + Point.right * 50 * i;
- bool found = false;
- for (int n = 0; n < boxes.Length; n++)
- {
- if (boxes[n] == possible)
- {
- found = true;
- left.Remove(boxes[n]);
- }
- }
- if (found)
- break;
- posLeft.Add(possible);
- }
- for (int i = 0; i < posLeft.Count; i++)
- {
- left = left.OrderBy(box => MathX.LineIntersectCirlce(new Pair<Point, Point>(box, posLeft[i]), Point.zero, 325) ? 1 : 0).ThenBy(box => posLeft[i].Distance(box)).ToList();
- Point cur = left[0];
- if (MathX.LineIntersectCirlce(new Pair<Point, Point>(armPos, cur), Point.zero, 300))
- {
- armPos = MathX.FindTangentIntersection(cur, armPos, Point.zero, 300).GetRounded();
- instructions.Add("move;BVe1wrvIuzvW;" + armPos);
- }
- instructions.Add("move;BVe1wrvIuzvW;" + cur);
- instructions.Add("pickup;BVe1wrvIuzvW");
- if (MathX.LineIntersectCirlce(new Pair<Point, Point>(posLeft[i], cur), Point.zero, 325)) {
- cur = MathX.FindTangentIntersection(cur, posLeft[i], Point.zero, 325).GetRounded();
- instructions.Add("move;BVe1wrvIuzvW;" + cur);
- }
- bool col = false;
- for (int n = 0; n < boxes.Length; n++)
- {
- if (boxes[n] == left[0])
- continue;
- if (MathX.LineIntersectsBox(new Pair<Point, Point>(posLeft[i], left[0]), boxes[n]))
- {
- col = true;
- break;
- }
- }
- if (col)
- {
- if (line.b == "X")
- {
- instructions.Add("move;BVe1wrvIuzvW;" + (posLeft[i] + Point.right * (cur.x - line.a)));
- armPos = posLeft[i];
- } else
- {
- instructions.Add("move;BVe1wrvIuzvW;" + (posLeft[i] + Point.right * (cur.y - line.a)));
- }
- }
- instructions.Add("putdown;BVe1wrvIuzvW");
- instructions.Add("move;BVe1wrvIuzvW;" + (posLeft[i]));
- armPos = posLeft[i];
- left.RemoveAt(0);
- }
- instructions.Add("end;BVe1wrvIuzvW");
- NetworkStream stream = client.GetStream();
- foreach (string i in instructions)
- {
- Byte[] data = Encoding.ASCII.GetBytes(i);
- stream.Write(data, 0, data.Length);
- Console.WriteLine("Sent: " + i);
- data = new Byte[256];
- string responseData = String.Empty;
- int bytes = stream.Read(data, 0, data.Length);
- responseData = Encoding.ASCII.GetString(data, 0, bytes);
- Console.WriteLine("Recieved: " + responseData + '\n');
- }
- stream.Close();
- client.Close();
- Console.ReadKey();
- }
- }
- class Point
- {
- public float x, y;
- public float Length { get { return (float)Math.Sqrt(x * x + y * y); } }
- public static Point zero = new Point(0, 0);
- public static Point one = new Point(1, 1);
- public static Point right = new Point(1, 0);
- public static Point up = new Point(0, 1);
- public Point (float x, float y)
- {
- this.x = x;
- this.y = y;
- }
- public Point (string data)
- {
- data = data.Substring(1, data.Length - 2);
- string[] xy = data.Split(',');
- x = int.Parse(xy[0]);
- y = int.Parse(xy[1]);
- }
- public static Point[] StringToPoints (string data)
- {
- data = data.Substring(1, data.Length - 2);
- string[] points = data.Split(';');
- Point[] rtrn = new Point[points.Length];
- for (int i = 0; i < points.Length; i++)
- rtrn[i] = new Point(points[i]);
- return rtrn;
- }
- public Point GetRounded ()
- {
- return new Point((float)Math.Round(x), (float)Math.Round(y));
- }
- public float Distance (Point B)
- {
- return (this - B).Length;
- }
- public float Cross(Point b)
- {
- return x * b.y - y * b.x;
- }
- public static Point operator + (Point A, Point B)
- {
- return new Point(A.x + B.x, A.y + B.y);
- }
- public static Point operator -(Point A, Point B)
- {
- return new Point(A.x - B.x, A.y - B.y);
- }
- public static Point operator *(Point A, float b)
- {
- return new Point(A.x * b, A.y * b);
- }
- public static Point operator /(Point A, float b)
- {
- return new Point(A.x / b, A.y / b);
- }
- public override string ToString()
- {
- return "(" + x + "," + y + ")";
- }
- public override bool Equals(object obj)
- {
- if (obj.GetType() != typeof(Point))
- return false;
- Point other = (Point)obj;
- return other.x == x && other.y == y;
- }
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- }
- class MathX
- {
- static int WFAccuracy = 10;
- public static Point Weiszfeld (Point[] boxes)
- {
- Point P = new Point(0, 0);
- for (int n = 0; n < WFAccuracy; n++)
- {
- Point numerator = new Point(0, 0);
- float denominator = 0;
- for (int i = 0; i < boxes.Length; i++)
- {
- numerator += boxes[i] / (P - boxes[i]).Length;
- denominator += 1 / (P - boxes[i]).Length;
- }
- P = numerator / denominator;
- }
- return P;
- }
- static float GetMovTime (Point start, Point end)
- {
- float s = start.Distance(end);
- float t = (float)Math.Sqrt(2400 * s)/(2 * s);
- if (t * 1200 <= 250)
- return t;
- else
- {
- s -= 625 / 24f;
- return 5 / 24f + s / 250;
- }
- }
- public static Pair<float, string> GetScore (Point[] boxes, Point center)
- {
- List<Point> Xtemp = boxes.ToList();
- List<Point> Ytemp = new List<Point>(Xtemp);
- Point curPos = new Point(500, 500);
- Pair<float, string> min = new Pair<float, string>(float.PositiveInfinity, "");
- float curTime = 0;
- for (int x = -(int)Math.Floor(boxes.Length / 2f); x < (int)Math.Ceiling(boxes.Length / 2f) - 1; x++)
- {
- Point cur = center + Point.right * 100 * x;
- float dist = cur.Distance(Point.zero);
- if (dist <= 300 || dist > 1200)
- {
- curTime = float.PositiveInfinity;
- break;
- }
- Xtemp = Xtemp.OrderBy(box => -box.Distance(cur)).ToList();
- if (cur.Distance(Xtemp[0]) == 0)
- continue;
- curTime += GetMovTime(curPos, Xtemp[0]) + GetMovTime(Xtemp[0], cur) + 4;
- curPos = cur;
- Xtemp.RemoveAt(0);
- }
- if (curTime != float.PositiveInfinity)
- {
- min.a = curTime;
- min.b = "X";
- }
- curTime = 0;
- curPos = Point.one * 500;
- for (int y = -(int)Math.Floor(boxes.Length / 2f); y < (int)Math.Ceiling(boxes.Length / 2f) - 1; y++)
- {
- Point cur = center + Point.up * 100 * y;
- float dist = cur.Distance(Point.zero);
- if (dist <= 300 || dist > 1200)
- {
- curTime = float.PositiveInfinity;
- break;
- }
- Ytemp = Ytemp.OrderBy(box => -box.Distance(cur)).ToList();
- if (cur.Distance(Ytemp[0]) == 0)
- continue;
- curTime += GetMovTime(curPos, Ytemp[0]) + GetMovTime(Ytemp[0], cur) + 4;
- curPos = cur;
- Ytemp.RemoveAt(0);
- }
- if (curTime < min.a)
- {
- min.a = curTime;
- min.b = "Y";
- }
- return min;
- }
- public static bool LineIntersectCirlce (Pair<Point, Point> line, Point center, float r)
- {
- float x = line.a.Distance(line.b);
- return ((center.x - line.a.x) * (line.b.y - line.a.y) - (center.y - line.a.y) * (line.b.x - line.a.x)) / x <= r;
- }
- public static bool LineIntersectLine (Pair<Point, Point> line, Pair<Point, Point> line2)
- {
- Point p = line.a;
- Point r = line.b - p;
- Point q = line2.a;
- Point s = line2.b - q;
- float t = (q - p).Cross(s) / r.Cross(s);
- float u = (q - p).Cross(r) / (r.Cross(s));
- if (r.Cross(s) == 0 && (q - p).Cross(r) == 0)
- return false;
- if (r.Cross(s) == 0 && (q - p).Cross(r) != 0)
- return false;
- if (r.Cross(s) != 0 && t >= 0 && t <= 1 && u >= 0 && u <= 1)
- return true;
- return false;
- }
- public static bool LineIntersectsBox (Pair<Point, Point> line, Point box)
- {
- Point A, B, C, D;
- A = box += Point.one * 50;
- B = box += new Point(50, -50);
- C = box -= Point.one * 50;
- D = box -= new Point(50, -50);
- Pair<Point, Point> lineA, lineB, lineC, lineD;
- lineA = new Pair<Point, Point>(A, B);
- lineB = new Pair<Point, Point>(B, C);
- lineC = new Pair<Point, Point>(C, D);
- lineD = new Pair<Point, Point>(D, A);
- Func<Pair<Point, Point>, bool> quickTest = l => LineIntersectLine(line, l);
- return quickTest(lineA) || quickTest(lineB) || quickTest(lineC) || quickTest(lineD);
- }
- public static float Sec (float x)
- {
- return 1 / (float)Math.Sin(x);
- }
- public static Point RayRayIntersect (Point A, Point B, float dirA, float dirB)
- {
- Point dirVB = new Point((float)Math.Cos(dirA), (float)Math.Sin(dirA));
- Point dirVA = new Point((float)Math.Cos(dirB), (float)Math.Sin(dirB));
- float u = ((B.y - A.y) * dirVB.x - (B.x - A.x) * dirVB.y) / (dirVB.x * dirVA.y - dirVB.y * dirVA.x);
- float v = ((B.y - A.y) * dirVA.x - (B.x - A.x) * dirVA.y) / (dirVB.x * dirVA.y - dirVB.y * dirVA.x);
- if ((A + dirVA * u).Distance(B + dirVB * v) > 0.01)
- return null;
- return A + dirVA * u;
- }
- public static Point FindTangentIntersection (Point A, Point B, Point center, float r)
- {
- float A1 = (float)Math.Asin(r / A.Distance(center));
- float angAC = (float)Math.Atan((center - A).y / (center - A).x);
- float angA1 = angAC - A1;
- float angA2 = angAC + A1;
- float B1 = (float)Math.Asin(r / B.Distance(center));
- float angBC = (float)Math.Atan((center - B).y / (center - B).x);
- float angB1 = angBC - B1;
- float angB2 = angBC + B1;
- Point T1 = RayRayIntersect(A, B, angA1, angB2);
- Point T2 = RayRayIntersect(A, B, angA2, angB1);
- T1 = new Point(T1.y, T1.x);
- T2 = new Point(T2.y, T2.x);
- Func<Point, float> quickCheck = p => { return A.Distance(p) + p.Distance(B); };
- if (quickCheck(T1) < quickCheck(T2))
- return T1;
- return T2;
- }
- }
- public class Pair <U, T>
- {
- public U a;
- public T b;
- public Pair (U a, T b)
- {
- this.a = a;
- this.b = b;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement