0

I would like to check the array I passed in the shuffle method for any duplicates. I would like to also generate a random number that is the size of a.length.

The thing is that I can't figure out how to check if the array has duplicates and if it does it would generate another number until it is unique from the rest.

public int[] Shuffle(int[] a)
    {

        //check if the array has duplicates
        for (int i = 0; i < a.Length; i++)
        {
            int curValue = random.Next(a.Length);
            if(a.Contains(curValue))
            {
                curValue = random.Next(a.Length);
            }
            else
            {
                a[i] = curValue;
            }
        }

        for (int i = 0; i < a.Length; i++)
        {
            int r = random.Next(a.Length);
            int t = a[r];
            a[r] = a[i];
            a[i] = t;
        }

        return a;
    }

Can anyone help me?

user3679003
  • 9
  • 1
  • 1
  • 8
  • 1
    This seems like an odd thing to do (what is the input array? does only its size matter? E: after the edit the input is used, but in a strange way), also your shuffle part is wrong in a sneaky and hard to notice way. – harold Apr 19 '17 at 18:27
  • First I want to populate my array with a random number depends on my array.length. But I don't want duplicates then I want to shuffle my array at a random position depending on the array length. Any suggestions? – user3679003 Apr 19 '17 at 18:32
  • 1
    Read about Linq's `.Distinct()` method. As for the all together generating a collection of random unique numbers search more in SO I've seen many solutions for that in the past – Gilad Green Apr 19 '17 at 18:32
  • What your shuffle should really be doing is swapping the values at *two* randomly chosen indices. Also, you might want to allow for more than one shuffle, i.e. take an arg which is the number of shuffle iterations. – rory.ap Apr 19 '17 at 18:32
  • Why do you pass an array to the method? If it's only going to return an array with random numbers between 0 and length, why not just pass the length? – Zohar Peled Apr 19 '17 at 18:34
  • 4
    If you just want the numbers 0 .. a.length - 1, you can just put them in there in a simple way (`a[i] = i`), and then shuffle them (look up a Knuth shuffle, it's *really* easy to get shuffles wrong) – harold Apr 19 '17 at 18:34
  • 3
    I recommend you use the [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle). Basically generate a random number in the range of size of the collection, take the value from that position, then remove it from the collection making the range one smaller the next time. Repeat until the collection is empty. – juharr Apr 19 '17 at 18:36

1 Answers1

0

Here is a function that does what you ask as I presume. Include using System.Linq to run it. I went on the basis of your text, because the code did not make your question clear to me. If you meant something differently please clarify.

        static int[] Shuffle(int[] a)
    {
        Random rnd = new Random();

        //Remove duplicates from array
        int[] distinct = a.Distinct().ToArray();

        //Add the same amount of unique numbers that have been removed as duplicates
        int len = a.Length - distinct.Length;
        int[] newNumbers = new int[len];
        int i = 0;
        while(i < len)
        {
            newNumbers[i] = rnd.Next(a.Length); //NOTE: here i put in the length of array a, but with an int array this will always resolve in a shuffled array containing all digits from 0 to the length-1 of the array.
            if (!distinct.Contains(newNumbers[i])  && !newNumbers.Take(i).Contains(newNumbers[i]))
            {
                ++i;
            }
        }

        //Randomize the array           
        int[] b = a.OrderBy(x => rnd.Next()).ToArray();

        //Concatenate the two arrays and return it (shuffled numbers and new unique numbers)
        return distinct.Concat(newNumbers).ToArray();
    }

As I said in the note, if you remain with an integer array and only allow adding of new random replacement number lower than the length of the array, you and up with a shuffled array of all numbers from 0 to the array length.

Since a new array for newNumbers is generated, you also need to check if a newly generated number is not in that array.

D.J. Klomp
  • 2,429
  • 1
  • 15
  • 30
  • This really helped me out. This actually helped me figure out what my problem was. – user3679003 Apr 19 '17 at 20:06
  • It is, unfortunately, a pretty bad way to actually do it.. – harold Apr 19 '17 at 20:25
  • Glad to be of help, please accept as answer or up-vote if it helped. @Harold, of course there are better ways to do this, this code will be far from efficient so please supply a better implementation if willing. – D.J. Klomp Apr 19 '17 at 20:43