0

I'm trying to randomly get a specific integer (1) from a 2D array list filled with 0's and not many 1's. I made this, and it works:

while (wallsList[randomX, randomY] != 1)
{
    randomX = randomizer.Next(34);
    randomY = randomizer.Next(34);
}

The downside of it, it's that it takes too much time to just find one time the int (1), and I have to do this process over 1000 times since new 1's get added and removed to the 2D array each time. It takes about 3m to launch my program so I would like to know if there is an optimized version of this, I searched a lot and only found this solution for 1D arrays. Thanks for your time.

5
  • 4
    why you must search for it randomly? why don't seek it linearly? Commented Jun 1, 2016 at 20:24
  • An optimized version of that would be to not search for a known value at random indices. Unless there is a very good reason for randomly searching like this, don't. Commented Jun 1, 2016 at 20:28
  • What is your question? How To get the 1 quicker? Why are you randomly looking for a wall in the first place? This make no sense Commented Jun 1, 2016 at 20:30
  • If you are going to randomly stab at the array in an attempt to find some value then your worse case performance would be O(infinity). That's not a good thing. And you say "I searched a lot and only found this solution for 1D arrays." what solution are you referring to? Commented Jun 1, 2016 at 20:31
  • I think you really want is to use 2 for loops Commented Jun 1, 2016 at 20:37

4 Answers 4

3

You have a sparse array. Why not represent it as a list of X/Y int pairs? Then, if the X/Y int pair is in the list, it's a 1, if not, it's a 0.

Then, to find a random value/cell containing 1, you just pick a random value from the list.

You could use a list like

new List <Tuple<int, int>> { new Tuple<int, int>(1, 5), new Tuple<int, int>(2, 7) }
Sign up to request clarification or add additional context in comments.

Comments

3

Since most of your random guesses will fail, it would be far more efficient to build a second array of known good indexes and randomly search only those.

var randomizer = new Random();
var wallsList = new int[34, 34];
wallsList[23,11] = 1;

// Build an array of points that are known to pass
var knownHits = 
    (from x in Enumerable.Range(0, 34)
     from y in Enumerable.Range(0, 34) 
     where wallsList[x, y] == 1
     select new { x, y })
    .ToArray(); 

// Pick a random point from previous array
var randomPoint = knownHits[randomizer.Next(knownHits.Length)]; 
var randomX = randomPoint.x;
var randomY = randomPoint.y;

Console.Write($"X = {randomX}, Y = {randomY}"); // X = 23, Y = 11

Alternatively, you could build the secondary array like this:

var knownHits = wallsList.Cast<int>()
    .Select((v, i) => new { v, x = i / 34, y = i % 34 })
    .Where(x => x.v == 1)
    .ToArray();

1 Comment

I suspect this is some kind of homework assignment so I don't know if the OP will be able to do this, but yea, this way is a lot better to do it
0

There are a few approaches you can take. One would be to change your representation from a 2d array into something like a list of pairs of coordinates. Now selecting one at random is easy, but maybe some other operations you want to perform become harder. This approach and yours have the advantage that it selects one of the 1's uniformly. Another approach that would sacrifice this quality would be to choose a random x and y and then return the next 1, scanning by x or y. This is also not as efficient as the first solution.

Comments

0

I'm trying to randomly get a specific integer (1) from a 2D array list filled with 0's and not many

If you must do it randomly, your approach is fine. However, what you can improve it by avoiding drawing the same index again :

var randomizer = new Random();
var wallsList = new int[34, 34];
wallsList[01, 23] = 1;

var indexes =
    from x in Enumerable.Range(0, 34)
    from y in Enumerable.Range(0, 34)
    select new { X = x, Y = y };

var result = indexes
    .OrderBy(_ => randomizer.Next())
    .FirstOrDefault(index => wallsList[index.X, index.Y] == 1);
if (result == null)
    throw new Exception("Index not found");

Console.WriteLine("1 is found at[{0}, {1}]", result.X, result.Y);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.