-1

I want to draw 6 different random numbers between 1 to 49 and make sure that they are neither drawn from one single block (cf. the 7 blocks below), nor from 2 blocks and nor from 6 blocks. If 6 random numbers are drawn in such a way, 6 new random numbers should be redrawn. In other words: The 6 random generated numbers should be drawn from 3, 4 or 5 blocks - does not matter which block.

enter image description here

What I have tried is the following:

public class CountColumns {

    public static void main(String[] args) {

        ArrayList<Integer[]> list = new ArrayList<Integer[]>();
        list.add(new Integer[] { 1, 8, 15, 22, 29, 36, 43 });
        list.add(new Integer[] { 2, 9, 16, 23, 30, 37, 44 });
        list.add(new Integer[] { 3, 10, 17, 24, 31, 38, 45 });
        list.add(new Integer[] { 4, 11, 18, 25, 32, 39, 46 });
        list.add(new Integer[] { 5, 12, 19, 26, 33, 40, 47 });
        list.add(new Integer[] { 6, 13, 20, 27, 34, 41, 48 });
        list.add(new Integer[] { 7, 14, 21, 28, 35, 42, 49 });

        //Random 6 numbers -- For testing purposes
        Set<Integer> mySet = new HashSet<Integer>(Arrays.asList(9, 16, 12, 40, 7, 49));

        int countblock1 = 0;
        int countblock2 = 0;
        int countblock3 = 0;
        int countblock4 = 0;
        int countblock5 = 0;
        int countblock6 = 0;
        int countblock7 = 0;

        for (int i = 0; i < list.size(); i++) {
            for (Integer j : mySet) {
                for (int c = 0; c < list.get(i).length; c++) {
                    if (j == list.get(i)[c]) {
                        if (i == 0) {
                            countblock1++;
                        } else if (i == 1) {
                            countblock2++;
                        } else if (i == 2) {
                            countblock3++;
                        } else if (i == 3) {
                            countblock4++;
                        } else if (i == 4) {
                            countblock5++;
                        } else if (i == 5) {
                            countblock6++;
                        } else if (i == 6) {
                            countblock7++;
                        }
                    }
                }
            }
        }

This code helps me to count how many numbers fall within a block. I am well aware, I will need some more sophisticated code - maybe combinatorics or permutation would help but I am not sure though. Can anybody help me out? Many thanks.

Tunc Jamgocyan
  • 321
  • 2
  • 7
  • 18

2 Answers2

2

I suggest a multiple-phase approach:

  1. Generate a random permutation of the blocks (or, equivalently, of the numbers 1 through 7). (See this thread for ways to do that.)
  2. Generate a random integer in the range [3, 5] (inclusive). Use that to pick the leading three blocks (indexes) from the permutation in step 1.
  3. Generate your six random numbers by iteratively picking a number at random from the 3 through 5 blocks, cycling through the blocks as necessary.

The advantage of this approach is that there is no reject cycling. Also, although you are cycling through the blocks sequentially, the sampling is unbiased because of step 1.

EDIT: I take it back about being unbiased. The above step 3 is biased because it spreads out the selection of the blocks evenly. For instance, it would never allow three blocks to be used with frequency (4, 1, 1). This can be fixed by modifying step 3 as follows:

  1. Select a single number at random from each block selected in step 2. (This guarantees that each block is used at least once.) Then select the remaining random numbers by picking a block at random and then an element at random from that block. As you select numbers, remove them from the block (or mark them used, or something) to prevent duplicates.
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
0

Okay, it's doable with my code above was well.

int amountOfZeroBlocks[] = new int[] { countblock1, countblock2, countblock3, countblock4, countblock5,
                countblock6, countblock7 };

        int countZeroBlocks = 0;
        for(int i : amountOfZeroBlocks) {
            if(i == 0) countZeroBlocks++;
        }

Now the only thing is to check how many zero blocks appear (if-clause) and redraw.

Tunc Jamgocyan
  • 321
  • 2
  • 7
  • 18