using System.Collections.Generic;
using System.Diagnostics;
[AttributeUsage(System.AttributeTargets.Method, AllowMultiple = false)]
class SortableAttribute : System.Attribute
static class ArrayUtility
private static Random random = new Random();
public static int[] GetNumbers(int size, int rangeStart, int rangeEnd) => [..Enumerable.Range(0, size).Select(_ => random.Next(rangeStart, rangeEnd))];
public static void PrintNumbers(int[] numbers)
for (int i = 0, iLength = numbers.Length; i < iLength; i++)
Console.Write($"{numbers[i]}".PadRight(5, ' '));
public static void BubbleSort(int[] numbers)
for (int i = 0, iLength = numbers.Length; i < iLength; i++)
for (int j = 0, jLength = numbers.Length - i - 1; j < jLength; j++)
if (numbers[j] > numbers[j + 1])
numbers[j] = numbers[j + 1];
numbers[j + 1] = temporary;
public static void SelectionSort(int[] numbers)
int minimum, minimumIndex;
for (int i = 0, iLength = numbers.Length; i < iLength; i++)
for (int j = i + 1, jLength = numbers.Length; j < jLength; j++)
if (numbers[j] < minimum)
numbers[minimumIndex] = numbers[i];
public static void InsertionSort(int[] numbers)
for (int i = 1, iLength = numbers.Length; i < iLength; i++)
for (int j = i - 1; j >= 0; j--)
if (numbers[j] < numbers[j + 1])
numbers[j] = numbers[j + 1];
public static void MergeSort(int[] numbers)
static void MergeSort(int[] numbers, int start, int end)
int pivot = start + (end - start) / 2;
MergeSort(numbers, start, pivot);
MergeSort(numbers, pivot + 1, end);
Merge(numbers, start, pivot, end);
static void Merge(int[] numbers, int start, int pivot, int end)
int iLength = pivot - start + 1;
int[] left = new int[iLength];
left[i] = numbers[start + i];
int jLength = end - pivot;
int[] right = new int[jLength];
right[j] = numbers[pivot + 1 + j];
while (i < iLength && j < jLength)
MergeSort(numbers, 0, numbers.Length - 1);
public static void QuickSort(int[] array)
int Partition(int[] array, int left, int right)
int pivot = array[right];
for (int i = left; i < right; i++)
temporary = array[store];
temporary = array[store + 1];
array[store + 1] = pivot;
array[right] = temporary;
void QuickSort(int[] array, int left, int right)
int pivot = Partition(array, left, right);
QuickSort(array, left, pivot - 1);
QuickSort(array, pivot + 1, right);
QuickSort(array, 0, array.Length - 1);
private const string ArrayFormatter = "\n\n{0}";
private const string ElapsedFormatter = "elapsed = {0}\n";
private static Stopwatch? stopwatch;
private static readonly int[] sealedNumbers = ArrayUtility.GetNumbers(20, -20, 20);
public static void RunSort(Action<int[]> sortingFunction)
Console.WriteLine(ArrayFormatter, sortingFunction.Method.Name);
int[] numbers = [..sealedNumbers];
stopwatch = Stopwatch.StartNew();
sortingFunction(numbers);
ArrayUtility.PrintNumbers(numbers);
Console.WriteLine(ElapsedFormatter, stopwatch.Elapsed);
private static readonly IEnumerator<Action<int[]>> algorithms = typeof(Sorting).GetMethods().Where(_ => _.IsDefined(typeof(SortableAttribute))).Select(method => method.CreateDelegate<Action<int[]>>()).GetEnumerator();
while (algorithms.MoveNext())
SortRunner.RunSort(algorithms.Current);