/// <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 = Vector.Range(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> /// Returns a vector containing indices (0, 1, 2, ..., n - 1) in random /// order. The vector grows up to to <paramref name="size"/>, but does not /// include <c>size</c> among its values. /// </summary> /// /// <param name="size">The size of the sample vector to be generated.</param> /// /// <example> /// <code> /// var a = Vector.Sample(3); // a possible output is { 2, 1, 0 }; /// var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 }; /// /// foreach (var i in Vector.Sample(5)) /// { /// // ... /// } /// </code> /// </example> /// public static int[] Sample(int size) { var random = Accord.Math.Random.Generator.Random; var idx = Vector.Range(size); var x = new double[idx.Length]; for (int i = 0; i < x.Length; i++) { x[i] = random.NextDouble(); } Array.Sort(x, idx); return(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 = Vector.Range(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; } }
/// <summary> /// Creates a vector containing every index that can be used to /// address a given <paramref name="array"/>, in order. /// </summary> /// /// <param name="array">The array whose indices will be returned.</param> /// /// <returns> /// A vector of the same size as the given <paramref name="array"/> /// containing all vector indices from 0 up to the length of /// <paramref name="array"/>. /// </returns> /// /// <example> /// <code> /// double[] a = { 5.3, 2.3, 4.2 }; /// int[] idx = a.GetIndices(); // output will be { 0, 1, 2 } /// </code> /// </example> /// /// <seealso cref="Matrix.GetIndices"/> /// public static int[] GetIndices <T>(this T[] array) { return(Vector.Range(0, array.Length)); }