Home > database >  Populate 2D array with range of random integers, but keep a fixed number of X elements always the sa
Populate 2D array with range of random integers, but keep a fixed number of X elements always the sa

Time:10-23

I generate random unique integers from 0 to 90:

   public static int randomNumber() {
      int min = 0;
      int max = 90;
      return min   (int) (Math.random() * ((max - min)   1));
   }

... and use those generated integers to populate a multidimensional 3*5 array:

   int rows = 3;
   int columns = 5;
   int[][] array = new int[rows][columns];

   public static void populateArray(int[][] array, int rows, int columns) {
      for (int indexRow = 0; indexRow < rows; indexRow  ) {
         for (int indexColumn = 0; indexColumn < columns; indexColumn  ) {
            array[indexRow][indexColumn] = randomNumber();
         }
      }
   }

... and this generates something like this:

56  64  22  38  78  
73  18  69  39  70  
49  24  3   49  25

However, I would like a fixed number of, say, 5 random elements in the array (no more, no less than 5 random elements) to be always 0, like this:

0   64  22  38  0   
73  18  0   39  70  
0   24  3   0   25

Is there any way to achieve that?

CodePudding user response:

You can first evaluate random positions where your matrix would have zeros:

static int[] zeroPositions(int totalPositions, int zeroPositions){
    int[] result = new int[zeroPositions];
    Random random = new Random();
    for(int i = 0; i < zeroPositions; i  ){
        int currentPosition = random.nextInt(totalPositions);
        while (contains(result, currentPosition)){
            currentPosition = (currentPosition   1) % totalPositions;
        }
        result[i] = currentPosition;
    }
    return result;
}

At the above code I omit some checks like that zero positions to be not greater than total positions (to save space).

Another what you need here and a bit later is a method that checks if an array contains a value:

public static boolean contains(int[] source, int value){
    for(int i = 0; i < source.length; i  ){
        if(source[i] == value){
            return true;
        }
    }
    return false;
}

Now you should amend your randomNumber method in order to have minim as 1 since zeroes would be just not filled cells.

public static int randomNumber() {
    int min = 1; // skip 0
    int max = 90;
    return min   (int) (Math.random() * ((max - min)   1));
} 

And amend populateArray method to test if a current position has to hold zero:

public static void populateArray(int[][] array, int rows, int columns, int[] zeroPositions) {

    for (int indexRow = 0; indexRow < rows; indexRow  ) {
        for (int indexColumn = 0; indexColumn < columns; indexColumn  ) {
            if(!contains(zeroPositions, indexRow * columns   indexColumn)){
                array[indexRow][indexColumn] = randomNumber();
            }
        }
    }
}

Now let's run everything:

public static void main(String[] args) {
    int rows = 3;
    int cols = 5;
    int[][] matrix = new int[rows][cols];
    populateArray(matrix, rows, cols, zeroPositions(rows * cols, 5));
    for(int i = 0; i < rows; i  ){
        for(int j = 0; j < cols; j  ){
            System.out.print(matrix[i][j]   " ");
        }
        System.out.println("");
    }
}

And finally some outputs:

8 58 0 0 28 
39 79 54 0 0 
28 0 30 51 56 

65 81 27 0 0 
17 21 74 0 0 
0 16 47 69 80 

44 0 18 57 30 
0 0 37 76 61 
0 0 38 77 20 

CodePudding user response:

Try this.

public static void populateArray(int[][] array, int fixedNumber, int fixedNumberCount) {
    int rows = array.length, cols = array[0].length, size = rows * cols;
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < fixedNumberCount;   i)
        list.add(fixedNumber);
    for (int i = fixedNumberCount; i < size;) {
        int r = randomNumber();
        if (r == fixedNumber) continue;
        list.add(r);
          i;
    }
    Collections.shuffle(list);
    for (int r = 0, i = 0; r < rows;   r)
        for (int c = 0; c < cols;   c,   i)
            array[r][c] = list.get(i);
}

public static void main(String[] args) {
    int[][] array = new int[5][5];
    populateArray(array, 0, 5);
    for (int[] row : array)
        System.out.println(Arrays.toString(row));
}

output:

[9, 71, 57, 86, 70]
[0, 0, 17, 70, 22]
[21, 0, 72, 7, 83]
[18, 37, 45, 8, 10]
[42, 8, 0, 85, 0]

CodePudding user response:

Ok, I went a little overboard to make it more general.

int[][] result = create(3,5,5,90);
for (int[] r : result) {
    System.out.println(Arrays.toString(r));
}

prints

[0, 48, 0, 0, 41]
[0, 32, 0, 0, 0]
[0, 0, 0, 81, 25]

  • first check the invariant to ensure the count is <= row * cols
  • create an array of 0's to fill result array
  • then generate an array of indices into the result array
  • Then fill result array by randomly selecting and index and the new number to be stored.
  • adjust the indices array to not repeat the previous index.
  • return the result.
// rows, cols - the array dimensions
// count - is the number of randoms numbers and the 
// max - is the max size of that number.    
public static int[][] create(int rows, int cols, int count, int max) {
    int size = rows * cols;
    if (count > size) {
        throw new IllegalArgumentException(
                "Size and count don't match");
    }
    Random r = new Random();
    // an array of zeroes
    int[][] result = new int[rows][cols];
    // an array of indices into result
    int[] indices = new int[size];
    Arrays.setAll(indices, i->i  );
    // now loop thru filling in result array without
    // repeating any index.
    for (int i = 0; i < count; i  ) {
        int pos = r.nextInt(size);
        result[indices[pos]/cols][indices[pos]%cols] = r.nextInt(max) 1;
        indices[pos] = indices[--size];
    }
    return result;
        
}
  • Related