|   |  | 1 |  | namespace Towel.DataStructures; | 
|   |  | 2 |  |  | 
|   |  | 3 |  | /// <summary>Implements a First-In-Last-Out stack data structure.</summary> | 
|   |  | 4 |  | /// <typeparam name="T">The generic type within the structure.</typeparam> | 
|   |  | 5 |  | public interface IStack<T> : IDataStructure<T>, | 
|   |  | 6 |  |   DataStructure.ICountable, | 
|   |  | 7 |  |   DataStructure.IClearable | 
|   |  | 8 |  | { | 
|   |  | 9 |  |   #region Methods | 
|   |  | 10 |  |  | 
|   |  | 11 |  |   /// <summary>Adds an item to the top of the stack.</summary> | 
|   |  | 12 |  |   /// <param name="push">The item to add to the stack.</param> | 
|   |  | 13 |  |   void Push(T push); | 
|   |  | 14 |  |   /// <summary>Returns the most recent addition to the stack.</summary> | 
|   |  | 15 |  |   /// <returns>The most recent addition to the stack.</returns> | 
|   |  | 16 |  |   T Peek(); | 
|   |  | 17 |  |   /// <summary>Removes and returns the most recent addition to the stack.</summary> | 
|   |  | 18 |  |   /// <returns>The most recent addition to the stack.</returns> | 
|   |  | 19 |  |   T Pop(); | 
|   |  | 20 |  |  | 
|   |  | 21 |  |   #endregion | 
|   |  | 22 |  | } | 
|   |  | 23 |  |  | 
|   |  | 24 |  | /// <summary>Implements a First-In-Last-Out stack data structure using a linked list.</summary> | 
|   |  | 25 |  | /// <typeparam name="T">The generic type within the structure.</typeparam> | 
|   |  | 26 |  | public class StackLinked<T> : IStack<T>, ICloneable<StackLinked<T>> | 
|   |  | 27 |  | { | 
|   |  | 28 |  |   internal Node? _top; | 
|   |  | 29 |  |   internal int _count; | 
|   |  | 30 |  |  | 
|   |  | 31 |  |   #region Nested Types | 
|   |  | 32 |  |  | 
|   |  | 33 |  |   internal class Node | 
|   |  | 34 |  |   { | 
|   |  | 35 |  |     internal T Value; | 
|   |  | 36 |  |     internal Node? Down; | 
|   |  | 37 |  |  | 
|   | 20129 | 38 |  |     internal Node(T value, Node? down = null) | 
|   | 20129 | 39 |  |     { | 
|   | 20129 | 40 |  |       Value = value; | 
|   | 20129 | 41 |  |       Down = down; | 
|   | 20129 | 42 |  |     } | 
|   |  | 43 |  |   } | 
|   |  | 44 |  |  | 
|   |  | 45 |  |   #endregion | 
|   |  | 46 |  |  | 
|   |  | 47 |  |   #region Constructors | 
|   |  | 48 |  |  | 
|   |  | 49 |  |   /// <summary>Constructs a new stack.</summary> | 
|   | 12 | 50 |  |   public StackLinked() | 
|   | 12 | 51 |  |   { | 
|   | 12 | 52 |  |     _top = null; | 
|   | 12 | 53 |  |     _count = 0; | 
|   | 12 | 54 |  |   } | 
|   |  | 55 |  |  | 
|   |  | 56 |  |   /// <summary>This constructor is for cloning purposes.</summary> | 
|   |  | 57 |  |   /// <param name="stack">The stack to clone.</param> | 
|   | 0 | 58 |  |   internal StackLinked(StackLinked<T> stack) | 
|   | 0 | 59 |  |   { | 
|   | 0 | 60 |  |     if (stack._top is not null) | 
|   | 0 | 61 |  |     { | 
|   | 0 | 62 |  |       _top = new Node(value: stack._top.Value); | 
|   | 0 | 63 |  |       Node? a = stack._top.Down; | 
|   | 0 | 64 |  |       Node? b = _top; | 
|   | 0 | 65 |  |       while (a is not null) | 
|   | 0 | 66 |  |       { | 
|   | 0 | 67 |  |         b.Down = new Node(value: a.Value); | 
|   | 0 | 68 |  |         b = b.Down; | 
|   | 0 | 69 |  |         a = a.Down; | 
|   | 0 | 70 |  |       } | 
|   | 0 | 71 |  |       _count = stack._count; | 
|   | 0 | 72 |  |     } | 
|   | 0 | 73 |  |   } | 
|   |  | 74 |  |  | 
|   |  | 75 |  |   #endregion | 
|   |  | 76 |  |  | 
|   |  | 77 |  |   #region Properties | 
|   |  | 78 |  |  | 
|   |  | 79 |  |   /// <inheritdoc/> | 
|   | 5 | 80 |  |   public int Count => _count; | 
|   |  | 81 |  |  | 
|   |  | 82 |  |   #endregion | 
|   |  | 83 |  |  | 
|   |  | 84 |  |   #region Methods | 
|   |  | 85 |  |  | 
|   |  | 86 |  |   /// <inheritdoc/> | 
|   | 0 | 87 |  |   public StackLinked<T> Clone() => new(this); | 
|   |  | 88 |  |  | 
|   |  | 89 |  |   /// <inheritdoc/> | 
|   |  | 90 |  |   public T[] ToArray() | 
|   | 0 | 91 |  |   { | 
|   | 0 | 92 |  |     if (_count is 0) | 
|   | 0 | 93 |  |     { | 
|   | 0 | 94 |  |       return Array.Empty<T>(); | 
|   |  | 95 |  |     } | 
|   | 0 | 96 |  |     T[] array = new T[_count]; | 
|   | 0 | 97 |  |     for (var (i, node) = (0, _top); node is not null; node = node.Down, i++) | 
|   | 0 | 98 |  |     { | 
|   | 0 | 99 |  |       array[i] = node.Value; | 
|   | 0 | 100 |  |     } | 
|   | 0 | 101 |  |     return array; | 
|   | 0 | 102 |  |   } | 
|   |  | 103 |  |  | 
|   |  | 104 |  |   /// <inheritdoc/> | 
|   |  | 105 |  |   public void Push(T addition) | 
|   | 20129 | 106 |  |   { | 
|   | 20129 | 107 |  |     _top = new Node(value: addition, down: _top); | 
|   | 20129 | 108 |  |     _count++; | 
|   | 20129 | 109 |  |   } | 
|   |  | 110 |  |  | 
|   |  | 111 |  |   /// <inheritdoc/> | 
|   |  | 112 |  |   public T Peek() | 
|   | 0 | 113 |  |   { | 
|   | 0 | 114 |  |     if (_top is null) | 
|   | 0 | 115 |  |     { | 
|   | 0 | 116 |  |       throw new InvalidOperationException("Attempting to remove from an empty queue."); | 
|   |  | 117 |  |     } | 
|   | 0 | 118 |  |     T peek = _top.Value; | 
|   | 0 | 119 |  |     return peek; | 
|   | 0 | 120 |  |   } | 
|   |  | 121 |  |  | 
|   |  | 122 |  |   /// <inheritdoc/> | 
|   |  | 123 |  |   public T Pop() | 
|   | 20099 | 124 |  |   { | 
|   | 20099 | 125 |  |     if (_count is 0) | 
|   | 2 | 126 |  |     { | 
|   | 2 | 127 |  |       throw new InvalidOperationException("attempting to pop from an empty stack."); | 
|   |  | 128 |  |     } | 
|   | 20097 | 129 |  |     if (_top is null) | 
|   | 0 | 130 |  |     { | 
|   | 0 | 131 |  |       throw new TowelBugException($"{nameof(Count)} is greater than 0 but {nameof(_top)} is null"); | 
|   |  | 132 |  |     } | 
|   | 20097 | 133 |  |     T pop = _top.Value; | 
|   | 20097 | 134 |  |     _top = _top.Down; | 
|   | 20097 | 135 |  |     _count--; | 
|   | 20097 | 136 |  |     return pop; | 
|   | 20097 | 137 |  |   } | 
|   |  | 138 |  |  | 
|   |  | 139 |  |   /// <inheritdoc/> | 
|   |  | 140 |  |   public void Clear() | 
|   | 0 | 141 |  |   { | 
|   | 0 | 142 |  |     _top = null; | 
|   | 0 | 143 |  |     _count = 0; | 
|   | 0 | 144 |  |   } | 
|   |  | 145 |  |  | 
|   |  | 146 |  |   /// <inheritdoc/> | 
|   |  | 147 |  |   public StepStatus StepperBreak<TStep>(TStep step = default) | 
|   |  | 148 |  |     where TStep : struct, IFunc<T, StepStatus> | 
|   | 3 | 149 |  |   { | 
|   | 38 | 150 |  |     for (Node? node = _top; node is not null; node = node.Down) | 
|   | 16 | 151 |  |     { | 
|   | 16 | 152 |  |       if (step.Invoke(node.Value) is Break) | 
|   | 0 | 153 |  |       { | 
|   | 0 | 154 |  |         return Break; | 
|   |  | 155 |  |       } | 
|   | 16 | 156 |  |     } | 
|   | 3 | 157 |  |     return Continue; | 
|   | 3 | 158 |  |   } | 
|   |  | 159 |  |  | 
|   | 0 | 160 |  |   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); | 
|   |  | 161 |  |  | 
|   |  | 162 |  |   /// <inheritdoc/> | 
|   |  | 163 |  |   public System.Collections.Generic.IEnumerator<T> GetEnumerator() | 
|   | 6 | 164 |  |   { | 
|   | 76 | 165 |  |     for (Node? node = _top; node is not null; node = node.Down) | 
|   | 32 | 166 |  |     { | 
|   | 32 | 167 |  |       yield return node.Value; | 
|   | 32 | 168 |  |     } | 
|   | 6 | 169 |  |   } | 
|   |  | 170 |  |  | 
|   |  | 171 |  |   #endregion | 
|   |  | 172 |  | } | 
|   |  | 173 |  |  | 
|   |  | 174 |  | /// <summary>Implements a First-In-Last-Out stack data structure using an array.</summary> | 
|   |  | 175 |  | /// <typeparam name="T">The generic type within the structure.</typeparam> | 
|   |  | 176 |  | public class StackArray<T> : IStack<T>, ICloneable<StackArray<T>> | 
|   |  | 177 |  | { | 
|   |  | 178 |  |   internal const int DefaultMinimumCapacity = 1; | 
|   |  | 179 |  |  | 
|   |  | 180 |  |   internal T[] _array; | 
|   |  | 181 |  |   internal int _count; | 
|   |  | 182 |  |   internal int? _minimumCapacity; | 
|   |  | 183 |  |  | 
|   |  | 184 |  |   #region Constructors | 
|   |  | 185 |  |  | 
|   |  | 186 |  |   /// <summary>Constructs a new stack.</summary> | 
|   |  | 187 |  |   public StackArray() | 
|   |  | 188 |  |   { | 
|   |  | 189 |  |     _array = new T[DefaultMinimumCapacity]; | 
|   |  | 190 |  |     _count = 0; | 
|   |  | 191 |  |   } | 
|   |  | 192 |  |  | 
|   |  | 193 |  |   /// <summary>Constructs a new stack.</summary> | 
|   |  | 194 |  |   /// <param name="minimumCapacity">The minimum capacity of the stack.</param> | 
|   |  | 195 |  |   public StackArray(int minimumCapacity) | 
|   |  | 196 |  |   { | 
|   |  | 197 |  |     if (minimumCapacity <= 0) | 
|   |  | 198 |  |     { | 
|   |  | 199 |  |       throw new ArgumentOutOfRangeException(nameof(minimumCapacity), minimumCapacity, $"{nameof(minimumCapacity)} <= 0") | 
|   |  | 200 |  |     } | 
|   |  | 201 |  |     _array = new T[minimumCapacity]; | 
|   |  | 202 |  |     _count = 0; | 
|   |  | 203 |  |     _minimumCapacity = minimumCapacity; | 
|   |  | 204 |  |   } | 
|   |  | 205 |  |  | 
|   |  | 206 |  |   internal StackArray(T[] array, int count, int? minimumCapacity) | 
|   |  | 207 |  |   { | 
|   |  | 208 |  |     _array = array; | 
|   |  | 209 |  |     _count = count; | 
|   |  | 210 |  |     _minimumCapacity = minimumCapacity; | 
|   |  | 211 |  |   } | 
|   |  | 212 |  |  | 
|   |  | 213 |  |   /// <summary>This constructor is for cloning purposes.</summary> | 
|   |  | 214 |  |   /// <param name="stack">The stack to clone.</param> | 
|   |  | 215 |  |   internal StackArray(StackArray<T> stack) | 
|   |  | 216 |  |   { | 
|   |  | 217 |  |     _array = (T[])stack._array.Clone(); | 
|   |  | 218 |  |     _count = stack._count; | 
|   |  | 219 |  |     _minimumCapacity = stack._minimumCapacity; | 
|   |  | 220 |  |   } | 
|   |  | 221 |  |  | 
|   |  | 222 |  |   #endregion | 
|   |  | 223 |  |  | 
|   |  | 224 |  |   #region Properties | 
|   |  | 225 |  |  | 
|   |  | 226 |  |   /// <summary>Gets the current capacity of the list.</summary> | 
|   |  | 227 |  |   public int CurrentCapacity => _array.Length; | 
|   |  | 228 |  |  | 
|   |  | 229 |  |   /// <summary>Allows you to adjust the minimum capacity of this list.</summary> | 
|   |  | 230 |  |   public int? MinimumCapacity | 
|   |  | 231 |  |   { | 
|   |  | 232 |  |     get => _minimumCapacity; | 
|   |  | 233 |  |     set | 
|   |  | 234 |  |     { | 
|   |  | 235 |  |       if (!value.HasValue) | 
|   |  | 236 |  |       { | 
|   |  | 237 |  |         _minimumCapacity = value; | 
|   |  | 238 |  |       } | 
|   |  | 239 |  |       else if (value < 1) | 
|   |  | 240 |  |       { | 
|   |  | 241 |  |         throw new InvalidOperationException("Attempting to set a minimum capacity to a negative or zero value."); | 
|   |  | 242 |  |       } | 
|   |  | 243 |  |       else if (value > _array.Length) | 
|   |  | 244 |  |       { | 
|   |  | 245 |  |         Array.Resize<T>(ref _array, value.Value); | 
|   |  | 246 |  |       } | 
|   |  | 247 |  |       _minimumCapacity = value; | 
|   |  | 248 |  |     } | 
|   |  | 249 |  |   } | 
|   |  | 250 |  |  | 
|   |  | 251 |  |   /// <inheritdoc/> | 
|   |  | 252 |  |   public int Count => _count; | 
|   |  | 253 |  |  | 
|   |  | 254 |  |   #endregion | 
|   |  | 255 |  |  | 
|   |  | 256 |  |   #region Methods | 
|   |  | 257 |  |  | 
|   |  | 258 |  |   /// <inheritdoc/> | 
|   |  | 259 |  |   public StackArray<T> Clone() => new(this); | 
|   |  | 260 |  |  | 
|   |  | 261 |  |   /// <inheritdoc/> | 
|   |  | 262 |  |   public T[] ToArray() => _count is 0 ? Array.Empty<T>() : _array[.._count]; | 
|   |  | 263 |  |  | 
|   |  | 264 |  |   /// <inheritdoc/> | 
|   |  | 265 |  |   public void Push(T addition) | 
|   |  | 266 |  |   { | 
|   |  | 267 |  |     if (_count == _array.Length) | 
|   |  | 268 |  |     { | 
|   |  | 269 |  |       if (_array.Length > int.MaxValue / 2) | 
|   |  | 270 |  |       { | 
|   |  | 271 |  |         throw new InvalidOperationException("your queue is so large that it can no longer double itself (Int32.MaxValue  | 
|   |  | 272 |  |       } | 
|   |  | 273 |  |       Array.Resize<T>(ref _array, _array.Length * 2); | 
|   |  | 274 |  |     } | 
|   |  | 275 |  |     _array[_count++] = addition; | 
|   |  | 276 |  |   } | 
|   |  | 277 |  |  | 
|   |  | 278 |  |   /// <inheritdoc/> | 
|   |  | 279 |  |   public T Pop() | 
|   |  | 280 |  |   { | 
|   |  | 281 |  |     if (_count is 0) | 
|   |  | 282 |  |     { | 
|   |  | 283 |  |       throw new InvalidOperationException("attempting to pop from an empty stack."); | 
|   |  | 284 |  |     } | 
|   |  | 285 |  |     if (_count < _array.Length / 4 && _array.Length / 2 > _minimumCapacity) | 
|   |  | 286 |  |     { | 
|   |  | 287 |  |       Array.Resize<T>(ref _array, _array.Length / 2); | 
|   |  | 288 |  |     } | 
|   |  | 289 |  |     T returnValue = _array[--_count]; | 
|   |  | 290 |  |     return returnValue; | 
|   |  | 291 |  |   } | 
|   |  | 292 |  |  | 
|   |  | 293 |  |   /// <inheritdoc/> | 
|   |  | 294 |  |   public T Peek() => _array[_count - 1]; | 
|   |  | 295 |  |  | 
|   |  | 296 |  |   /// <inheritdoc/> | 
|   |  | 297 |  |   public void Clear() | 
|   |  | 298 |  |   { | 
|   |  | 299 |  |     _array = new T[_minimumCapacity ?? DefaultMinimumCapacity]; | 
|   |  | 300 |  |     _count = 0; | 
|   |  | 301 |  |   } | 
|   |  | 302 |  |  | 
|   |  | 303 |  |   /// <inheritdoc/> | 
|   |  | 304 |  |   public StepStatus StepperBreak<TStep>(TStep step = default) | 
|   |  | 305 |  |     where TStep : struct, IFunc<T, StepStatus> => | 
|   |  | 306 |  |     _array.StepperBreak(0, _count, step); | 
|   |  | 307 |  |  | 
|   |  | 308 |  |   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); | 
|   |  | 309 |  |  | 
|   |  | 310 |  |   /// <inheritdoc/> | 
|   |  | 311 |  |   public System.Collections.Generic.IEnumerator<T> GetEnumerator() | 
|   |  | 312 |  |   { | 
|   |  | 313 |  |     for (int i = 0; i < _count; i++) | 
|   |  | 314 |  |     { | 
|   |  | 315 |  |       yield return _array[i]; | 
|   |  | 316 |  |     } | 
|   |  | 317 |  |   } | 
|   |  | 318 |  |  | 
|   |  | 319 |  |   #endregion | 
|   |  | 320 |  | } |