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); } }
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); } }
/// <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; }
[Benchmark] public void SetHashLinked_AddCompileTime() { ISet <Person> set = new SetHashLinked <Person, EquatePerson, HashPerson>(); foreach (Person person in RandomTestData) { set.Add(person); } }
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); } }
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); } }
public void Add() { ISet <int> addable = new SetHashLinked <int>(); int addCount = AddCount; for (int i = 0; i < addCount; i++) { addable.Add(i); } }
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); } }
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); } }
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); } }
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); } }
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())); } }
/// <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); }
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>(); } } }
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())); } }
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(); }
[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 }
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(); }