/// <summary> /// Enumerates all possible value permutations for a given array. /// </summary> /// /// <param name="values">The array whose permutations need to be generated</param>. /// <param name="inPlace"> /// If set to true, the different generated permutations will be stored in /// the same array, thus preserving memory. However, this may prevent the /// samples from being stored in other locations without having to clone /// them. If set to false, a new memory block will be allocated for each /// new object in the sequence.</param> /// /// <example> /// <code> /// // Let's say we would like to generate all possible permutations /// // of the elements (1, 2, 3). In order to enumerate all those /// // permutations, we can use: /// /// int[] values = { 1, 2, 3 }; /// /// foreach (int[] permutation in Combinatorics.Permutations(values)) /// { /// // The permutations will be generated in the following order: /// // /// // { 1, 3, 2 }; /// // { 2, 1, 3 }; /// // { 2, 3, 1 }; /// // { 3, 1, 2 }; /// // { 3, 2, 1 }; /// // /// } /// </code> /// </example> /// public static IEnumerable <T[]> Permutations <T>(T[] values, bool inPlace = false) { T[] current = new T[values.Length]; yield return(inPlace ? values : (T[])values.Clone()); int[] idx = Matrix.Indices(0, values.Length); int j, l; while (true) { for (j = values.Length - 2; j >= 0; j--) { if (idx[j + 1] > idx[j]) { break; } } if (j == -1) { yield break; } for (l = values.Length - 1; l > j; l--) { if (idx[l] > idx[j]) { break; } } int temp = idx[j]; idx[j] = idx[l]; idx[l] = temp; for (int i = j + 1; i < idx.Length; i++) { if (i > idx.Length - i + j) { break; } temp = idx[i]; idx[i] = idx[idx.Length - i + j]; idx[idx.Length - i + j] = temp; } for (int i = 0; i < values.Length; i++) { current[i] = values[idx[i]]; } yield return(inPlace ? current : (T[])current.Clone()); } }
/// <summary> /// Enumerates all possible value permutations for /// a given array. /// </summary> /// public static IEnumerable <T[]> Permutations <T>(T[] values) { int[] idx = Matrix.Indices(0, values.Length); int j, l; while (true) { for (j = values.Length - 2; j >= 0; j--) { if (idx[j + 1] > idx[j]) { break; } } if (j == -1) { yield break; } for (l = values.Length - 1; l > j; l--) { if (idx[l] > idx[j]) { break; } } int temp = idx[j]; idx[j] = idx[l]; idx[l] = temp; for (int i = j + 1; i < idx.Length; i++) { if (i > idx.Length - i + j) { break; } temp = idx[i]; idx[i] = idx[idx.Length - i + j]; idx[idx.Length - i + j] = temp; } yield return(values.Submatrix(idx)); } }
/// <summary> /// Sorts the elements of an entire one-dimensional array using the given comparison. /// </summary> /// public static void Sort <T>(this T[] values, out int[] order, bool stable = false, ComparerDirection direction = ComparerDirection.Ascending) where T : IComparable <T> { if (!stable) { order = Matrix.Indices(values.Length); if (direction == ComparerDirection.Ascending) { Array.Sort(values, order); } else { Array.Sort(values, order, new GeneralComparer <T>(direction)); } return; } var keys = new KeyValuePair <int, T> [values.Length]; for (var i = 0; i < values.Length; i++) { keys[i] = new KeyValuePair <int, T>(i, values[i]); } if (direction == ComparerDirection.Ascending) { Array.Sort(keys, values, new StableComparer <T>((a, b) => a.CompareTo(b))); } else { Array.Sort(keys, values, new StableComparer <T>((a, b) => - a.CompareTo(b))); } order = new int[values.Length]; for (int i = 0; i < keys.Length; i++) { order[i] = keys[i].Key; } }