1

I have a 2D array in which are some indexes null and some of indexes have value. I want to select a random index that contains null.

example

5,0,0,5,0
4,0,0,4,7
9,0,4,8,9
0,8,4,0,1

i want to choose random index from these which are zero

thx for reply

Jens
  • 67,715
  • 15
  • 98
  • 113

6 Answers6

2

Or you can try this : put index of '0' as key/value on a map, then :

   Random   random = new Random();
   Map x= new HashMap();
    x.put(0,1); 

....

List keys      = new ArrayList<Integer>(x.keySet());
Integer randomX = keys.get( random.nextInt(keys.size()) );
Integer value  = x.get(randomX );
Saimir
  • 210
  • 2
  • 12
0

You could use simple trick - just map your zero values to array. Or better solution is only count the number of zero values, so, you should iterate through your 2D array and compare values - if you want find zero, then it should be:

int count = 0;
for(int i=0;i< array.length;i++)
  for(int j=0;j< array[i].length;j++)
    if(array[i][j] == 0)
      count++;

After that you can get random number from your interval 1-count and then iterate your 2D array and choose the zero number with random position.

int randomPosition = (int )(Math.random() * (count-1));
int now=0;
if(randomPosition > -1)
  for(int i=0;i< array.length;i++)
    for(int j=0;j< array[i].length;j++)
      if(array[i][j]==0){
         now++;
         if(now == randomPosition){
         rowPosition = i;
         columnPosition = j;
        }
      }

This is not really the correct way how to do it and if you can, you should not use null values - or zeros as null values in your design, better think about another solution to save values in 2D arrays. Do you really need null values or zero values there?And why do you need return random null position?

Matus Danoczi
  • 137
  • 1
  • 10
  • i am making random algorithm for gomoku, so i need choose the random position from empties thx for replies – Marek Forst Feb 14 '15 at 17:03
  • @MarekForst ok, i do not know the game, but if you really need it, you could use the I wrote, which is not effective, but solve your problem :) – Matus Danoczi Feb 14 '15 at 19:00
0
//Init array
int array[][] = { { 5, 0, 0, 5, 0 }, { 4, 0, 0, 4, 7 },
                  { 9, 0, 4, 8, 9 }, { 0, 8, 4, 0, 1 } };

//Init vector for indices of elements with 0 value
ArrayList<int[]> indices = new ArrayList<int[]>();

//Find indices of element with 0 value
for (int i = 0; i < array.length; i++)
{
    for (int j = 0; j < array[i].length; j++)
    {
        if (array[i][j] == 0)
        {
            indices.add(new int[] { i, j });
        }
    }
}

//Just print the possible candidates
for (int[] index : indices)
{
   System.out.println("Index = (" + index[0] + ", " + index[1] + ")");
}
System.out.println();

//Select a random index and print the result
Random rand = new Random();
int ri = rand.nextInt(indices.size());
int[] index = indices.get(ri);

System.out.println("Selected index = (" + index[0] + ", " + index[1] + ")");

The solution is based that it is easy to select a random value in a 1D array. Therefore as the first step all the indices belongs to elements with value 0 are collected in a ArrayList object, then the select of a random element in this ArrayList object results the searched indices.

Tibor Takács
  • 3,535
  • 1
  • 20
  • 23
  • Netbeans says: This inspection reports any uses of java.util.Vector or java.util.Hashtable. While still supported, these classes were made obsolete by the JDK1.2 collection classes, and should probably not be used in new development. Why is used Vector? thx for reply to all! – Marek Forst Feb 14 '15 at 17:24
  • Good question. The answer is written here: http://stackoverflow.com/questions/1386275/why-is-java-vector-class-considered-obsolete-or-deprecated I have changed the Vector object to ArrayList. – Tibor Takács Feb 14 '15 at 18:00
0

From your question, I understand you want to select a random element (that contains 0) in a 2-dimensional array in Java. First of all, you should understand that since most numbers are value-based, 0 != null. This will help to make your question clearer.

Now, you will first have to loop through your array to determine which elements are 0, recording the positions where each 0 element is placed. Then, you generate a random number to determine which 0 element should be picked:

//determines amt of 0s in array
ArrayList<ArrayList<int>> keys = new ArrayList<>();
for (int i = 0; i < array.length; i++) {
    ArrayList<int> inner = new ArrayList<int>();
    for (int j = 0; j < array[i].length; j++) {
        if (i == 0) { inner.add(j); }
    }
    keys.add(inner);
}

Random r = new Random();
//TODO: generate random number, determine which element to pick

Hope this helps.

James Ko
  • 32,215
  • 30
  • 128
  • 239
0

This solution is maybe a bit long, but effective. I tried to solve this with java streams:

First what you need is to convert 2D array into a simple IntStream. The simplest way could be something like:

Arrays.stream(arr).flatMapToInt(intArr -> Arrays.stream(intArr));

Our stream now looks like this:

{5,0,0,0,5,0,4,0,0,4,7,9...}

Next you need to get stream with values like key-value (index-value in this case). This is quite hard with streams and there is maybe an easier solution, but I created a KeyValue class with auto-incrementation of index:

class KeyValue {
    int index;
    int value;
    static int nextIndex;

    public KeyValue(int v) {
        this.index = nextIndex;
        nextIndex++;
        this.value = v;
    }
    public static void restart() {
        nextIndex = 0;
    }
}

Now it is easy to convert our stream to index-value items. Call:

.mapToObj(KeyValue::new)

Now our stream looks like this:

{KeyValue[i=0 v=5], KeyValue[i=1 v=0], KeyValue[i=2 v=0], KeyValue[i=3 v=0]...}

Now filter zeros and collect stream to an array:

.filter(kv -> kv.value == 0).toArray(KeyValue[]::new);

Whole code to create an array is:

KeyValue[] zeros = Arrays
                .stream(arr)
                .flatMapToInt(intArr -> Arrays.stream(intArr))
                .mapToObj(KeyValue::new)
                .filter(k -> k.value == 0)
                .toArray(KeyValue[]::new);

Now it is pretty easy to get a random value from the array:

int ourResult = zeros[random.nextInt(zeros.length)].index;

Whole code will look like this:

int[][] arr = new int[][]
            {
                    {5, 0, 0, 5, 0},
                    {4, 0, 0, 4, 7},
                    {9, 0, 4, 8, 9},
                    {0, 8, 4, 0, 1}
            };
    Random random = new Random();
    KeyValue.restart();
    KeyValue[] zeros = Arrays
            .stream(arr)
            .flatMapToInt(intArr -> Arrays.stream(intArr))
            .mapToObj(KeyValue::new)
            .filter(k -> k.value == 0)
            .toArray(KeyValue[]::new);
    int ourResult = zeros[random.nextInt(zeros.length)].index;

Happy coding :)

MaKri
  • 190
  • 1
  • 8
0

I was looking for this answer, and come up with this in processing:

// object to hold some info
class Point {
    // public fields fine for Point object
    public int i, j, count;
    // constructor
    public Point (int i, int j) {
        this.i = i;
        this.j = j;
        this.count = 0;
    }

    public String toString() {
        return i + " , " + j;
    }
}
int[][] grid;

// processing needs to init grid in setup
void setup() {
    // init grid
    grid = new int[][] {
    {5,1,2},
    {3,4,4},
    {4,0,1}
    };
println(getRandomZero(new Point(0,0)));
}

// recursion try for 300 random samples
Point getRandomZero(Point e) {
    // base case
    Point p = e;
    if (grid[p.i][p.j] != 0 && p.i < grid.length && p.j < grid[p.i].length) {
        p.i = randomInt(0,grid.length);
        p.j = randomInt(0,grid[p.i].length);
        p.count++;
// if can't find it in 300 tries return null (probably not any empties)
        if (p.count > 300) return null;
        p = getRandomZero(p);
    }
    return p;
}
// use Random obj = new Random() for Java
int randomInt(int low, int high) {
    float random = random(1);
    return (int) ((high-low)*random)+low;
}

I'll edit for Java specifically tomorrow.

0x_a6
  • 1
  • 1