Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
    /// <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();
    }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
            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);
            }
Exemplo n.º 5
0
            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);
            }
Exemplo n.º 6
0
        /// <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;
        }