1

配列をランダム化する方法を見つけるのを手伝ってくれませんか? 例えば:

int[] arrayInt = { 1, 2, 3, 4, 5, 6, 7 };

ランダム化した後、結果を別の配列に格納する必要があります。

また、再度ランダム化するときは、2 番目の配列に格納されている値と比較する必要があります。その値が存在する場合、プログラムは再度ランダム化する必要があります。

4

5 に答える 5

7

Enumerable.OrderBy入力配列をランダム変数で順序付けするために使用するアプローチを次に示します。新しいシーケンスが生成された後、次のように入力配列と比較されますSequenceEqual

public static T[] UniqueRandomArray<T>(T[] input, Random rnd)
{
    if (input.Length <= 1) throw new ArgumentException("Input array must have at least two elements, otherwise the output would be the same.", "input");
    IEnumerable<T> rndSeq;
    while (input.SequenceEqual(rndSeq = input.OrderBy(x => rnd.Next())));
    return rndSeq.ToArray();
}

このコード例は、リストに追加される 10 個の新しい配列を生成します。新しい配列が前の配列と異なることが保証されます。

Random rnd = new Random();
List<int[]> randomArrays = new List<int[]>();
int[] arrayInt1 = { 1, 2, 3, 4, 5, 6, 7 };
randomArrays.Add(arrayInt1);

for (int i = 0; i < 10; i++)
{
    int[] lastArray = randomArrays[randomArrays.Count - 1];
    int[] randomArray = UniqueRandomArray(lastArray, rnd);
    randomArrays.Add(randomArray);
}

デモ

于 2013-05-10T07:31:54.153 に答える
1

linqの使用

        Random rand = new Random();
        int[] arrayInt =
            new[] {1, 2, 3, 4, 5, 6, 7}.Select(x => new {x, r = rand.Next()})
                                       .OrderBy(x => x.r)
                                       .Select(x => x.x)
                                       .ToArray();

このように任意のタイプをランダム化できます

public static class RandomExt
{
    public static T[] RandomizeOrder<T>(this T[] array)
    {
        var rand = new Random();
        return array.Select(x => new {x, r = rand.Next()})
                                       .OrderBy(x => x.r)
                                       .Select(x => x.x)
                                       .ToArray();
    }
}

int[] arrayInt = new[] {1, 2, 3, 4, 5, 6, 7}.RandomizeOrder();
于 2013-05-10T07:32:03.707 に答える
0

お役に立てれば。比較のために安全な暗号プロバイダーと安全なハッシュを使用します - やり過ぎなので、使用するプロバイダーを自由に調整してください:)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Collections;
using System.Collections.Concurrent;

namespace RandomiseArray
{
    static class Program
    {
        static void Main(string[] args)
        {
            // source array
            string[] s = new string[] { "a", "b", "c", "d", "e", "f", "g" };

            // number of unique random combinations required
            int combinationsRequired = 5;
            var randomCombinations = s.Randomise(System.Text.UnicodeEncoding.Unicode.GetBytes, combinationsRequired);

            foreach (var c in randomCombinations)
                Console.WriteLine(c.Aggregate((x, y) => x + "," + y));

            Console.ReadLine();
        }

        /// <summary>
        /// given a source array and a function to convert any item in the source array to a byte array, produce x unique random sequences
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="byteFunction"></param>
        /// <param name="x"></param>
        /// <returns></returns>
        public static IEnumerable<IEnumerable<T>> Randomise<T>(this IEnumerable<T> source, Func<T, byte[]> byteFunction, int x)
        {
            var foundValues = new ConcurrentDictionary<byte[], T[]>();
            int found = 0;
            do
            {
                T[] y = source.Randomise().ToArray();
                var h = y.Hash(byteFunction);
                if (!foundValues.Keys.Contains(h))
                {
                    found++;
                    foundValues[h] = y;
                    yield return y;         // guaranteed unique combination  (well, within the collision scope of SHA512...)
                }
            } while (found < x);
        }

        public static IEnumerable<T> Randomise<T>(this IEnumerable<T> source)
        {
            using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
                return source.OrderBy(i => rng.Next());
        }

        public static int Next(this RNGCryptoServiceProvider rng)
        {
            byte[] buf = new byte[4];
            rng.GetBytes(buf);
            return BitConverter.ToInt32(buf, 0);
        }

        public static byte[] Hash<T>(this IEnumerable<T> items, Func<T, byte[]> getItemBytes)
        {
            using (SHA512CryptoServiceProvider sha = new SHA512CryptoServiceProvider())
                return sha.ComputeHash(items.SelectMany(i => getItemBytes(i)).ToArray());
        }
    }
}
于 2013-05-10T08:19:30.970 に答える
0

OrderBy はシャッフルする良い方法ですが、O(n log n) の並べ替えを使用します。シャッフルは O(n) で実行できます。

これはウィキペディアの擬似コードです

 for i from n − 1 downto 1 do
       j ← random integer with 0 ≤ j ≤ i
       exchange a[j] and a[i]
于 2013-05-10T08:22:48.643 に答える