예제 #1
0
        public static void IEnumerable_Testing <TStack>()
            where TStack : IStack <int>, new()
        {
            {             // push only
                int[]        values = { 0, 1, 2, 3, 4, 5, };
                IStack <int> stack  = new TStack();
                values.Stepper(i => stack.Push(i));
#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available
                Assert.IsTrue(System.Linq.Enumerable.Count(stack) == values.Length);
#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available
                ISet <int> set = SetHashLinked.New <int>();
                values.Stepper(i => set.Add(i));
                foreach (int i in stack)
                {
                    Assert.IsTrue(set.Contains(i));
                    set.Remove(i);
                }
                Assert.IsTrue(set.Count == 0);
            }
            {             // push + pop
                int[]        values         = { 0, 1, 2, 3, 4, 5, };
                int[]        expectedValues = { 0, 1, 2, 3, };
                IStack <int> stack          = new TStack();
                values.Stepper(i => stack.Push(i));
                stack.Pop();
                stack.Pop();
#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available
                Assert.IsTrue(System.Linq.Enumerable.Count(stack) == expectedValues.Length);
#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available
                ISet <int> set = SetHashLinked.New <int>();
                expectedValues.Stepper(i => set.Add(i));
                foreach (int i in stack)
                {
                    Assert.IsTrue(set.Contains(i));
                    set.Remove(i);
                }
                Assert.IsTrue(set.Count == 0);
            }
            {             // push + pop
                int[]        values = { 0, 1, 2, 3, 4, 5, };
                IStack <int> stack  = new TStack();
                values.Stepper(i => stack.Push(i));
                values.Stepper(i =>
                {
                    stack.Pop();
                    stack.Push(i);
                });
#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available
                Assert.IsTrue(System.Linq.Enumerable.Count(stack) == values.Length);
#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available
                ISet <int> set = SetHashLinked.New <int>();
                values.Stepper(i => set.Add(i));
                foreach (int i in stack)
                {
                    Assert.IsTrue(set.Contains(i));
                    set.Remove(i);
                }
                Assert.IsTrue(set.Count == 0);
            }
        }
예제 #2
0
        public static void IEnumerable_Testing <TQueue>()
            where TQueue : IQueue <int>, new()
        {
            {             // enqueue only
                int[]        values = { 0, 1, 2, 3, 4, 5, };
                IQueue <int> queue  = new TQueue();
                values.Stepper(i => queue.Enqueue(i));
#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available
                Assert.IsTrue(System.Linq.Enumerable.Count(queue) == values.Length);
#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available
                ISet <int> set = SetHashLinked.New <int>();
                values.Stepper(i => set.Add(i));
                foreach (int i in queue)
                {
                    Assert.IsTrue(set.Contains(i));
                    set.Remove(i);
                }
                Assert.IsTrue(set.Count == 0);
            }
            {             // enqueue + dequeue
                int[]        values         = { 0, 1, 2, 3, 4, 5, };
                int[]        expectedValues = { 2, 3, 4, 5, };
                IQueue <int> queue          = new TQueue();
                values.Stepper(i => queue.Enqueue(i));
                queue.Dequeue();
                queue.Dequeue();
#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available
                Assert.IsTrue(System.Linq.Enumerable.Count(queue) == expectedValues.Length);
#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available
                ISet <int> set = SetHashLinked.New <int>();
                expectedValues.Stepper(i => set.Add(i));
                foreach (int i in queue)
                {
                    Assert.IsTrue(set.Contains(i));
                    set.Remove(i);
                }
                Assert.IsTrue(set.Count == 0);
            }
            {             // enqueue + dequeue
                int[]        values = { 0, 1, 2, 3, 4, 5, };
                IQueue <int> queue  = new TQueue();
                values.Stepper(i => queue.Enqueue(i));
                values.Stepper(i =>
                {
                    queue.Dequeue();
                    queue.Enqueue(i);
                });
#pragma warning disable CA1829 // Use Length/Count property instead of Count() when available
                Assert.IsTrue(System.Linq.Enumerable.Count(queue) == values.Length);
#pragma warning restore CA1829 // Use Length/Count property instead of Count() when available
                ISet <int> set = SetHashLinked.New <int>();
                values.Stepper(i => set.Add(i));
                foreach (int i in queue)
                {
                    Assert.IsTrue(set.Contains(i));
                    set.Remove(i);
                }
                Assert.IsTrue(set.Count == 0);
            }
        }
예제 #3
0
 /// <summary>
 /// This constructor is for cloning purposes.
 /// <para>Runtime: O(n)</para>
 /// </summary>
 /// <param name="set">The set to clone.</param>
 internal SetHashLinked(SetHashLinked <T> set)
 {
     _equate = set._equate;
     _hash   = set._hash;
     _table  = (Node[])set._table.Clone();
     _count  = set._count;
 }
예제 #4
0
        [Benchmark] public void SetHashLinked_AddCompileTime()
        {
            ISet <Person> set = new SetHashLinked <Person, EquatePerson, HashPerson>();

            foreach (Person person in RandomTestData)
            {
                set.Add(person);
            }
        }
예제 #5
0
파일: Stack.cs 프로젝트: mangzee/Towel
 public static void IEnumerable_Testing <Stack>()
     where Stack : IStack <int>, new()
 {
     {             // push only
         int[]        values = { 0, 1, 2, 3, 4, 5, };
         IStack <int> stack  = new Stack();
         values.Stepper(i => stack.Push(i));
         Assert.IsTrue(System.Linq.Enumerable.Count(stack) == values.Length);
         ISet <int> set = new SetHashLinked <int>();
         values.Stepper(i => set.Add(i));
         foreach (int i in stack)
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         }
         Assert.IsTrue(set.Count == 0);
     }
     {             // push + pop
         int[]        values         = { 0, 1, 2, 3, 4, 5, };
         int[]        expectedValues = { 0, 1, 2, 3, };
         IStack <int> stack          = new Stack();
         values.Stepper(i => stack.Push(i));
         stack.Pop();
         stack.Pop();
         Assert.IsTrue(System.Linq.Enumerable.Count(stack) == expectedValues.Length);
         ISet <int> set = new SetHashLinked <int>();
         expectedValues.Stepper(i => set.Add(i));
         foreach (int i in stack)
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         }
         ;
         Assert.IsTrue(set.Count == 0);
     }
     {             // push + pop
         int[]        values = { 0, 1, 2, 3, 4, 5, };
         IStack <int> stack  = new Stack();
         values.Stepper(i => stack.Push(i));
         values.Stepper(i =>
         {
             stack.Pop();
             stack.Push(i);
         });
         Assert.IsTrue(System.Linq.Enumerable.Count(stack) == values.Length);
         ISet <int> set = new SetHashLinked <int>();
         values.Stepper(i => set.Add(i));
         foreach (int i in stack)
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         }
         ;
         Assert.IsTrue(set.Count == 0);
     }
 }
예제 #6
0
파일: Queue.cs 프로젝트: pfriesch/Towel
 public static void IEnumerable_Testing <Queue>()
     where Queue : IQueue <int>, new()
 {
     {             // enqueue only
         int[]        values = { 0, 1, 2, 3, 4, 5, };
         IQueue <int> queue  = new Queue();
         values.Stepper(i => queue.Enqueue(i));
         Assert.IsTrue(System.Linq.Enumerable.Count(queue) == values.Length);
         ISet <int> set = new SetHashLinked <int>();
         values.Stepper(i => set.Add(i));
         foreach (int i in queue)
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         }
         Assert.IsTrue(set.Count == 0);
     }
     {             // enqueue + dequeue
         int[]        values         = { 0, 1, 2, 3, 4, 5, };
         int[]        expectedValues = { 2, 3, 4, 5, };
         IQueue <int> queue          = new Queue();
         values.Stepper(i => queue.Enqueue(i));
         queue.Dequeue();
         queue.Dequeue();
         Assert.IsTrue(System.Linq.Enumerable.Count(queue) == expectedValues.Length);
         ISet <int> set = new SetHashLinked <int>();
         expectedValues.Stepper(i => set.Add(i));
         foreach (int i in queue)
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         }
         ;
         Assert.IsTrue(set.Count == 0);
     }
     {             // enqueue + dequeue
         int[]        values = { 0, 1, 2, 3, 4, 5, };
         IQueue <int> queue  = new Queue();
         values.Stepper(i => queue.Enqueue(i));
         values.Stepper(i =>
         {
             queue.Dequeue();
             queue.Enqueue(i);
         });
         Assert.IsTrue(System.Linq.Enumerable.Count(queue) == values.Length);
         ISet <int> set = new SetHashLinked <int>();
         values.Stepper(i => set.Add(i));
         foreach (int i in queue)
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         }
         ;
         Assert.IsTrue(set.Count == 0);
     }
 }
예제 #7
0
        public void Add()
        {
            ISet <int> addable  = new SetHashLinked <int>();
            int        addCount = AddCount;

            for (int i = 0; i < addCount; i++)
            {
                addable.Add(i);
            }
        }
예제 #8
0
 public static void Stepper_Testing <TQueue>()
     where TQueue : IQueue <int>, new()
 {
     {             // enqueue only
         int[]        values = { 0, 1, 2, 3, 4, 5, };
         IQueue <int> queue  = new TQueue();
         values.Stepper(i => queue.Enqueue(i));
         Assert.IsTrue(queue.Count == values.Length);
         ISet <int> set = SetHashLinked.New <int>();
         values.Stepper(i => set.Add(i));
         queue.Stepper(i =>
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         });
         Assert.IsTrue(set.Count == 0);
     }
     {             // enqueue + dequeue
         int[]        values         = { 0, 1, 2, 3, 4, 5, };
         int[]        expectedValues = { 2, 3, 4, 5, };
         IQueue <int> queue          = new TQueue();
         values.Stepper(i => queue.Enqueue(i));
         queue.Dequeue();
         queue.Dequeue();
         Assert.IsTrue(queue.Count == expectedValues.Length);
         ISet <int> set = SetHashLinked.New <int>();
         expectedValues.Stepper(i => set.Add(i));
         queue.Stepper(i =>
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         });
         Assert.IsTrue(set.Count == 0);
     }
     {             // enqueue + dequeue
         int[]        values = { 0, 1, 2, 3, 4, 5, };
         IQueue <int> queue  = new TQueue();
         values.Stepper(i => queue.Enqueue(i));
         values.Stepper(i =>
         {
             queue.Dequeue();
             queue.Enqueue(i);
         });
         Assert.IsTrue(queue.Count == values.Length);
         ISet <int> set = SetHashLinked.New <int>();
         values.Stepper(i => set.Add(i));
         queue.Stepper(i =>
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         });
         Assert.IsTrue(set.Count == 0);
     }
 }
예제 #9
0
        public void SetHashLinked_AddRunTime()
        {
            ISet <Person> set = SetHashLinked.New <Person>(
                (a, b) => a.Id == b.Id,
                x => x.Id.GetHashCode());

            foreach (Person person in RandomTestData !)
            {
                set.Add(person);
            }
        }
예제 #10
0
        public void Add()
        {
            ISet <Person> set = new SetHashLinked <Person>(
                (a, b) => a.Id == b.Id,
                x => x.Id.GetHashCode());

            foreach (Person person in RandomTestData)
            {
                set.Add(person);
            }
        }
예제 #11
0
 public static void Stepper_Testing <TStack>()
     where TStack : IStack <int>, new()
 {
     {             // push only
         int[]        values = { 0, 1, 2, 3, 4, 5, };
         IStack <int> stack  = new TStack();
         values.Stepper(i => stack.Push(i));
         Assert.IsTrue(stack.Count == values.Length);
         ISet <int> set = SetHashLinked.New <int>();
         values.Stepper(i => set.Add(i));
         stack.Stepper(i =>
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         });
         Assert.IsTrue(set.Count == 0);
     }
     {             // push + pop
         int[]        values         = { 0, 1, 2, 3, 4, 5, };
         int[]        expectedValues = { 0, 1, 2, 3, };
         IStack <int> stack          = new TStack();
         values.Stepper(i => stack.Push(i));
         stack.Pop();
         stack.Pop();
         Assert.IsTrue(stack.Count == expectedValues.Length);
         ISet <int> set = SetHashLinked.New <int>();
         expectedValues.Stepper(i => set.Add(i));
         stack.Stepper(i =>
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         });
         Assert.IsTrue(set.Count == 0);
     }
     {             // push + pop
         int[]        values = { 0, 1, 2, 3, 4, 5, };
         IStack <int> stack  = new TStack();
         values.Stepper(i => stack.Push(i));
         values.Stepper(i =>
         {
             stack.Pop();
             stack.Push(i);
         });
         Assert.IsTrue(stack.Count == values.Length);
         ISet <int> set = SetHashLinked.New <int>();
         values.Stepper(i => set.Add(i));
         stack.Stepper(i =>
         {
             Assert.IsTrue(set.Contains(i));
             set.Remove(i);
         });
         Assert.IsTrue(set.Count == 0);
     }
 }
예제 #12
0
        public void Remove_Testing()
        {
            {             // int
                const int  count = 100000;
                ISet <int> set   = SetHashLinked.New <int>();
                Iterate(count, i => set.Add(i));
                for (int i = 0; i < count; i += 3)
                {
                    set.Remove(i);
                }
                for (int i = 0; i < count; i++)
                {
                    if (i % 3 == 0)
                    {
                        Assert.IsFalse(set.Contains(i));
                    }
                    else
                    {
                        Assert.IsTrue(set.Contains(i));
                    }
                }
                Assert.IsFalse(set.Contains(-1));
                Assert.IsFalse(set.Contains(count));
            }

            {             // string
                const int     count = 100000;
                ISet <string> set   = SetHashLinked.New <string>();
                Iterate(count, i => set.Add(i.ToString()));
                for (int i = 0; i < count; i += 3)
                {
                    set.Remove(i.ToString());
                }
                for (int i = 0; i < count; i++)
                {
                    if (i % 3 == 0)
                    {
                        Assert.IsFalse(set.Contains(i.ToString()));
                    }
                    else
                    {
                        Assert.IsTrue(set.Contains(i.ToString()));
                    }
                }
                Assert.IsFalse(set.Contains((-1).ToString()));
                Assert.IsFalse(set.Contains(count.ToString()));
            }
        }
예제 #13
0
파일: Step.cs 프로젝트: Thaina/Towel
        /// <summary>Determines if the data contains any duplicates.</summary>
        /// <typeparam name="T">The generic type of the data.</typeparam>
        /// <param name="stepper">The stepper function for the data.</param>
        /// <param name="equate">An equality function for the data</param>
        /// <param name="hash">A hashing function for the data.</param>
        /// <returns>True if the data contains duplicates. False if not.</returns>
        /// <remarks>Use the StepperBreak overload if possible. It is more effiecient.</remarks>
        public static bool ContainsDuplicates <T>(this Stepper <T> stepper, Equate <T> equate, Hash <T> hash)
        {
            bool duplicateFound   = false;
            SetHashLinked <T> set = new SetHashLinked <T>(equate, hash);

            stepper(x =>
            {
                if (set.Contains(x))
                {
                    duplicateFound = true;
                }
                else
                {
                    set.Add(x);
                }
            });
            return(duplicateFound);
        }
예제 #14
0
파일: Program.cs 프로젝트: jfevia/Towel
        public static void Main(string[] args)
        {
            // Settings
            //
            // You can control what benchmarking is done by commenting out
            // tags. A benchmark will only run if all its tags are enabled.
            //
            ISet <Tag> settings = new SetHashLinked <Tag>()
            {
                // Major Tags
                Tag.Algorithms,
                Tag.DataStructures,
                Tag.Diagnostics,
                Tag.Mathematics,
                Tag.Measurements,
                Tag.Parallels,

                // Data Structure Tags
                Tag.Link,            // aka Tuple
                Tag.Indexed,         // aka Array
                Tag.Addable,         // aka List
                Tag.FirstInLastout,  // aka Stack
                Tag.FirstInFirstOut, // aka Queue
                Tag.Heap,
                Tag.AvlTree,
                Tag.RedBlackTree,
                Tag.BTree,
                Tag.SkipList,
                Tag.Set,
                Tag.Map, // aka Dictionary
                Tag.KdTree,
                Tag.Omnitree,
            };

            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
            {
                BenchmarksAttribute attribute = type.GetCustomAttribute <BenchmarksAttribute>();
                if (!(attribute is null))
                {
                    var summary = BenchmarkRunner.Run <Program>();
                }
            }
        }
예제 #15
0
        public void Add_Testing()
        {
            {             // int
                const int  count = 100000;
                ISet <int> set   = SetHashLinked.New <int>();
                Iterate(count, i => set.Add(i));
                set.Add(int.MinValue);
                set.Add(int.MaxValue);

                Iterate(count, i => Assert.IsTrue(set.Contains(i)));
                Assert.IsTrue(set.Contains(int.MinValue));
                Assert.IsTrue(set.Contains(int.MaxValue));
                Assert.IsFalse(set.Contains(-1));
                Assert.IsFalse(set.Contains(count));

                Assert.ThrowsException <ArgumentException>(() => set.Add(0));
                Assert.ThrowsException <ArgumentException>(() => set.Add(int.MinValue));
                Assert.ThrowsException <ArgumentException>(() => set.Add(int.MaxValue));
            }

            {             // string
                const int     count = 100000;
                ISet <string> set   = SetHashLinked.New <string>();
                Iterate(count, i => set.Add(i.ToString()));
                set.Add(int.MinValue.ToString());
                set.Add(int.MaxValue.ToString());

                Iterate(count, i => Assert.IsTrue(set.Contains(i.ToString())));
                Assert.IsTrue(set.Contains(int.MinValue.ToString()));
                Assert.IsTrue(set.Contains(int.MaxValue.ToString()));
                Assert.IsFalse(set.Contains((-1).ToString()));
                Assert.IsFalse(set.Contains(count.ToString()));

                Assert.ThrowsException <ArgumentException>(() => set.Add(0.ToString()));
                Assert.ThrowsException <ArgumentException>(() => set.Add(int.MinValue.ToString()));
                Assert.ThrowsException <ArgumentException>(() => set.Add(int.MaxValue.ToString()));
            }
        }
예제 #16
0
        static void Main(string[] args)
        {
            Random random = new Random();
            int    test   = 10;

            Console.WriteLine("You are runnning the Data Structures example.");
            Console.WriteLine("======================================================");
            Console.WriteLine();

            #region Link (aka Tuple)

            Console.WriteLine("  Link------------------------------------");
            Console.WriteLine();
            Console.WriteLine("    A \"Link\" is like a System.Tuple that implements");
            Console.WriteLine("    Towel.DataStructures.DataStructure. A Link/Tuple is");
            Console.WriteLine("    used when you have a small, known-sized set of objects");
            Console.WriteLine("    that you want to bundle together without making a custom");
            Console.WriteLine("    custom class.");
            Console.WriteLine();

            Link link = new Link <int, int, int, int, int, int>(0, 1, 2, 3, 4, 5);
            Console.Write("    Traversal: ");
            link.Stepper(i => Console.Write(i));
            Console.WriteLine();

            Console.WriteLine("    Size: " + link.Size);
            Console.WriteLine();

            #endregion

            #region Indexed (aka Array)

            Console.WriteLine("  Indexed---------------------------------");
            Console.WriteLine();
            Console.WriteLine("    An \"Indexed\" is just a wrapper for arrays that implements");
            Console.WriteLine("    Towel.DataStructures.DataStructure. An array is used when");
            Console.WriteLine("    dealing with static-sized, known-sized sets of data. Arrays");
            Console.WriteLine("    can be sorted along 1 dimensions for binary searching algorithms.");
            Console.WriteLine();

            IIndexed <int> indexed = new IndexedArray <int>(test);

            Console.Write("    Filling in (0-" + (test - 1) + ")...");
            for (int i = 0; i < test; i++)
            {
                indexed[i] = i;
            }
            Console.WriteLine();

            Console.Write("    Traversal: ");
            indexed.Stepper(i => Console.Write(i));
            Console.WriteLine();

            Console.WriteLine("    Length: " + indexed.Length);

            Console.WriteLine();

            #endregion

            #region Addable (aka List)

            Console.WriteLine("  Addable---------------------------------");
            Console.WriteLine();
            Console.WriteLine("    An \"Addable\" is like an IList that implements");
            Console.WriteLine("    Towel.DataStructures.DataStructure. \"AddableArray\" is");
            Console.WriteLine("    the array implementation while \"AddableLinked\" is the");
            Console.WriteLine("    the linked-list implementation. An Addable/List is used");
            Console.WriteLine("    when dealing with an unknown quantity of data that you");
            Console.WriteLine("    will likely have to enumerate/step through everything. The");
            Console.WriteLine("    AddableArray shares the properties of an Indexed/Array in");
            Console.WriteLine("    that it can be relateively quickly sorted along 1 dimensions");
            Console.WriteLine("    for binary search algorithms.");
            Console.WriteLine();

            // AddableArray ---------------------------------------
            IAddable <int> addableArray = new AddableArray <int>(test);

            Console.Write("    [AddableArray] Adding (0-" + (test - 1) + ")...");
            for (int i = 0; i < test; i++)
            {
                addableArray.Add(i);
            }
            Console.WriteLine();

            Console.Write("    [AddableArray] Traversal: ");
            addableArray.Stepper(i => Console.Write(i));
            Console.WriteLine();

            Console.WriteLine("    [AddableArray] Count: " + addableArray.Count);

            addableArray.Clear(); // Clears the addable

            Console.WriteLine();

            // AddableLinked ---------------------------------------
            IAddable <int> addableLinked = new AddableLinked <int>();

            Console.Write("    [AddableLinked] Adding (0-" + (test - 1) + ")...");
            for (int i = 0; i < test; i++)
            {
                addableLinked.Add(i);
            }
            Console.WriteLine();

            Console.Write("    [AddableLinked] Traversal: ");
            addableLinked.Stepper(i => Console.Write(i));
            Console.WriteLine();

            Console.WriteLine("    [AddableLinked] Count: " + addableLinked.Count);

            addableLinked.Clear(); // Clears the addable

            Console.WriteLine();

            #endregion

            #region FirstInLastOut (aka stack)
            {
                Console.WriteLine("  FirstInLastOut---------------------------------");
                Console.WriteLine();
                Console.WriteLine("    An \"FirstInLastOut\" is a Stack that implements");
                Console.WriteLine("    Towel.DataStructures.DataStructure. \"FirstInLastOutArray\" is");
                Console.WriteLine("    the array implementation while \"FirstInLastOutLinked\" is the");
                Console.WriteLine("    the linked-list implementation. A FirstInLastOut/Stack is used");
                Console.WriteLine("    specifically when you need the algorithm provided by the Push");
                Console.WriteLine("    and Pop functions.");
                Console.WriteLine();

                IFirstInLastOut <int> firstInLastOutArray = new FirstInLastOutArray <int>();

                Console.Write("    [FirstInLastOutArray] Pushing (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    firstInLastOutArray.Push(i);
                }
                Console.WriteLine();

                Console.Write("    [FirstInLastOutArray] Traversal: ");
                firstInLastOutArray.Stepper(i => Console.Write(i));
                Console.WriteLine();

                Console.WriteLine("    [FirstInLastOutArray] Pop: " + firstInLastOutArray.Pop());
                Console.WriteLine("    [FirstInLastOutArray] Pop: " + firstInLastOutArray.Pop());
                Console.WriteLine("    [FirstInLastOutArray] Peek: " + firstInLastOutArray.Peek());
                Console.WriteLine("    [FirstInLastOutArray] Pop: " + firstInLastOutArray.Pop());
                Console.WriteLine("    [FirstInLastOutArray] Count: " + firstInLastOutArray.Count);

                firstInLastOutArray.Clear(); // Clears the firstInLastOut

                Console.WriteLine();

                IFirstInLastOut <int> firstInLastOutLinked = new FirstInLastOutLinked <int>();

                Console.Write("    [FirstInLastOutLinked] Pushing (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    firstInLastOutLinked.Push(i);
                }
                Console.WriteLine();

                Console.Write("    [FirstInLastOutLinked] Traversal: ");
                firstInLastOutLinked.Stepper(i => Console.Write(i));
                Console.WriteLine();

                Console.WriteLine("    [FirstInLastOutLinked] Pop: " + firstInLastOutLinked.Pop());
                Console.WriteLine("    [FirstInLastOutLinked] Pop: " + firstInLastOutLinked.Pop());
                Console.WriteLine("    [FirstInLastOutLinked] Peek: " + firstInLastOutLinked.Peek());
                Console.WriteLine("    [FirstInLastOutLinked] Pop: " + firstInLastOutLinked.Pop());
                Console.WriteLine("    [FirstInLastOutLinked] Count: " + firstInLastOutLinked.Count);

                firstInLastOutLinked.Clear(); // Clears the firstInLastOut

                Console.WriteLine();
            }
            #endregion

            #region FirstInFirstOut (aka Queue)
            {
                Console.WriteLine("  FirstInFirstOut---------------------------------");
                Console.WriteLine();
                Console.WriteLine("    An \"FirstInFirstOut\" is a Queue that implements");
                Console.WriteLine("    Towel.DataStructures.DataStructure. \"FirstInFirstOutArray\" is");
                Console.WriteLine("    the array implementation while \"FirstInFirstOutLinked\" is the");
                Console.WriteLine("    the linked-list implementation. A FirstInFirstOut/Stack is used");
                Console.WriteLine("    specifically when you need the algorithm provided by the Queue");
                Console.WriteLine("    and Dequeue functions.");
                Console.WriteLine();

                IFirstInFirstOut <int> firstInFirstOutArray = new FirstInFirstOutArray <int>();

                Console.Write("    [FirstInFirstOutArray] Enqueuing (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    firstInFirstOutArray.Enqueue(i);
                }
                Console.WriteLine();

                Console.Write("    [FirstInFirstOutArray] Traversal: ");
                firstInFirstOutArray.Stepper(i => Console.Write(i));
                Console.WriteLine();

                Console.WriteLine("    [FirstInFirstOutArray] Dequeue: " + firstInFirstOutArray.Dequeue());
                Console.WriteLine("    [FirstInFirstOutArray] Dequeue: " + firstInFirstOutArray.Dequeue());
                Console.WriteLine("    [FirstInFirstOutArray] Peek: " + firstInFirstOutArray.Peek());
                Console.WriteLine("    [FirstInFirstOutArray] Dequeue: " + firstInFirstOutArray.Dequeue());
                Console.WriteLine("    [FirstInFirstOutArray] Count: " + firstInFirstOutArray.Count);

                firstInFirstOutArray.Clear(); // Clears the firstInLastOut

                Console.WriteLine();

                IFirstInFirstOut <int> firstInFirstOutLinked = new FirstInFirstOutLinked <int>();

                Console.Write("    [FirstInFirstOutLinked] Enqueuing (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    firstInFirstOutLinked.Enqueue(i);
                }
                Console.WriteLine();

                Console.Write("    [FirstInFirstOutLinked] Traversal: ");
                firstInFirstOutLinked.Stepper(i => Console.Write(i));
                Console.WriteLine();

                Console.WriteLine("    [FirstInFirstOutLinked] Pop: " + firstInFirstOutLinked.Dequeue());
                Console.WriteLine("    [FirstInFirstOutLinked] Pop: " + firstInFirstOutLinked.Dequeue());
                Console.WriteLine("    [FirstInFirstOutLinked] Peek: " + firstInFirstOutLinked.Peek());
                Console.WriteLine("    [FirstInFirstOutLinked] Pop: " + firstInFirstOutLinked.Dequeue());
                Console.WriteLine("    [FirstInFirstOutLinked] Count: " + firstInFirstOutLinked.Count);

                firstInFirstOutLinked.Clear(); // Clears the firstInLastOut

                Console.WriteLine();
            }
            #endregion

            #region Heap
            {
                Console.WriteLine("  Heap---------------------------------");
                Console.WriteLine();
                Console.WriteLine("    An \"Heap\" is a binary tree that stores items based on priorities.");
                Console.WriteLine("    It implements Towel.DataStructures.DataStructure like the others.");
                Console.WriteLine("    It uses sifting algorithms to move nodes vertically through itself.");
                Console.WriteLine("    It is often the best data structure for standard priority queues.");
                Console.WriteLine("    \"HeapArray\" is an implementation where the tree has been flattened");
                Console.WriteLine("    into an array.");
                Console.WriteLine();

                Console.WriteLine("    Let's say the priority is how close a number is to \"5\".");
                Console.WriteLine("    So \"Dequeue\" will give us the next closest value to \"5\".");
                Comparison Priority(int a, int b)
                {
                    int        _a         = Compute.AbsoluteValue(a - 5);
                    int        _b         = Compute.AbsoluteValue(b - 5);
                    Comparison comparison = Compare.Wrap(_b.CompareTo(_a));

                    return(comparison);
                }

                Console.WriteLine();

                IHeap <int> heapArray = new HeapArray <int>(Priority);

                Console.Write("    [HeapArray] Enqueuing (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    heapArray.Enqueue(i);
                }
                Console.WriteLine();

                Console.WriteLine("    [HeapArray] Dequeue: " + heapArray.Dequeue());
                Console.WriteLine("    [HeapArray] Dequeue: " + heapArray.Dequeue());
                Console.WriteLine("    [HeapArray] Peek: " + heapArray.Peek());
                Console.WriteLine("    [HeapArray] Dequeue: " + heapArray.Dequeue());
                Console.WriteLine("    [HeapArray] Count: " + heapArray.Count);

                heapArray.Clear(); // Clears the heapArray

                Console.WriteLine();
            }
            #endregion

            #region Tree

            //Console.WriteLine("  Tree-----------------------------");

            //Tree<int> tree_Map = new TreeMap<int>(0, Compute.Equal, Hash.Default);

            //for (int i = 1; i < test; i++)
            //{
            //    tree_Map.Add(i, i / Compute.SquareRoot(i));
            //}
            //Console.Write("    Children of 0 (root): ");
            //tree_Map.Children(0, (int i) => { Console.Write(i + " "); });
            //Console.WriteLine();
            //Console.Write("    Children of " + ((int)System.Math.Sqrt(test) - 1) + " (root): ");
            //tree_Map.Children(((int)System.Math.Sqrt(test) - 1), (int i) => { Console.Write(i + " "); });
            //Console.WriteLine();
            //Console.Write("    Traversal: ");
            //tree_Map.Stepper((int i) => { Console.Write(i + " "); });
            //Console.WriteLine();

            //Console.WriteLine();

            #endregion

            #region AVL Tree
            {
                Console.WriteLine("  AvlTree------------------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    An AVL Tree is a sorted binary tree.");
                Console.WriteLine("    It implements Towel.DataStructures.DataStructure like the others.");
                Console.WriteLine("    It allows for very fast 1D ranged queries/traversals.");
                Console.WriteLine("    It is very similar to an Red Black tree, but uses a different sorting algorithm.");
                Console.WriteLine();

                IAvlTree <int> avlTree = new AvlTreeLinked <int>();

                Console.Write("    Adding (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    avlTree.Add(i);
                }
                Console.WriteLine();

                Console.Write("    Traversal: ");
                avlTree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                //// Note: Because the nodes in AVL Tree linked do not have
                //// a parent pointer, the IEnumerable "foreach" iteration
                //// is extremely slow and should be avoided. It requires
                //// a stack for it's iteration.
                //
                //Console.Write("    Traversal Foreach: ");
                //foreach (int i in avlTree)
                //{
                //    Console.Write(i);
                //}
                //Console.WriteLine();

                int minimum = random.Next(1, test / 2);
                int maximum = random.Next(1, test / 2) + test / 2;
                Console.Write("    Ranged Traversal [" + minimum + "-" + maximum + "]: ");
                avlTree.Stepper(i => Console.Write(i), minimum, maximum);
                Console.WriteLine();

                int removal = random.Next(0, test);
                Console.Write("    Remove(" + removal + "): ");
                avlTree.Remove(removal);
                avlTree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                int contains = random.Next(0, test);
                Console.WriteLine("    Contains(" + contains + "): " + avlTree.Contains(contains));
                Console.WriteLine("    Current Least: " + avlTree.CurrentLeast);
                Console.WriteLine("    Current Greatest: " + avlTree.CurrentGreatest);
                Console.WriteLine("    Count: " + avlTree.Count);

                avlTree.Clear(); // Clears the AVL tree

                Console.WriteLine();
            }
            #endregion

            #region Red-Black Tree
            {
                Console.WriteLine("  Red-Black Tree------------------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    An Red-Black Tree is a sorted binary tree.");
                Console.WriteLine("    It implements Towel.DataStructures.DataStructure like the others.");
                Console.WriteLine("    It allows for very fast 1D ranged queries/traversals.");
                Console.WriteLine("    It is very similar to an AVL tree, but uses a different sorting algorithm.");
                Console.WriteLine();

                IRedBlackTree <int> redBlackTree = new RedBlackTreeLinked <int>();

                Console.Write("    Adding (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    redBlackTree.Add(i);
                }
                Console.WriteLine();

                Console.Write("    Traversal: ");
                redBlackTree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                int minimum = random.Next(1, test / 2);
                int maximum = random.Next(1, test / 2) + test / 2;
                Console.Write("    Ranged Traversal [" + minimum + "-" + maximum + "]: ");
                redBlackTree.Stepper(i => Console.Write(i), minimum, maximum);
                Console.WriteLine();

                int removal = random.Next(0, test);
                Console.Write("    Remove(" + removal + "): ");
                redBlackTree.Remove(removal);
                redBlackTree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                int contains = random.Next(0, test);
                Console.WriteLine("    Contains(" + contains + "): " + redBlackTree.Contains(contains));
                Console.WriteLine("    Current Least: " + redBlackTree.CurrentLeast);
                Console.WriteLine("    Current Greatest: " + redBlackTree.CurrentGreatest);
                Console.WriteLine("    Count: " + redBlackTree.Count);

                redBlackTree.Clear(); // Clears the Red Black tree

                Console.WriteLine();
            }
            #endregion

            #region BTree
            {
                Console.WriteLine("  B Tree------------------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    A B Tree is a sorted binary tree that allows multiple values to");
                Console.WriteLine("    be stored per node. This makes it sort of a hybrid between a");
                Console.WriteLine("    binary tree and an array. Because multiple values are stored ");
                Console.WriteLine("    per node, it means less nodes must be traversed to completely");
                Console.WriteLine("    traverse the values in the B tree.");
                Console.WriteLine();

                Console.WriteLine("    The generic B Tree in Towel is still in development.");

                Console.WriteLine();
            }
            #endregion

            #region Set
            {
                Console.WriteLine("  Set------------------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    A Set is like an Addable/List, but it does not allow duplicates. Sets are");
                Console.WriteLine("    usually implemented using hash codes. Implementations with hash codes");
                Console.WriteLine("    usually have very fast \"Contains\" checks to see if a value has already");
                Console.WriteLine("    been added to the set.");
                Console.WriteLine();

                ISet <int> setHashLinked = new SetHashLinked <int>();

                Console.Write("    Adding (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    setHashLinked.Add(i);
                }
                Console.WriteLine();

                Console.Write("    Traversal: ");
                setHashLinked.Stepper(i => Console.Write(i));
                Console.WriteLine();

                int a = random.Next(0, test);
                setHashLinked.Remove(a);
                Console.Write("    Remove(" + a + "): ");
                setHashLinked.Stepper(i => Console.Write(i));
                Console.WriteLine();

                int b = random.Next(0, test);
                Console.WriteLine("    Contains(" + b + "): " + setHashLinked.Contains(b));
                Console.WriteLine("    Count: " + setHashLinked.Count);

                Console.WriteLine();
            }
            #endregion

            #region Map (aka Dictionary)
            {
                Console.WriteLine("  Map------------------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    A Map (aka Dictionary) is similar to a Set, but it stores two values (a ");
                Console.WriteLine("    key and a value). Maps do not allow duplicate keys much like Sets don't");
                Console.WriteLine("    allow duplicate values. When provided with the key, the Map uses that key");
                Console.WriteLine("    to look up the value that it is associated with. Thus, it allows you to ");
                Console.WriteLine("    \"map\" one object to another. As with Sets, Maps are usually implemented");
                Console.WriteLine("    using hash codes.");
                Console.WriteLine();

                // Note: the first generic is the value, the second is the key
                IMap <string, int> mapHashLinked = new MapHashLinked <string, int>();

                Console.WriteLine("    Let's map each int to its word representation (ex 1 -> One).");

                Console.Write("    Adding (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    mapHashLinked.Add(i, ((decimal)i).ToEnglishWords());
                }
                Console.WriteLine();

                Console.WriteLine("    Traversal: ");
                mapHashLinked.Keys(i => Console.WriteLine("      " + i + "->" + mapHashLinked[i]));
                Console.WriteLine();

                int a = random.Next(0, test);
                mapHashLinked.Remove(a);
                Console.Write("    Remove(" + a + "): ");
                mapHashLinked.Keys(i => Console.Write(i));
                Console.WriteLine();

                int b = random.Next(0, test);
                Console.WriteLine("    Contains(" + b + "): " + mapHashLinked.Contains(b));
                Console.WriteLine("    Count: " + mapHashLinked.Count);

                Console.WriteLine();
            }
            #endregion

            #region OmnitreePoints
            {
                Console.WriteLine("  OmnitreePoints--------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    An Omnitree is an ND SPT that allows for");
                Console.WriteLine("    multidimensional sorting. Any time you need to look");
                Console.WriteLine("    items up based on multiple fields/properties, then");
                Console.WriteLine("    you might want to use an Omnitree. If you need to");
                Console.WriteLine("    perform ranged queries on multiple dimensions, then");
                Console.WriteLine("    the Omnitree is the data structure for you.");
                Console.WriteLine();
                Console.WriteLine("    The \"OmnitreePoints\" stores individual points (vectors),");
                Console.WriteLine("    and the \"OmnitreeBounds\" stores bounded objects (spaces).");
                Console.WriteLine();

                IOmnitreePoints <int, double, string, decimal> omnitree =
                    new OmnitreePointsLinked <int, double, string, decimal>(
                        // This is a location delegate. (how to locate the item along each dimension)
                        (int index, out double a, out string b, out decimal c) =>
                {
                    a = index;
                    b = index.ToString();
                    c = index;
                });

                Console.Write("    Adding (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    omnitree.Add(i);
                }
                Console.WriteLine();

                Console.Write("    Traversal: ");
                omnitree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                int    minimumXZ = random.Next(1, test / 2);
                int    maximumXZ = random.Next(1, test / 2) + test / 2;
                string minimumY  = minimumXZ.ToString();
                string maximumY  = maximumXZ.ToString();
                Console.Write("    Spacial Traversal [" +
                              "(" + minimumXZ + ", \"" + minimumY + "\", " + minimumXZ + ")->" +
                              "(" + maximumXZ + ", \"" + maximumY + "\", " + maximumXZ + ")]: ");
                omnitree.Stepper(i => Console.Write(i),
                                 minimumXZ, maximumXZ,
                                 minimumY, maximumY,
                                 minimumXZ, maximumXZ);
                Console.WriteLine();

                // Note: this "look up" is just a very narrow spacial query that (since we know the data)
                // wil only give us one result.
                int    lookUp         = random.Next(0, test);
                string lookUpToString = lookUp.ToString();
                Console.Write("    Look Up (" + lookUp + ", \"" + lookUpToString + "\", " + lookUp + "): ");
                omnitree.Stepper(i => Console.Write(i),
                                 lookUp, lookUp,
                                 lookUp.ToString(), lookUp.ToString(),
                                 lookUp, lookUp);
                Console.WriteLine();

                // Ignoring dimensions on traversals example.
                // If you want to ignore a column on a traversal, you can do so like this:
                omnitree.Stepper(i => { /*Do Nothing*/ },
                                 lookUp, lookUp,
                                 Omnitree.Bound <string> .None, Omnitree.Bound <string> .None,
                                 Omnitree.Bound <decimal> .None, Omnitree.Bound <decimal> .None);

                Console.Write("    Counting Items In a Space [" +
                              "(" + minimumXZ + ", \"" + minimumY + "\", " + minimumXZ + ")->" +
                              "(" + maximumXZ + ", \"" + maximumY + "\", " + maximumXZ + ")]: ");
                omnitree.CountSubSpace(
                    minimumXZ, maximumXZ,
                    minimumY, maximumY,
                    minimumXZ, maximumXZ);
                Console.WriteLine();

                int    removalMinimum  = random.Next(1, test / 2);
                int    removalMaximum  = random.Next(1, test / 2) + test / 2;
                string removalMinimumY = removalMinimum.ToString();
                string removalMaximumY = removalMaximum.ToString();
                Console.Write("    Remove (" + removalMinimum + "-" + removalMaximum + "): ");
                omnitree.Remove(
                    removalMinimum, removalMaximum,
                    removalMinimumY, removalMaximumY,
                    removalMinimum, removalMaximum);
                omnitree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                Console.WriteLine("    Dimensions: " + omnitree.Dimensions);
                Console.WriteLine("    Count: " + omnitree.Count);

                omnitree.Clear(); // Clears the Omnitree

                Console.WriteLine();
            }
            #endregion

            #region OmnitreeBounds
            {
                Console.WriteLine("  OmnitreeBounds--------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    An Omnitree is an ND SPT that allows for");
                Console.WriteLine("    multidimensional sorting. Any time you need to look");
                Console.WriteLine("    items up based on multiple fields/properties, then");
                Console.WriteLine("    you might want to use an Omnitree. If you need to");
                Console.WriteLine("    perform ranged queries on multiple dimensions, then");
                Console.WriteLine("    the Omnitree is the data structure for you.");
                Console.WriteLine();
                Console.WriteLine("    The \"OmnitreePoints\" stores individual points (vectors),");
                Console.WriteLine("    and the \"OmnitreeBounds\" stores bounded objects (spaces).");
                Console.WriteLine();

                IOmnitreeBounds <int, double, string, decimal> omnitree =
                    new OmnitreeBoundsLinked <int, double, string, decimal>(
                        // This is a location delegate. (how to locate the item along each dimension)
                        (int index,
                         out double min1, out double max1,
                         out string min2, out string max2,
                         out decimal min3, out decimal max3) =>
                {
                    string indexToString = index.ToString();

                    min1 = index; max1 = index;
                    min2 = indexToString; max2 = indexToString;
                    min3 = index; max3 = index;
                });

                Console.Write("    Adding (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    omnitree.Add(i);
                }
                Console.WriteLine();

                Console.Write("    Traversal: ");
                omnitree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                int    minimumXZ = random.Next(1, test / 2);
                int    maximumXZ = random.Next(1, test / 2) + test / 2;
                string minimumY  = minimumXZ.ToString();
                string maximumY  = maximumXZ.ToString();
                Console.Write("    Spacial Traversal [" +
                              "(" + minimumXZ + ", \"" + minimumY + "\", " + minimumXZ + ")->" +
                              "(" + maximumXZ + ", \"" + maximumY + "\", " + maximumXZ + ")]: ");
                omnitree.StepperOverlapped(i => Console.Write(i),
                                           minimumXZ, maximumXZ,
                                           minimumY, maximumY,
                                           minimumXZ, maximumXZ);
                Console.WriteLine();

                // Note: this "look up" is just a very narrow spacial query that (since we know the data)
                // wil only give us one result.
                int    lookUpXZ = random.Next(0, test);
                string lookUpY  = lookUpXZ.ToString();
                Console.Write("    Look Up (" + lookUpXZ + ", \"" + lookUpY + "\", " + lookUpXZ + "): ");
                omnitree.StepperOverlapped(i => Console.Write(i),
                                           lookUpXZ, lookUpXZ,
                                           lookUpY, lookUpY,
                                           lookUpXZ, lookUpXZ);
                Console.WriteLine();

                // Ignoring dimensions on traversals example.
                // If you want to ignore a dimension on a traversal, you can do so like this:
                omnitree.StepperOverlapped(i => { /*Do Nothing*/ },
                                           lookUpXZ, lookUpXZ,
                                           // The "None" means there is no bound, so all values are valid
                                           Omnitree.Bound <string> .None, Omnitree.Bound <string> .None,
                                           Omnitree.Bound <decimal> .None, Omnitree.Bound <decimal> .None);

                Console.Write("    Counting Items In a Space [" +
                              "(" + minimumXZ + ", \"" + minimumY + "\", " + minimumXZ + ")->" +
                              "(" + maximumXZ + ", \"" + maximumY + "\", " + maximumXZ + ")]: " +
                              omnitree.CountSubSpaceOverlapped(
                                  minimumXZ, maximumXZ,
                                  minimumY, maximumY,
                                  minimumXZ, maximumXZ));
                Console.WriteLine();

                int    removalMinimumXZ = random.Next(1, test / 2);
                int    removalMaximumXZ = random.Next(1, test / 2) + test / 2;
                string removalMinimumY  = removalMinimumXZ.ToString();
                string removalMaximumY  = removalMaximumXZ.ToString();
                Console.Write("    Remove (" + removalMinimumXZ + "-" + removalMaximumXZ + "): ");
                omnitree.RemoveOverlapped(
                    removalMinimumXZ, removalMaximumXZ,
                    removalMinimumY, removalMaximumY,
                    removalMinimumXZ, removalMaximumXZ);
                omnitree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                Console.WriteLine("    Dimensions: " + omnitree.Dimensions);
                Console.WriteLine("    Count: " + omnitree.Count);

                omnitree.Clear(); // Clears the Omnitree

                Console.WriteLine();
            }
            #endregion

            #region KD Tree
            {
                Console.WriteLine("  KD Tree------------------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    A KD Tree binary tree that stores points sorted along along an");
                Console.WriteLine("    arbitrary number of dimensions. So it performs multidimensional");
                Console.WriteLine("    sorting similar to the Omnitree (Quadtree/Octree) in Towel, but");
                Console.WriteLine("    it uses a completely different algorithm and format.");
                Console.WriteLine();

                Console.WriteLine("    The generic KD Tree in Towel is still in development.");

                Console.WriteLine();
            }
            #endregion

            #region Graph
            {
                Console.WriteLine("  Graph------------------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    A Graph is a data structure of nodes and edges. Nodes are values");
                Console.WriteLine("    and edges are connections between those values. Graphs are often");
                Console.WriteLine("    used to model real world data such as maps, and are often used in");
                Console.WriteLine("    path finding algoritms. See the \"Algorithms\" example for path");
                Console.WriteLine("    finding examples. This is just an example of how to make a graph.");
                Console.WriteLine("    A \"GraphSetOmnitree\" is an implementation where nodes are stored.");
                Console.WriteLine("    in a Set and edges are stored in an Omnitree (aka Quadtree).");
                Console.WriteLine();

                IGraph <int> graphSetOmnitree = new GraphSetOmnitree <int>();

                Console.WriteLine("    Adding Nodes (0-" + (test - 1) + ")...");
                for (int i = 0; i < test; i++)
                {
                    graphSetOmnitree.Add(i);
                }

                int edgesPerNode = 3;
                Console.WriteLine("    Adding Random Edges (0-3 per node)...");
                for (int i = 0; i < test; i++)
                {
                    // lets use a heap to randomize the edges using random priorities
                    IHeap <(int, int)> heap = new HeapArray <(int, int)>((x, y) => Compare.Wrap(x.Item2.CompareTo(y.Item2)));
                    for (int j = 0; j < test; j++)
                    {
                        if (j != i)
                        {
                            heap.Enqueue((j, random.Next()));
                        }
                    }

                    // dequeue some random edges from the heap and add them to the graph
                    int randomEdgeCount = random.Next(edgesPerNode + 1);
                    for (int j = 0; j < randomEdgeCount; j++)
                    {
                        graphSetOmnitree.Add(i, heap.Dequeue().Item1);
                    }
                }

                Console.Write("    Nodes (Traversal): ");
                graphSetOmnitree.Stepper(i => Console.Write(i));
                Console.WriteLine();

                Console.WriteLine("    Edges (Traversal): ");
                graphSetOmnitree.Stepper((from, to) => Console.WriteLine("      " + from + "->" + to));
                Console.WriteLine();

                int a = random.Next(0, test);
                Console.Write("    Neighbors (" + a + "):");
                graphSetOmnitree.Neighbors(a, i => Console.Write(" " + i));
                Console.WriteLine();

                int b = random.Next(0, test / 2);
                int c = random.Next(test / 2, test);
                Console.WriteLine("    Are Adjacent (" + b + ", " + c + "): " + graphSetOmnitree.Adjacent(b, c));
                Console.WriteLine("    Node Count: " + graphSetOmnitree.NodeCount);
                Console.WriteLine("    Edge Count: " + graphSetOmnitree.EdgeCount);

                graphSetOmnitree.Clear(); // Clears the graph

                Console.WriteLine();
            }
            #endregion

            #region Trie
            {
                Console.WriteLine("  Trie------------------------------------------------");
                Console.WriteLine();
                Console.WriteLine("    A Trie is a tree where portions of the data are stored in each node");
                Console.WriteLine("    such that when you traverse the tree to a leaf, you have read the contents");
                Console.WriteLine("    of that leaf along the way. Because of this, a Trie allows for its values");
                Console.WriteLine("    to share data, which is a form of compression. So a Trie may be used to save");
                Console.WriteLine("    memory. A trie may also be a very useful tool in pattern matching, because it");
                Console.WriteLine("    it allows for culling based are portions of the data.");
                Console.WriteLine();

                Console.WriteLine("    The generic Trie in Towel is still in development.");

                Console.WriteLine();
            }
            #endregion

            Console.WriteLine("============================================");
            Console.WriteLine("Examples Complete...");
            Console.ReadLine();
        }
예제 #17
0
        [TestMethod] public void Random_UniqueNext()
        {
            #region count < Math.Sqrt(maxValue - minValue)

            {             // test shifting from maxValue
                int           i      = 999;
                TestingRandom random = new TestingRandom(() => i--);
                ISet <int>    set    = new SetHashLinked <int>();
                random.NextUnique(5, 0, 1000, j => { Assert.IsFalse(set.Contains(j)); set.Add(j); });
                Assert.IsTrue(set.Count == 5);
            }
            {             // test shifting from 0
                TestingRandom random = new TestingRandom(() => 0);
                ISet <int>    set    = new SetHashLinked <int>();
                random.NextUnique(5, 0, 1000, i => { Assert.IsFalse(set.Contains(i)); set.Add(i); });
                Assert.IsTrue(set.Count == 5);
            }
            {             // test shifting from inner value
                TestingRandom random = new TestingRandom(() => 7);
                ISet <int>    set    = new SetHashLinked <int>();
                random.NextUnique(5, 0, 1000, i => { Assert.IsFalse(set.Contains(i)); set.Add(i); });
                Assert.IsTrue(set.Count == 5);
            }
            {             // test
                Random random = new Random();
                for (int i = 0; i < 10000; i++)
                {
                    ISet <int> set = new SetHashLinked <int>();
                    random.NextUnique(5, 0, 1000, j => { Assert.IsFalse(set.Contains(j)); set.Add(j); });
                    Assert.IsTrue(set.Count == 5);
                }
            }
            {             // test invalid random argument exception
                TestingRandom random = new TestingRandom(() => 1000);
                Assert.ThrowsException <ArgumentException>(() => random.NextUnique(5, 0, 1000, i => { }));
            }
            {             // test invalid random argument exception
                TestingRandom random = new TestingRandom(() => - 1);
                Assert.ThrowsException <ArgumentException>(() => random.NextUnique(5, 0, 1000, i => { }));
            }

            #endregion

            #region count >= Math.Sqrt(maxValue - minValue)

            {             // test shifting from maxValue
                int           i      = 999;
                TestingRandom random = new TestingRandom(() => i--);
                ISet <int>    set    = new SetHashLinked <int>();
                random.NextUnique(100, 0, 1000, j => { Assert.IsFalse(set.Contains(j)); set.Add(j); });
                Assert.IsTrue(set.Count == 100);
            }
            {             // test shifting from 0
                TestingRandom random = new TestingRandom(() => 0);
                ISet <int>    set    = new SetHashLinked <int>();
                random.NextUnique(100, 0, 1000, i => { Assert.IsFalse(set.Contains(i)); set.Add(i); });
                Assert.IsTrue(set.Count == 100);
            }
            {             // test shifting from inner value
                TestingRandom random = new TestingRandom(() => 7);
                ISet <int>    set    = new SetHashLinked <int>();
                random.NextUnique(100, 0, 1000, i => { Assert.IsFalse(set.Contains(i)); set.Add(i); });
                Assert.IsTrue(set.Count == 100);
            }
            {             // test
                Random random = new Random();
                for (int i = 0; i < 10000; i++)
                {
                    ISet <int> set = new SetHashLinked <int>();
                    random.NextUnique(100, 0, 1000, j => { Assert.IsFalse(set.Contains(j)); set.Add(j); });
                    Assert.IsTrue(set.Count == 100);
                }
            }
            {             // test invalid random argument exception
                TestingRandom random = new TestingRandom(() => 1000);
                Assert.ThrowsException <ArgumentException>(() => random.NextUnique(100, 0, 1000, i => { }));
            }
            {             // test invalid random argument exception
                TestingRandom random = new TestingRandom(() => - 1);
                Assert.ThrowsException <ArgumentException>(() => random.NextUnique(100, 0, 1000, i => { }));
            }

            #endregion
        }
예제 #18
0
        static void Main(string[] args)
        {
            Console.WriteLine("You are runnning the Algorithms example.");
            Console.WriteLine("======================================================");
            Console.WriteLine();

            #region Sorting
            {
                // Note: these functions are not restricted to array types. You can use the
                // overloads with "Get" and "Assign" delegates to use them on any int-indexed
                // data structure.

                Console.WriteLine("  Sorting Algorithms----------------------");
                Console.WriteLine();
                int[] dataSet = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
                Console.Write("    Data Set:" + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                // Shuffling (Randomizing)
                Sort.Shuffle(dataSet);
                Console.Write("    Shuffle (Randomizing): " + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                // Bubble
                Sort.Bubble(dataSet);
                Console.Write("    Bubble: " + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                Console.WriteLine("    shuffling dataSet...");
                Sort.Shuffle(dataSet);

                // Selection
                Sort.Selection(dataSet);
                Console.Write("    Selection: " + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                Console.WriteLine("    shuffling dataSet...");
                Sort.Shuffle(dataSet);

                // Insertion
                Sort.Insertion(dataSet);
                Console.Write("    Insertion: " + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                Console.WriteLine("    shuffling dataSet...");
                Sort.Shuffle(dataSet);

                // Quick
                Sort.Quick(dataSet);
                Console.Write("    Quick: " + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                Console.WriteLine("    shuffling dataSet...");
                Sort.Shuffle(dataSet);

                // Merge
                Sort.Merge(Compute.Compare, dataSet);
                Console.Write("    Merge: " + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                Console.WriteLine("    shuffling dataSet...");
                Sort.Shuffle(dataSet);

                // Heap
                Sort.Heap(Compute.Compare, dataSet);
                Console.Write("    Heap: " + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                Console.WriteLine("    shuffling dataSet...");
                Sort.Shuffle(dataSet);

                // OddEven
                Sort.OddEven(Compute.Compare, dataSet);
                Console.Write("    OddEven: " + string.Join(", ", dataSet.Select(x => x.ToString())));
                Console.WriteLine();

                //Console.WriteLine("  shuffling dataSet...");
                //Sort<int>.Shuffle(dataSet);

                //// Slow
                //Sort<int>.Slow(Logic.compare, get, set, 0, dataSet.Length);
                //Console.Write("Slow: " + string.Join(", ", dataSet.Select(x => x.ToString())));
                //Console.WriteLine();

                //Console.WriteLine("  shuffling dataSet...");
                //Sort<int>.Shuffle(dataSet);

                // Bogo
                //Sort<int>.Bogo(Logic.compare, get, set, 0, dataSet.Length);
                Console.Write("    Bogo: Disabled (takes forever)"); //+ string.Join(", ", dataSet.Select(x => x.ToString())));
                //Console.WriteLine();

                Console.WriteLine();
                Console.WriteLine();
            }
            #endregion

            #region Graph Search (Using Graph Data Structure)
            {
                Console.WriteLine("  Graph Searching----------------------");
                Console.WriteLine();

                // make a graph
                IGraph <int> graph = new GraphSetOmnitree <int>()
                {
                    // add nodes
                    0,
                    1,
                    2,
                    3,
                    // add edges
                    { 0, 1 },
                    { 0, 2 },
                    { 1, 3 },
                    { 2, 3 }
                };

                // make a heuristic function
                int heuristic(int node)
                {
                    switch (node)
                    {
                    case 0:
                        return(3);

                    case 1:
                        return(6);

                    case 2:
                        return(1);

                    case 3:
                        return(0);

                    default:
                        throw new NotImplementedException();
                    }
                }

                // make a cost function
                int cost(int from, int to)
                {
                    if (from == 0 && to == 1)
                    {
                        return(1);
                    }
                    if (from == 0 && to == 2)
                    {
                        return(2);
                    }
                    if (from == 1 && to == 3)
                    {
                        return(5);
                    }
                    if (from == 2 && to == 3)
                    {
                        return(1);
                    }
                    if (from == 0 && to == 3)
                    {
                        return(99);
                    }
                    throw new Exception("invalid path cost computation");
                }

                // make a goal function
                bool goal(int node)
                {
                    if (node == 3)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }

                // run A* the algorithm
                Stepper <int> aStar_path = Search.Graph <int, int>(0, graph, heuristic, cost, goal);
                Console.Write("    A* Path: ");
                if (aStar_path != null)
                {
                    aStar_path(i => Console.Write(i + " "));
                }
                else
                {
                    Console.Write("none");
                }

                Console.WriteLine();

                // run the Greedy algorithm
                Stepper <int> greedy_path = Search.Graph <int, int>(0, graph, heuristic, goal);
                Console.Write("    Greedy Path: ");
                if (greedy_path != null)
                {
                    greedy_path(i => Console.Write(i + " "));
                }
                else
                {
                    Console.Write("none");
                }

                Console.WriteLine();
                Console.WriteLine();
            }
            #endregion

            #region Graph Search (Vector Game-Style Example)
            {
                Console.WriteLine("  Graph Searching (Vector Game-Style Example)-------------------");
                Console.WriteLine();
                Console.WriteLine("    Debug the code. The path is to large to write to the console.");
                Console.WriteLine();

                // Lets say you are coding enemy AI and you want the AI to find a path towards the player
                // in order to attack them. Here are their starting positions:
                Vector <float> enemyLocation    = new Vector <float>(-100f, 0f, -50f);
                Vector <float> playerLocation   = new Vector <float>(200f, 0f, -50f);
                float          enemyAttackRange = 3f; // enemy has a melee attack with 3 range

                // Lets say most of the terrain is open, but there is a big rock in between them that they
                // must go around.
                Vector <float> rockLocation = new Vector <float>(15f, 0f, -40f);
                float          rockRadius   = 20f;

                // Make sure we don't re-use locations (must be wiped after running the algorithm)
                ISet <Vector <float> > alreadyUsed = new SetHashLinked <Vector <float> >();

                Vector <float> validationVectorStorage = null; // storage to prevent a ton of vectors from being allocated

                // So, we just need to validate movement locations (make sure the path finding algorithm
                // ignores locations inside the rock)
                bool validateMovementLocation(Vector <float> location)
                {
                    // if the location is inside the rock, it is not a valid movement
                    location.Subtract(rockLocation, ref validationVectorStorage);
                    float magnitude = validationVectorStorage.Magnitude;

                    if (magnitude <= rockRadius)
                    {
                        return(false);
                    }

                    // NOTE: If you are running a physics engine, you might be able to just call it to validate a location.

                    // if the location was already used, then let's consider it invalid, because
                    // another path (which is faster) has already reached that location
                    if (alreadyUsed.Contains(location))
                    {
                        return(false);
                    }

                    return(true);
                }

                // Now we need the neighbor function (getting the neighbors of the current location).
                void neighborFunction(Vector <float> currentLocation, Step <Vector <float> > neighbors)
                {
                    // NOTES:
                    // - This neighbor function has a 90 degree per-node resolution (360 / 4 [north/south/east/west] = 90).
                    // - This neighbor function has a 1 unit per-node distance resolution, because we went 1 unit in each direction.

                    // RECOMMENDATIONS:
                    // - If the path finding is failing, you may need to increase the resolution.
                    // - If the algorithm is running too slow, you may need to reduce the resolution.

                    float distanceResolution = 1;

                    float x = currentLocation.X;
                    float y = currentLocation.Y;
                    float z = currentLocation.Z;

                    // Note: I'm using the X-axis and Z-axis here, but which axis you need to use
                    // depends on your environment. Your "north" could be along the Y-axis for example.

                    Vector <float> north = new Vector <float>(x + distanceResolution, y, z);

                    if (validateMovementLocation(north))
                    {
                        alreadyUsed.Add(north); // mark location as used
                        neighbors(north);
                    }

                    Vector <float> east = new Vector <float>(x, y, z + distanceResolution);

                    if (validateMovementLocation(east))
                    {
                        alreadyUsed.Add(east); // mark location as used
                        neighbors(east);
                    }

                    Vector <float> south = new Vector <float>(x - distanceResolution, y, z);

                    if (validateMovementLocation(south))
                    {
                        alreadyUsed.Add(south); // mark location as used
                        neighbors(south);
                    }

                    Vector <float> west = new Vector <float>(x, y, z - distanceResolution);

                    if (validateMovementLocation(west))
                    {
                        alreadyUsed.Add(west); // mark location as used
                        neighbors(west);
                    }
                }

                Vector <float> heuristicVectorStorage = null; // storage to prevent a ton of vectors from being allocated

                // Heuristic function (how close are we to the goal)
                float heuristicFunction(Vector <float> currentLocation)
                {
                    // The goal is the player's location, so we just need our distance from the player.
                    currentLocation.Subtract(playerLocation, ref heuristicVectorStorage);
                    return(heuristicVectorStorage.Magnitude);
                }

                // Lets say there is a lot of mud around the rock, and the mud makes our player move at half their normal speed.
                // Our path finding needs to find the fastest route to the player, whether it be through the mud or not.
                Vector <float> mudLocation = new Vector <float>(15f, 0f, -70f);
                float          mudRadius   = 30f;

                Vector <float> costVectorStorage = null; // storage to prevent a ton of vectors from being allocated

                // Cost function
                float costFunction(Vector <float> from, Vector <float> to)
                {
                    // If the location we are moving to is in the mud, lets adjust the
                    // cost because mud makes us move slower.
                    to.Subtract(mudLocation, ref costVectorStorage);
                    float magnitude = costVectorStorage.Magnitude;

                    if (magnitude <= mudRadius)
                    {
                        return(2f);
                    }

                    // neither location is in the mud, it is just a standard movement at normal speed.
                    return(1f);
                }

                Vector <float> goalVectorStorage = null; // storage to prevent a ton of vectors from being allocated

                // Goal function
                bool goalFunction(Vector <float> currentLocation)
                {
                    // if the player is within the enemy's attack range WE FOUND A PATH! :)
                    currentLocation.Subtract(playerLocation, ref goalVectorStorage);
                    float magnitude = goalVectorStorage.Magnitude;

                    if (magnitude <= enemyAttackRange)
                    {
                        return(true);
                    }

                    // the enemy is not yet within attack range
                    return(false);
                }

                // We have all the necessary parameters. Run the pathfinding algorithms!
                Stepper <Vector <float> > aStarPath =
                    Search.Graph(
                        enemyLocation,
                        neighborFunction,
                        heuristicFunction,
                        costFunction,
                        goalFunction);

                // Flush the already used markers before running the Greedy algorithm.
                // Normally you won't run two algorithms for the same graph/location, but
                // we are running both algorithms in this example to demonstrate the
                // differences between them.
                alreadyUsed.Clear();

                Stepper <Vector <float> > greedyPath =
                    Search.Graph(
                        enemyLocation,
                        neighborFunction,
                        heuristicFunction,
                        goalFunction);

                // NOTE: If there is no valid path, then "Search.Graph" will return "null."
                // For this example, I know that there will be a valid path so I did not
                // include a null check.

                // Lets convert the paths into arrays so you can look at them in the debugger. :)
                Vector <float>[] aStarPathArray  = aStarPath.ToArray();
                Vector <float>[] greedyPathArray = greedyPath.ToArray();

                // lets calculate the movement cost of each path to see how they compare
                float astartTotalCost = Compute.Add <float>(step =>
                {
                    for (int i = 0; i < aStarPathArray.Length - 1; i++)
                    {
                        step(costFunction(aStarPathArray[i], aStarPathArray[i + 1]));
                    }
                });
                float greedyTotalCost = Compute.Add <float>(step =>
                {
                    for (int i = 0; i < greedyPathArray.Length - 1; i++)
                    {
                        step(costFunction(greedyPathArray[i], greedyPathArray[i + 1]));
                    }
                });

                // Notice that that the A* algorithm produces a less costly path than the Greedy,
                // meaning that it is faster. The Greedy path went through the mud, but the A* path
                // took the longer route around the other side of the rock, which ended up being faster
                // than running through the mud.
            }
            #endregion

            #region Random Generation
            {
                Console.WriteLine("  Random Generation---------------------");
                Console.WriteLine();

                int iterationsperrandom = 3;
                void testrandom(Random random)
                {
                    for (int i = 0; i < iterationsperrandom; i++)
                    {
                        Console.WriteLine("    " + i + ": " + random.Next());
                    }
                    Console.WriteLine();
                }

                Arbitrary mcg_2pow59_13pow13 = new Arbitrary.Algorithms.MultiplicativeCongruent_A();
                Console.WriteLine("    mcg_2pow59_13pow13 randoms:");
                testrandom(mcg_2pow59_13pow13);
                Arbitrary mcg_2pow31m1_1132489760 = new Arbitrary.Algorithms.MultiplicativeCongruent_B();
                Console.WriteLine("    mcg_2pow31m1_1132489760 randoms:");
                testrandom(mcg_2pow31m1_1132489760);
                Arbitrary mersenneTwister = new Arbitrary.Algorithms.MersenneTwister();
                Console.WriteLine("    mersenneTwister randoms:");
                testrandom(mersenneTwister);
                Arbitrary cmr32_c2_o3 = new Arbitrary.Algorithms.CombinedMultipleRecursive();
                Console.WriteLine("    mersenneTwister randoms:");
                testrandom(cmr32_c2_o3);
                Arbitrary wh1982cmcg = new Arbitrary.Algorithms.WichmannHills1982();
                Console.WriteLine("    mersenneTwister randoms:");
                testrandom(wh1982cmcg);
                Arbitrary wh2006cmcg = new Arbitrary.Algorithms.WichmannHills2006();
                Console.WriteLine("    mersenneTwister randoms:");
                testrandom(wh2006cmcg);
                Arbitrary mwcxorsg = new Arbitrary.Algorithms.MultiplyWithCarryXorshift();
                Console.WriteLine("    mwcxorsg randoms:");
                testrandom(mwcxorsg);
            }
            #endregion

            Console.WriteLine();
            Console.WriteLine("============================================");
            Console.WriteLine("Example Complete...");
            Console.ReadLine();
        }