1

I have two dimensional array. I want to pick a slot at random, and continue to do so never picking the same slot twice until I have finally picked all slots (so nothing random about the last pick of course). Is there a well known algorithm for doing this? I'm using C#, but obviously this is more about algorithms than any particular platform. Yes, 'the big book' is on my purchase list :)

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Myles McDonnell
  • 12,943
  • 17
  • 66
  • 116
  • 1
    You are looking for a [random permutation](http://stackoverflow.com/search?q=%5Bc%23%5D+random+permutation) of the set of slots. – dtb Mar 04 '12 at 19:04
  • 1
    possible duplicate of [Random playlist algorithm](http://stackoverflow.com/questions/1816534/random-playlist-algorithm) – dtb Mar 04 '12 at 19:04

4 Answers4

5

Take a look at the Fisher-Yates shuffle. It's designed to pick a random permutation from a set.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

Using the Fisher-Yates shuffle algorithm as mentioned before (in O(n) time)

int X = 3;  int Y = 4;
int[] array = new int[X * Y];

for (int i = 0; i < array.Length; i++) array[i] = i;
FisherYatesShuffle(array);

var randomSlots = array.Select((i,j) => new {x=array[j]%X , y=array[j]/X })
                       .ToArray();

public static void FisherYatesShuffle<T>(T[] array)
{
    Random r = new Random();
    for (int i = array.Length - 1; i > 0; i--)
    {
        int j = r.Next(0, i + 1);
        T temp = array[j];
        array[j] = array[i];
        array[i] = temp;
    }
}
L.B
  • 114,136
  • 19
  • 178
  • 224
1

Assuming your array is like this:

Random rand = new Random();

object[,] array = new object[width,height];
bool[,] chosen = new bool[width,height];

int i, j;
do
{
    i = rand.Next(width);
    j = rand.Next(height);
} while (chosen[i,j]);

chosen[i,j] = true;
object current = array[i,j];

This should work fine.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
  • Thanks, better than the recursive solution above, but still we will tend to loop more and more as we get toward the end of the set. Perhaps this is just an unavoidable issue? – Myles McDonnell Mar 04 '12 at 19:32
  • @MylesMcDonnell I don't think it's avoidable, and your edit broke the functionality of the code. it is not supposed to be a `!`, if chosen is set to true, that index is invalid. I have rolled the code back. – Richard J. Ross III Mar 04 '12 at 19:39
  • Sorry for messing with your answer ;) – Omar Mar 04 '12 at 19:40
  • @RichardJ.RossIII Apologies..@Fuex I think we both made the same mistake – Myles McDonnell Mar 04 '12 at 21:06
0

I did this for numbers

list<int> PastList=new PastList<int>();
private void Choоse()
{
   int i = Recurs();
   PastList.Add(i);
}

private int Recurs()
{
   int i;

   i = rnd.Next(0, 99);
   if (PastList.Contains(i))
   {
       i = Recurs();
   }

   return i;
}
Omar
  • 16,329
  • 10
  • 48
  • 66
Stecenko Ruslan
  • 293
  • 1
  • 3
  • The problem with this is the closer we get to the end of the set more recursion occurs. It could take a lot of calls to rnd.Next(0,99) to get the last item. Ouch. – Myles McDonnell Mar 04 '12 at 19:28