1

I have an issue about coding logic here. I have to generate an array of Boolean, based on percentage.

To clarify, I got a percentage 'X' (int value) and I want to generate a array of Boolean which is composed ox X percents of 1, randomly distributed. Moreover, the length of the array is constant.

For example, I I want to generate my array of Boolean, based on X=40, I would have:

[0,1,0,1,0,0,0,0,1,1,0,0,1,0,0,1,1,0,1,0]

I did not managed to find any easy solution or an existing function to generate this array. Mays someone can help me about this?

Thank you :)

PM 77-1
  • 12,933
  • 21
  • 68
  • 111
  • you can create empty slots first, then generate the number of true items, then place items to current available empty slots randomly one by one. This way maybe it is easier to implement. – Surely Feb 08 '19 at 17:30
  • 2
    Fill an array with consecutive zeros and ones and then do [random shuffling](https://stackoverflow.com/questions/1519736/random-shuffling-of-an-array). – PM 77-1 Feb 08 '19 at 17:31
  • @PM77-1, I think your comment precedes my answer. If you want to do your's as an answer, let me know and I'll delete mine. – Mike Samuel Feb 08 '19 at 17:43
  • @MikeSamuel - I did not want to provide the code. That's why I made it comment. Please keep your answer. – PM 77-1 Feb 08 '19 at 17:53

4 Answers4

1

Random shuffling of an array explains how to shuffle an array.

// Create an array.  Initially elements are zero
int[] arr = new int[n];
// Put the right number of 1's in it
double limit = n * (X / 100.0);
for (int i = 0; i < limit; ++i) {  // Assumes X <= 100
  arr[i] = 1;
}
// Randomize the order of elements.
shuffleArr(arr);
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
1

You can use (Math.random() < percentage) to get false or true with the desired probabilities.

double percentage = 0.4; // use 0.0 <= percentage <= 1.0
boolean[] array = new boolean[100];
for (int i = 0; i < array.length; i++) {
    array[i] = (Math.random() < percentage);
}
Thomas Fritsch
  • 9,639
  • 33
  • 37
  • 49
  • With this approach(+1) (not only the position, but also) the *count* resp. *percentage* of set bits is random (so not exact/subject to fluctuation). – xerx593 Feb 09 '19 at 14:41
1

Here is an approach for you:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;    

public class RandomizeArray {    

    public static void main(String args[]) {
        Boolean[] myArray = new Boolean[40];
        int xPercentage = 40;
        int ratio = myArray.length * xPercentage / 100;

        Arrays.fill(myArray, Boolean.FALSE);

        for(int i = 0; i<ratio; i++) {
            myArray[i] = true;
        }

        List<Boolean> l = Arrays.asList(myArray);
        Collections.shuffle(l);

        System.out.println(l);

    }    

}

Output:

[false, false, false, false, true, true, true, false, false, false, true, false, false, true, false, true, true, true, false, false, true, false, false, true, false, false, true, true, false, true, false, false, false, false, true, false, true, false, false, true]

[false, false, true, false, false, false, true, false, true, true, false, false, false, false, false, true, true, true, false, false, false, true, false, false, true, true, true, false, false, false, false, true, true, false, false, true, false, true, false, true]
sirandy
  • 1,834
  • 5
  • 27
  • 32
0

Consider a utility function, which I see handy in many use cases, like:

// Bases on {@link java.util.Random#ints(int, int)}, but "with uniqueness and limit".
static IntStream uniqueInts(int min, int max, int count, java.util.Random rnd) {
    // check parameters ... (max > min), (max - min > count), (rnd != null...)
    // call Random.ints(min, max) with distinct and limit
    return rnd.ints(min, max).distinct().limit(count);
}

, then applied to your case ...again with BitSet, because I'd hate the fact "to waste 7 bits with each boolean":

static BitSet randomBits(int total, int goodPercent, Random rand) {
    final BitSet bitSet = new BitSet(total);
    uniqueInts(0, total,  total * goodPercent / 100, rand)
        .forEach(i -> {
            bitSet.set(i);
        });
    // bitsSet.cardinality() == total * goodPercent / 100 (!)
    return bitSet;
}

..and finally (print & main methods):

static void printBits(int length, BitSet bs, PrintStream out) {
    int i = 0;
    out.append('[');
    for (; i < bs.length(); i++) {
        out.append(bs.get(i) ? '1' : '0');
    }
    // fill with zeros (according to BitSet.length() definition...
    // and provide parameter, since BitSet lacks this information).
    for (; i < length; i++) {
        out.append('0');
    }
    out.append(']');
    out.println();
}

public static void main(String[] args) {
    int total = 20;
    int goodPercent = 40;
    Random rand = new Random();
    // repeat it total times, to make a nice square
    for (int i = 0; i < total; i++) {
        BitSet test = randomBits(total, goodPercent, rand);
        printBits(total, test, System.out);
    }
}

output:

[01100011011001010000]
[01100000000101011110]
[00000101101110001001]
[01001001000110100110]
[01001110100001110000]
[00100110011100000011]
[01011100001011001000]
[00000011101101100010]
[11101000110000010010]
[01010100100011011000]
[10000101100010001101]
[00100001110010110001]
[01100000010111100001]
[10000001110101000110]
[00001010011010100011]
[01101000001110100001]
[01000100110000101101]
[00110000001010011110]
[10011011100000000011]
[01011000010111000100]
xerx593
  • 12,237
  • 5
  • 33
  • 64