2

This one is very simple and basic, but for some reason I cant get it right. So I'm making a for loop and inside the for loop generating random numbers, but I want to eliminate some numbers by redoing the for loop when those numbers come up. how should I do it and whats my mistake. Thank you in advance.

How I did it:

int[] array= new int[6];
for(int i=0;i<array.length;i++){
   Random rand = new Random();
   int  n = rand.nextInt(50) + 1;
   if(n==5 || n==9 || n==13){
      i--;
      return;
   }
   array[i]=n;
}

6 Answers6

3

I think the cleanest way would be to have an inner loop that loops until you get an acceptable number. That way the inner loop could be later factored into a function if necessary. I also moved the random number generator initialization out of the loop, since I assume that's what was intended.

Random rand = new Random();
for (int i = 0; i < array.length; ++i) {
  int n = rand.nextInt(50) + 1;
  while (n == 5 || n == 9 || n == 13) {
    n = rand.nextInt(50) + 1;
  }
  array[i] = n;
}
Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
Antimony
  • 37,781
  • 10
  • 100
  • 107
  • 1
    I don't think so. What if (**extremely unlike, but *possible***) you are always hitting the 5, or 9, or 13? – zlakad Feb 15 '18 at 01:25
  • 1
    @zlakad Then you should invest in lottery tickets. At any rate, `java.util.Random` is a PRNG, so it will never get stuck. – Antimony Feb 15 '18 at 01:26
  • 1
    Yep, but I think it can be avoided in this case. E.g. make a Collection with all Integers except 5, 9, 13. Call `Collections.shuffle()`, and take the first `array.lenght` elements – zlakad Feb 15 '18 at 01:30
  • It is a matter of efficiency... Suppose that you have to chose some set of randoms in the way these are set of very narrow sub-set of the other set of randoms? – zlakad Feb 15 '18 at 01:42
  • 1
    I agree with @zlakad's point here, and is the main reason why I included my answer. If essentially OP doesn't want to pick: 5, 9, or 13 from their choices of random numbers then there isn't a reason to include those numbers as choices in the first place. – Spencer Wieczorek Feb 15 '18 at 02:03
3

This is an interesting post. Just want to chime in and share what my first instinct is. Perhaps it is not conventional.

There is no reason to roll again if you hit upon 5, 9, 13. The approach can be deterministic

Algorithm:

  1. Choose a number R between 1-47 (the numbers 1-4, 6-8, 10-12, 14-50 are all equally probable)
  2. If R == 5 then R = 48
  3. else if R == 9 then R = 49
  4. else if R == 13 then R = 50

This can easily be made into a function where you pass a set of unwanted numbers.

Ian Mc
  • 5,656
  • 4
  • 18
  • 25
  • Interesting answer – Scary Wombat Feb 15 '18 at 02:11
  • technically that's completely random, but because I'm using this for a school project I thought my teacher might say 'It's not random enough'. But thank you anyways. – amirsoltani Feb 16 '18 at 17:26
  • It would be a shame if a teacher would argue against this approach. This answer calculates the variable with equal probability, and the most efficiency. But I understand. Good luck in your studies, and hopefully you learned something by this exercise. – Ian Mc Feb 16 '18 at 17:31
  • makes no sense to me – ACV Feb 16 '18 at 23:09
  • I'd be happy to explain if you provide a bit of insight to what doesn't make sense. – Ian Mc Feb 16 '18 at 23:11
1

Looks like you could use a while-loop:

int[] array= new int[6];
int i = 0;
while(i<array.length){
   Random rand = new Random();
   int  n = rand.nextInt(50) + 1;
   if(n!=5 && n!=9 && n!=13){
       array[i++] = n;  
   }
}
Indominus
  • 1,228
  • 15
  • 31
1

On thing you could do is generate a list of numbers from [1, .., 50] and remove the numbers you don't want from that list: [5, 9, 13]. Like so:

List<Integer> unwatedNums = Arrays.asList(5, 9, 13);
List<Integer> list = IntStream.rangeClosed(1, 50).boxed().collect(Collectors.toList());
list.removeAll(unwatedNums);

Now instead you can safely grab a random element from that list without having it to unnecessarily get a new random number in some cases:

int[] array= new int[6];
for(int i=0;i<array.length;i++){
    array[i]=list.get((new Random()).nextInt(list.size()));
}
Spencer Wieczorek
  • 21,229
  • 7
  • 44
  • 54
  • @Antimony I'm not sure what you mean by: *"random numbers without replacement"* in your first comment. What's the issue with this method exactly? – Spencer Wieczorek Feb 15 '18 at 01:33
  • You could also do a `Collections.shuffle()` on list and then just take the first six elements – Scary Wombat Feb 15 '18 at 01:40
  • @ScaryWombat That would limit it to be a set of uniquely picked numbers, where I see no reason in OP's code that a repeated random number is considered invalid. – Spencer Wieczorek Feb 15 '18 at 01:44
0

The cleanest way is to make sure you don't generate the numbers you don't want - you can adjust your range depending on how many numbers you want to exclude.

This function will give you a random number for lowRange to highRange (both ends included), without any of the numbers specified in without:

public static int randomWithout(Random rand, int lowRange, int highRange, int... without) {
    int range = highRange - lowRange + 1 - without.length;
    int result = rand.nextInt(range) + lowRange;
    for (int i = 0; i < without.length; i++) {
        if (result >= without[i]) {
            result++;
        }
    }
    return result;
}

You can then use this function like this:

int[] array = new int[6];
Random rand = new Random();
for (int i = 0; i < array.length; ++i) {
    array[i] = randomWithout(rand, 1, 50, 5, 9, 13);
}

The big advantage is deterministic running time - using a while loop while you get a number that you don't want could theoretically run forever.

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
0

The answers were great and if you are having the same problem as me I suggest you to look through the answers regardless, but the answer that I was looking for is following:

int[] array= new int[6];
for(int i=0;i<array.length;i++){
   Random rand = new Random();
   int  n = rand.nextInt(50) + 1;
   if(n==5 || n==9 || n==13){
      i--;
      continue; // this has solved my problem
   }
 array[i]=n;
}