1

i'm code:

       Random rand = new Random();
       int[] arr = new int[4];
       for (int i = 0; i < 4; i++)
       {
           for (int k = 0; k < 4; k++)
           {
               int rad = rand.Next(1, 5);
               if (arr[k] != rad)
                   arr[i] = rad;
           }
       }
       for (int i = 0; i < 4; i++)
           MessageBox.Show(arr[i].ToString());

I wanna production numbers from 1 to 4 am and unequal with each other. tnx.

Chavoshipor
  • 71
  • 1
  • 7
  • 4
    create array `{1,2,3,4}` and shuffle it with another algorithm. this is common http://www.dotnetperls.com/fisher-yates-shuffle – M.kazem Akhgary Feb 24 '16 at 10:25

4 Answers4

2

Create an array with unique elements and then shuffle it, like in the code below, it will shuffle an array in uniformly random order it uses Fisher-Yates shuffle algorithm:

int N = 20;
var theArray = new int[N];
for (int i = 0; i < N; i++)
    theArray[i] = i;

Shuffle(theArray);

public static void Shuffle(int[] a) {
    if (a == null) throw new ArgumentNullException("Array is null");
    int n = a.Length;
    var theRandom = new Random();
    for (int i = 0; i < n; i++) {
        int r = i + theRandom.Next(n-i);     // between i and n-1
        int temp = a[i];
        a[i] = a[r];
        a[r] = temp;
    }
}

Explanation and template version of algorithm could be found in this post with nice answer from Jon Skeet.

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    // Note i > 0 to avoid final pointless iteration
    for (int i = elements.Length-1; i > 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        int swapIndex = rng.Next(i + 1);
        T tmp = elements[i];
        elements[i] = elements[swapIndex];
        elements[swapIndex] = tmp;
    }
    // Lazily yield (avoiding aliasing issues etc)
    foreach (T element in elements)
    {
        yield return element;
    }
}
Community
  • 1
  • 1
Ivan Leonenko
  • 2,363
  • 2
  • 27
  • 37
2

Think it the other way round:

instead of:

generating a number and then check it if it is not duplicate

you make it such that:

you already have a set of non-duplicate numbers, then you take it one-by-one - removing the possibilities of duplicates.

Something like this will do:

List<int> list = Enumerable.Range(1, 4).ToList();
List<int> rndList = new List<int>();
Random rnd = new Random();
int no = 0;
for (int i = 0; i < 4; ++i) {
    no = rnd.Next(0, list.Count);
    rndList.Add(list[no]);
    list.Remove(list[no]);
}

The result is in your rndList.

This way, no duplicate will occur.

Ian
  • 30,182
  • 19
  • 69
  • 107
  • After running you code `rndList` contains `0, 0, 3, 0`, which is not unique as OP asked, and also generating a number and then checking for duplicate is less efficient than simple Fisher-Yates. – Ivan Leonenko Feb 10 '17 at 20:49
  • @IvanLeonenko corrected. It should be `list[no]` instead of `no`. Thanks for the notification. About the efficiency, I do not really have profile between them. But the Fisher Yates algorithm could be faster than my simple algorithm, as you say. My opinion is just that the algorithm I offer is quite simple and straightforward. – Ian Feb 11 '17 at 14:07
1

Create a list containing the numbers you want, then shuffle them:

var rnd = new Random();
List<int> rndList = Enumerable.Range(1, 4).OrderBy(r => rnd.Next()).ToList();

If you want an array instead of a list:

var rnd = new Random();
int[] rndArray = Enumerable.Range(1, 4).OrderBy(r => rnd.Next()).ToArray();
kkyr
  • 3,785
  • 3
  • 29
  • 59
  • Thanks. I do not wanna I use from the list . I wanna do the right array . Because I have a game right – Chavoshipor Feb 24 '16 at 10:33
  • @user5566530 Updated for an array as well – kkyr Feb 24 '16 at 10:35
  • 1
    I know this approach works, but I always hate seeing O(N Log(N)) algorithms being proposed when an O(N) one exists. – Matthew Watson Feb 24 '16 at 10:37
  • 2
    This implementation is O(n log n) and the one I gave is O(n). Also this implementation doesn't give you uniformly random order. Please see explanation in this post http://stackoverflow.com/questions/1287567/is-using-random-and-orderby-a-good-shuffle-algorithm – Ivan Leonenko Feb 24 '16 at 10:40
-2
int[] arr = new int[5];
int i = 0;
while (i < 5)
{
    Random rand = new Random();
    int a = rand.Next(1,6);

    bool alreadyexist = false;
    for (int j = 0; j < 5; j++)
    {

        if (a == arr[j])
        {
            alreadyexist = true;
        }

    }
    if (alreadyexist == false)
    {
        arr[i] = a;
        i++;
    }

}
for (int k = 0; k < 5; k++)
{

    MessageBox.Show(arr[k].ToString());
}
Ian
  • 30,182
  • 19
  • 69
  • 107
Hassan Tariq
  • 730
  • 7
  • 15
  • 2
    You shouldn't create Random each iteration it could give the same order and values if it happens too frequently. Complexity is above linear, especially with such implementation when you create Random object too frequently. Also this implementation doesn't give you uniformly random order, use at least Fisher-Yates. This answer should not be accepted. – Ivan Leonenko Feb 24 '16 at 11:02
  • Thanks. But this answer and the answer I was helped in my project – Chavoshipor Mar 02 '16 at 07:41
  • Why did you change this question from answerd to non answerd after @user5566530 – Hassan Tariq Jul 04 '16 at 09:59