コード例 #1
0
ファイル: Program.cs プロジェクト: bjtaylor1/projecteuler
        static void Main(string[] args)
        {
            var cfs      = new CompositeFactors();
            var cfHashes = new C5.HashSet <int>();
            var b        = ImmutableSortedDictionary.CreateBuilder <int, int>();

            b.Add(0, Limit);
            CompositeFactor initial = new CompositeFactor(b);

            cfs.Add(initial);
            cfHashes.Add(initial.GetHashCode());

            for (int i = 0; i < Limit - 1; i++)
            {
                if (i % 100 == 0)
                {
                    Console.Write($"{(double)i / Limit:P1}, count = {cfs.Count} / {cfs.HashCount}\r");
                }
                var firstUnexpanded = cfs.DeleteMin();
                var expansions      = firstUnexpanded.Expand();
                foreach (var e in expansions)
                {
                    cfs.Add(e);
                }
                cfs.Add(new CompositeFactor(firstUnexpanded.Factors.ToBuilder().Increase(0)));
            }
            Console.Out.WriteLine($"\nFound {Limit}th factor");
            var   answerFactor = cfs.DeleteMin();
            mpz_t result       = answerFactor.Factors.Aggregate(new mpz_t(1), (res, f) => res * new mpz_t(Primes.Values[f.Key]).Power(f.Value)).Mod(123454321);

            Console.WriteLine(result);
        }
コード例 #2
0
 /// <summary>
 /// Adds triangle. If his Vectors should align with another triangles vectors, they need to be the same instances
 /// </summary>
 /// <param name="trngls"></param>
 public void AddTriangleByReference(Triangle trngls)
 {
     C5.HashSet <Triangle> incidence = new C5.HashSet <Triangle>();
     triangleIncidence.Add(trngls, new ArrayList <Triangle>());
     //register each vertex
     foreach (Vector3 vertex in trngls.vertices)
     {
         if (!vertex2Triangle.ContainsKey(vertex))
         {
             vertex2Triangle[vertex] = new ArrayList <Triangle>();
         }
         else
         {
             foreach (Triangle triangle in vertex2Triangle[vertex])
             {
                 if (incidence.Contains(triangle))  //already found a common vertex
                 {
                     triangleIncidence[triangle].Add(trngls);
                     triangleIncidence[trngls].Add(triangle);
                 }
                 else
                 {
                     incidence.Add(triangle);  //first common vertex found -> remember it
                 }
             }
         }
         vertex2Triangle[vertex].Add(trngls);
     }
 }
コード例 #3
0
ファイル: BasesTest.cs プロジェクト: linearregression/C5
 public void UnseqequalityComparerViaBuilder2()
 {
     SCG.IEqualityComparer <C5.HashSet <int> > h = C5.EqualityComparer <C5.HashSet <int> > .Default;
     C5.HashSet <int> s = new C5.HashSet <int>();
     s.Add(1); s.Add(2); s.Add(3);
     Assert.AreEqual(CHC.unsequencedhashcode(1, 2, 3), h.GetHashCode(s));
 }
コード例 #4
0
        public void HandleEventPoints(C5.HashSet <EventPoint> eventPoints)
        {
            if (eventPoints.Count == 0)
            {
                return;
            }

            var array = eventPoints.ToArray();

            MoveSweepLineTo(array[0]);

            if (eventPoints.Count > 1) // Jeśli w zestawie jest więcej niż jeden element, muszą się one ze sobą przecinać
            {
                for (var i = 0; i < array.Length - 1; i++)
                {
                    for (var j = i + 1; j < array.Length; j++)
                    {
                        CheckIntersection(array[i], array[j]);
                    }
                }
            }

            foreach (var ep in eventPoints)
            {
                HandleEventPoint(ep);
            }
        }
コード例 #5
0
        public C5.HashSet <EventPoint> DeleteMin() // Pobierz i zwróć najmniejszy element kolejki
        {
            if (isEmpty())
            {
                throw new Exception("Kolejka jest pusta");
            }

            var entry = _events.DeleteMin();
            var hs    = new C5.HashSet <EventPoint>();

            hs.AddAll(entry.Value);
            return(hs);
        }
コード例 #6
0
        private void CheckIntersection(EventPoint ep1, EventPoint ep2) // Sprawdza czy istnieje przecięcie pomiędzy dwoma zdarzeniami
        {
            if (CurrentSweepPoint == null)
            {
                return;
            }
            var currentSweepPoint = (PointFr)CurrentSweepPoint;

            if (ep1 == null || ep2 == null || ep1.Type == EventPointType.Intersection || ep2.Type == EventPointType.Intersection) // Zatrzymaj jeżeli conajmniej jedno ze zdarzeń jest puste lub jest przecięciem
            {
                return;
            }
            if (ep2.Segment == null || ep1.Segment == null)
            {
                throw new ArgumentException("Wartość ep1.Segment i ep2.Segment nie może być pusta");
            }

            var pNullable = ((LineSegmentFr)ep1.Segment).Intersection((LineSegmentFr)ep2.Segment); // Znajdź punkt przecięcia pomiędzy liniami zdarzeń

            if (pNullable == null)
            {
                return;
            }
            var p = (PointFr)pNullable;

            var existing = new C5.HashSet <EventPoint>();

            if (_intersections.ContainsKey(p))
            {
                existing = _intersections[p]; // Dodaj przecięcie do słownika
                _intersections.Remove(p);
            }

            existing.Add(ep1);
            existing.Add(ep2);
            _intersections.Add(p, existing);

            if (SweepLineValue == null)
            {
                throw new ArgumentException("Wartość miotły nie może być pusta");
            }

            var sweepLineValue = (LineFr)SweepLineValue;

            if (p.IsRightOf(sweepLineValue) || (sweepLineValue.Contains(p) && p.Y > currentSweepPoint.Y)) // Jeśli przecięcie jest po prawej stronie miotły lub na miotle i powyzej obecnego zdarzenia, dodaj do kolejki
            {
                var intersection = new EventPoint(p, EventPointType.Intersection, (LineSegmentFr?)null, this);
                EventQueue.Insert(p, intersection);
            }
        }
コード例 #7
0
        private readonly TreeDictionary <PointFr, C5.LinkedList <EventPoint> > _events; // Posortowana mapa punktów i odpowiadających im zdarzeń

        public EventQueue(C5.HashSet <LineSegmentFr> segments, SweepLine sweepLine)     // Tworzy nową kolejkę zdarzeń przy użyciu zestawu odcinków
        {
            if (segments.Count <= 0)
            {
                throw new ArgumentException($"Kolekcja {nameof(segments)} nie może być pusta");
            }

            _events = new TreeDictionary <PointFr, C5.LinkedList <EventPoint> >(new PointFrXThenYComparer());

            var minY      = Fraction.PositiveInfinity;
            var maxY      = Fraction.NegativeInfinity;
            var minDeltaX = Fraction.PositiveInfinity;
            var xs        = new TreeSet <Fraction>();

            foreach (var s in segments)
            {
                xs.Add(s.StartPoint.X);
                xs.Add(s.EndPoint.X);
                if (s.MinY < minY)
                {
                    minY = s.MinY;
                }
                if (s.MaxY > maxY)
                {
                    maxY = s.MaxY;
                }

                Insert(s.StartPoint, new EventPoint(s.StartPoint, EventPointType.Left, s, sweepLine));
                Insert(s.EndPoint, new EventPoint(s.EndPoint, EventPointType.Right, s, sweepLine));
            }

            var xsArray = xs.ToArray();

            for (var i = 1; i < xsArray.Length; i++)
            {
                var tempDeltaX = xsArray[i] - xsArray[i - 1];
                if (tempDeltaX < minDeltaX)
                {
                    minDeltaX = tempDeltaX;
                }
            }

            var deltaY = maxY - minY;
            var slope  = deltaY / minDeltaX * -1;                                     // * 1000

            sweepLine.SweepLineValue = new LineFr(PointFr.Origin, new PointFr(0, 1)); // slope, PointFr.Origin
            sweepLine.EventQueue     = this;                                          // Porzuciłem pomysł dynamicznego zmianu nachylenia miotły, ponieważ wymagało to obliczania dużych wartości przecięć z osiami wykresu dla prostej przy użyciu Ułamków (StackOverflowException)
        }
コード例 #8
0
        public Nav2dNode findClosestAccessibleNodeInGrid(Vector3Int cellPos, Vector3 targetPos)
        {
            Nav2dNode node = null;

            C5.HashSet <Vector3Int> explored = new C5.HashSet <Vector3Int>();
            Queue <Vector3Int>      opened   = new Queue <Vector3Int>();

            opened.Enqueue(cellPos);

            // dont try to long
            for (int i = 0; i < 20; i++)
            {
                Vector3Int current = opened.Dequeue();
                Nav2dCell  cell    = FindNavCellAtPosition(current);

                node = cell?.findClosestAccessibleNodeInCell(targetPos);

                if (node != null)
                {
                    break;
                }

                explored.Add(current);

                Vector3Int[] neighbors =
                {
                    current + new Vector3Int(0,   1, 0),
                    current + new Vector3Int(0,  -1, 0),
                    current + new Vector3Int(-1,  0, 0),
                    current + new Vector3Int(1,   0, 0)
                };

                foreach (var n in neighbors)
                {
                    if (!explored.Contains(n))
                    {
                        opened.Enqueue(n);
                    }
                }
            }
            return(node);
        }
コード例 #9
0
    /// <summary>
    /// Optimizes navmesh by deleting some triangles
    /// </summary>
    /// <param name="itm"></param>
    public IEnumerator OptimizeMesh()
    {
        C5.HashSet <Vector3>  open  = new C5.HashSet <Vector3>();
        C5.HashSet <Triangle> openT = new C5.HashSet <Triangle>();
        open.AddAll(vertex2Triangle.Keys);

        while (!open.IsEmpty)    //loop through all vertices

        {
            Vector3 current = open.Pop();

            if (vertex2Triangle[current].Count < 3) //if less than 3, they cannot form a "circle"
            {
                continue;
            }

            openT.Clear();
            openT.AddAll(vertex2Triangle[current]);

            //Debug.Log("Opening " + current);

            //start at arbitrary triangle
            C5.IList <Triangle> circle = new C5.ArrayList <Triangle>();
            circle.Add(openT.Pop());

            //find connected circle
            while (openT.Count > 0)
            {
                Triangle[] circleElement = openT.Intersect(triangleIncidence[circle.Last]).ToArray();
                if (circleElement.Length < 1) //no candidate - break
                {
                    break;
                }
                circle.Add(circleElement[0]);

                openT.Remove(circle.Last);
            }
            if (openT.Count == 0 && triangleIncidence[circle.Last].Contains(circle.First))
            {
                //Debug.Log( "Unbroken: "+current );
                //check height differences
                bool isFlatEnough = true;
                foreach (Triangle trg in vertex2Triangle[current])
                {
                    foreach (Vector3 vct in trg.vertices)
                    {
                        if (Mathf.Abs(vct.y - current.y) > maxHeightDifference)
                        {
                            isFlatEnough = false;
                        }
                    }
                }
                if (!isFlatEnough)
                {
                    continue;
                }

                ArrayList <Vector3> vctList = new ArrayList <Vector3>();

                //remove old triangles
                foreach (Triangle trg in circle)   //ToArray() is to create a buffer (to prevent concurrent modification)
                {
                    RemoveTriangle(trg);
                    for (int i = 0; i < 3; i++)
                    {
                        //find the CURRENT vertex - the one that is beeing removed
                        if (trg.vertices[i] == current)
                        {
                            //add the NEXT to the list
                            vctList.Add(trg.vertices[(i + 1) % 3]);
                        }
                    }
                }

                if (Outline.IsClockwise(vctList))
                {
                    vctList.Reverse();
                }
                //build new triangles and add them
                foreach (IEnumerable <int> newTriangles in Utils.TriangulatePolygon(vctList, Enumerable.Range(0, vctList.Count)).Chunks(3))
                {
                    Triangle newTriag = new Triangle(newTriangles.Select(x => vctList[x]).ToArray());
                    AddTriangleByReference(newTriag);
                }

                //reopen used vertices
                //open.AddAll(vctList); - maybe not necessary????
                //yield return new WaitForSeconds(1);
                yield return(null);
            }
        }
    }
コード例 #10
0
    public IEnumerable <Mesh> ExtractMeshes()
    {
        List <Mesh> meshes = new List <Mesh>();

        C5.HashSet <Triangle> untouched = new C5.HashSet <Triangle>();
        untouched.AddAll(triangleIncidence.Keys);

        Queue <Triangle> open = new Queue <Triangle>();



        //the mesh that is beeing built
        List <Vector3>            vertices      = new List <Vector3>();
        Dictionary <Vector3, int> vertexToIndex = new Dictionary <Vector3, int>();
        List <int> indices = new List <int>();

        while (!untouched.IsEmpty)
        {
            if (open.Count == 0)  //empty - open on a new slot
            {
                open.Enqueue(untouched.First());
                untouched.Remove(open.First());
            }

            if (vertices.Count > 60000)  //too many - split meshes
            {
                Mesh msh = new Mesh();
                msh.vertices  = vertices.ToArray();
                msh.triangles = indices.ToArray();
                meshes.Add(msh);
                vertices.Clear();
                vertexToIndex.Clear();
                indices.Clear();
            }

            //one step of BFS
            Triangle current = open.Dequeue();
            foreach (Triangle expand in triangleIncidence[current])
            {
                if (untouched.Contains(expand))
                {
                    open.Enqueue(expand);
                    untouched.Remove(expand);
                }
            }
            //add to mesh
            for (int i = 0; i < 3; i++)
            {
                if (vertexToIndex.ContainsKey(current.vertices[i]))
                {
                    indices.Add(vertexToIndex[current.vertices[i]]);
                }
                else
                {
                    vertices.Add(current.vertices[i]);
                    vertexToIndex[current.vertices[i]] = vertices.Count - 1;
                    indices.Add(vertices.Count - 1);
                }
            }
        }

        //buuild last mesh
        Mesh msh2 = new Mesh();

        msh2.vertices  = vertices.ToArray();
        msh2.triangles = indices.ToArray();
        meshes.Add(msh2);

        return(meshes);
    }