public override object Task2() { const int turns = 10000000; const int maxVal = 1000000; Dictionary <int, CircularLinkedListNode <int> > lookupTable = new Dictionary <int, CircularLinkedListNode <int> >(); CircularLinkedList <int> cups = new CircularLinkedList <int>(); foreach (int i in ParseInput()) { cups.AddLast(i); lookupTable[cups.Last.Value] = cups.Last; } for (int i = 10; i <= maxVal; i++) { cups.AddLast(i); lookupTable[cups.Last.Value] = cups.Last; } CircularLinkedListNode <int> current = cups.First; CircularLinkedListNode <int>[] pickedUpCups = new CircularLinkedListNode <int> [3]; for (int _ = 0; _ < turns; _++) { for (int i = 0; i < pickedUpCups.Length; i++) { pickedUpCups[i] = current.Next; cups.Remove(pickedUpCups[i]); } CircularLinkedListNode <int> destNode = lookupTable[current.Value == 1 ? maxVal : current.Value - 1]; while (Array.IndexOf(pickedUpCups, destNode) != -1) { destNode = lookupTable[destNode.Value == 1 ? maxVal : destNode.Value - 1]; } for (int i = pickedUpCups.Length - 1; i >= 0; i--) { cups.AddAfter(destNode, pickedUpCups[i]); } current = current.Next; } CircularLinkedListNode <int> one = lookupTable[1]; return((ulong)one.Next.Value * (ulong)one.Next.Next.Value == 5403610688); }
/// <summary> /// ici est appelé directement depuis l'un des link /// </summary> public void AddLink(int index) { if (linkCount == linkCountMax || linkBreaked) { return; } if (index > listCircular.Count) { Debug.LogError("index out of range: " + index); return; } LinkCountAdd(); GameObject closestLink = listCircular[index].Value; if (!closestLink) { listCircular.RemoveAllEmpty(); closestLink = listCircular[index].Value; } GameObject newLink = ObjectsPooler.Instance.SpawnFromPool(GameData.PoolTag.Link, closestLink.transform.position, Quaternion.identity, parentLink); /*SpringJoint jointLink = */ newLink.transform.GetOrAddComponent <SpringJoint>(); ChangeMeshRenrered(newLink.GetComponent <MeshRenderer>()); //si l'index n'est pas le dernier (l'un des 2 gros objet), on peut le créé après if (index != listCircular.Count - 1) { listCircular.AddAfter(listCircular[index], newLink); SetupLink(newLink, index + 1); ChangeThisPring(index); ChangeThisPring(index + 1); } else { Debug.Log("ICI on ajoute sur le dernier ???"); listCircular.AddBefore(listCircular[index], newLink); SetupLink(newLink, index - 0); ChangeThisPring(index - 1); ChangeThisPring(index - 0); } ChangeParamJointWhenAdding(1); CreateFakeListForDebug(); }
public override object Task1() { int rotationSteps = int.Parse(rawInput); CircularLinkedList <int> circle = new CircularLinkedList <int>(); circle.AddLast(0); for (int i = 1; i < 2018; i++) { circle.MoveHeadRight(rotationSteps); circle.AddAfter(circle.First, i); circle.MoveHeadRight(1); } return(circle.First.Next.Value); }
public override void ModifyLav(AngularBisectorNetwork network) { Debug.Assert(nodeA.List == nodeB.List); CircularLinkedList <Vertex> lav = nodeA.List; Vertex vA = nodeA.Value; Vertex vB = nodeB.Value; // * Create a new Vertex V with the coordinates of the intersection I Vertex v = new Vertex(this.Position); // * insert the new vertex into the LAV. That means connect it with the predecessor // of Va and the successor of Vb in the LAV CircularLinkedListNode <Vertex> nodeV = new CircularLinkedListNode <Vertex>(v); lav.AddAfter(nodeA, nodeV); lav.Remove(nodeA); lav.Remove(nodeB); // * link the new node V with the appropriate edges ea and eb (pointed to by vertices // Va and Vb // TODO: This needs some work for start and end nodes. What should happen? v.inEdge = vA.inEdge; v.outEdge = vB.outEdge; // f. for the new node V, created from I, compute: // * the new angle bisector b between the line segments ea and eb, and // TODO: This bisector sometimes needs to be revered! But under what circumstances? Direction2D bisector = AngularBisector(nodeV.Value.inEdge, nodeV.Value.outEdge); // Determine whether the triangle A B V has an acute or obtuse angle at V // this is used to determine the direction of the bisector Triangle2D triangle = new Triangle2D(vA.Position, vB.Position, v.Position); if (triangle.AngleC > (Math.PI / 2.0)) { bisector = -bisector; } nodeV.Value.Bisector = new Ray2D(nodeV.Value.Bisector.Source, bisector); // * the intersections of this bisector with the bisectors starting from the neighbour vertices in // the LAV in the same way as in the step 1c // * store the nearer intersection (if it exists) in the priority queue network.EnqueueNearestBisectorIntersection(lav, nodeV); }
public override void ModifyLav(AngularBisectorNetwork network) { Debug.Assert(nodeV.List != null); CircularLinkedList <Vertex> lav1 = nodeV.List; // * Create two new nodes V1 and V2 with the same co-ordinates as the intersection point I CircularLinkedListNode <Vertex> nodeV1 = new CircularLinkedListNode <Vertex>(new Vertex(this.Position)); CircularLinkedListNode <Vertex> nodeV2 = new CircularLinkedListNode <Vertex>(new Vertex(this.Position)); // * Search the opposite edge in SLAV sequentially CircularLinkedListNode <Vertex> oppositeNode = lav1.FindPair(delegate(Vertex va, Vertex vb) { // Ignore testing againt the in and out edges of V if (va == V || vb == V) { return(false); } // and the candiate "opposite" line Line2D oppositeLine = new Line2D(va.outEdge.source.Position, va.outEdge.target.Position); // TODO: Check which way round these lines are - so the the positive side defines our zone of interest Line2D oppositeBoundary1 = va.Bisector.SupportingLine.Opposite; Line2D oppositeBoundary2 = vb.Bisector.SupportingLine; OrientedSide sideA = oppositeBoundary1.Side(this.Position); OrientedSide sideB = oppositeLine.Side(this.Position); OrientedSide sideC = oppositeBoundary2.Side(this.Position); //return sideA == OrientedSide.Negative && sideB == OrientedSide.Negative && sideC == OrientedSide.Negative; return(sideA == OrientedSide.Negative && sideB == OrientedSide.Negative && sideC == OrientedSide.Negative); }); // TODO: Is this legitimate? if (oppositeNode == null) { Debug.Assert(false); return; } // oppositeNode is Y in the paper Debug.Assert(oppositeNode != null); // * insert both new nodes into the SLAV (break one LAV into two parts). Vertex V1 will be // interconnected between the predecessor of V and the vertex/node which is an end point of // the opposite line segment. V2 will be connected between the successor of V and the vertex/ // node which is a starting point of the opposite line segment. This step actually splits the // polygon shape into two parts. // Set up nodes according to the naming conventions in the Felkel et al paper. CircularLinkedListNode <Vertex> nodeY = oppositeNode; CircularLinkedListNode <Vertex> nodeX = oppositeNode.Next; CircularLinkedListNode <Vertex> nodeM = nodeV.Previous; CircularLinkedListNode <Vertex> nodeN = nodeV.Next; // The LinkedList is split into two parts. The first part remains in the original list, // the second part is placed into a new list. CircularLinkedList <Vertex> lav2 = network.CreateLav(); // We search the list for either M or Y, whichever comes first. This tells us which // algorithm to use to split the lav in two. CircularLinkedListNode <Vertex> found = lav1.FindNode(node => node == nodeM || node == nodeY); lav1.Remove(nodeV); // Splice nodes from lav1 into lav2 Debug.Assert(found != null); if (found == nodeY) { // Splice two sections of lav1 into lav2 with V1 and V2 // TODO: We have four nodes in a linked list defining two ranges First--->Y and N--->Last // These ranges may be non-overlapping, or may be overlapping in some way. e.g. Y may come after N. // 1) Find none overlapping range or ranges // 2) Copy the range(s) to lav2 // 3) Insert nodeV2 into the correct place in lav2 after Y // Another alternative 2 // 1. Is the break in the list between N and Y? bool continuousNY = null != lav1.FindNodeFrom(nodeN, node => node == nodeY); if (continuousNY) { lav2.AddLast(nodeV2); lav2.SpliceLast(nodeN, nodeY); lav2.IsCircular = true; } else // !continuousNY { lav2.SpliceLast(lav1.First, nodeY); lav2.AddLast(nodeV2); lav2.SpliceLast(nodeN, lav1.Last); lav2.IsCircular = lav1.IsCircular; } // Alternative approach //// 1. Remember whether lav1 is circular //bool lav1Circularity = lav1.IsCircular; //// 1a. Determine whether lav2 should be circular- by whether it is continuous between nodeN and nodeY //bool continuousNY = null != lav1.FindNodeFrom(nodeN, node => node == nodeY); //bool lav2Circularity = lav1Circularity || continuousNY; //// 2. Make lav1 circular, so we can safely iterate from N to Y irrespective of the location of the list head //lav1.IsCircular = true; //// 3. Add nodeV2 into lav2 //lav2.AddLast(nodeV2); //// 4. Splice from N to Y into Lav2 //lav2.SpliceLast(nodeN, nodeY); //// 5. Restore the circularity of lav1 and lav2 //lav1.IsCircular = lav1Circularity; //lav2.IsCircular = lav2Circularity; // X--->M->V1 if (lav1.Count > 0) // <--- Is this needed? { Debug.Assert(lav1.First == nodeX); Debug.Assert(lav1.Last == nodeM); lav1.AddLast(nodeV1); lav1.IsCircular = true; } } else { Debug.Assert(found == nodeM); // Splice one section of lav1 into lav2 // N--->Y->V2 lav2.SpliceFirst(nodeN, nodeY); lav2.AddLast(nodeV2); // First--->M->V2->X--->Last if (lav1.Count > 0) { Debug.Assert(nodeM.Next == nodeX); lav1.AddAfter(nodeM, nodeV1); } } // * link the new nodes V1 and V2 with the appropriate edges nodeV1.Value.inEdge = V.inEdge; nodeV1.Value.outEdge = nodeY.Value.outEdge; nodeV2.Value.inEdge = nodeY.Value.outEdge; nodeV2.Value.outEdge = V.outEdge; // f. for both nodes V1 and V2: // * compute the new angle bisectors betwenne the line segment linked to them is step 2e nodeV1.Value.Bisector = new Ray2D(nodeV1.Value.Bisector.Source, AngularBisector(nodeV1.Value.inEdge, nodeV1.Value.outEdge)); nodeV2.Value.Bisector = new Ray2D(nodeV2.Value.Bisector.Source, AngularBisector(nodeV2.Value.inEdge, nodeV2.Value.outEdge)); // * compute the intersections of these bisectors with the bisectors starting at their neighbour // vertices according to the LAVs (e.g. at points N and Y and M and X in fig 6a.), the same // way as in step 1c. New intersection points of both types may occur // * store the nearest intersection into the priority queue // TODO: [ Does this mean the nearest for V1 and the nearest for V2, or only the nearest of them both? ] network.EnqueueNearestBisectorIntersection(lav1, nodeV1); network.EnqueueNearestBisectorIntersection(lav2, nodeV2); }
/// <summary> /// /// </summary> /// <param name="subject">Первый контур.</param> /// <param name="clip">Второй контур.</param> /// <param name="operation">Операция, проводимая над контурами.</param> /// <returns></returns> public static ICollection<ICollection<Vector2>> Process(CircularLinkedList<Vector2> subject, CircularLinkedList<Vector2> clip, Operation operation) { LinkedListNode<Vector2> curSubject = subject.First; Dictionary<Vector2, Pair<Vector2>> intersections = new Dictionary<Vector2, Pair<Vector2>>(); List<ICollection<Vector2>> polygons = new List<ICollection<Vector2>>(); if (Misc.AreEqual<Vector2>(subject, clip)) { switch (operation) { case Operation.Union: polygons.Add(subject); return polygons; break; case Operation.Intersect: polygons.Add(subject); return polygons; break; case Operation.Difference: return polygons; break; default: break; } } while (curSubject != subject.Last) { LinkedListNode<Vector2> curClip = clip.First; while (curClip != clip.Last) { Vector2 intersectionPoint; if (IntersectSegment(curSubject.Value, curSubject.Next.Value, curClip.Value, curClip.Next.Value, out intersectionPoint)) { subject.AddAfter(curSubject, intersectionPoint); clip.AddAfter(curClip, intersectionPoint); intersections.Add(intersectionPoint, new Pair<Vector2>(curClip.Value, curClip.Next.Value)); } curClip = curClip.Next; } curSubject = curSubject.Next; } CircularLinkedList<Vector2> entering = new CircularLinkedList<Vector2>(); CircularLinkedList<Vector2> exiting = new CircularLinkedList<Vector2>(); MakeEnterExitList(subject, clip, intersections, entering, exiting); subject.RemoveLast(); clip.RemoveLast(); Traverse(subject, clip, entering, exiting, polygons, operation); if (polygons.Count == 0) { switch (operation) { case Operation.Union: polygons.Add(subject); polygons.Add(clip); break; case Operation.Intersect: break; case Operation.Difference: polygons.Add(subject); break; default: break; } } return polygons; }