-2

I'm making three random choices between two classes, A and B. I need to avoid getting B all three times.

Is there a way to stop arc4random() from giving me that result?

jscs
  • 63,694
  • 13
  • 151
  • 195
DwemerTech
  • 11
  • 3
  • 1
    So if you get two nodes of type b, then you should manually make the third node of type a, by bypassing the RNG in that case. – Anya Shenanigans Apr 12 '15 at 17:27
  • 2
    `arc4random` isn't the issue. It doesn't display anything. It just gives a number. You simply need to adjust your logic so you always have at least one "a" node. – rmaddy Apr 12 '15 at 17:37
  • [How to get not twice the same array value in a row?](http://stackoverflow.com/q/13745248) – jscs Apr 12 '15 at 19:28

2 Answers2

3
  • One approach is: If your random routine gives you an unacceptable answer, run it again until it gives you an acceptable answer.

    For example, in a solitaire game app of mine, I shuffle a deck and deal some of it into a layout which must be solvable. But what if it isn't solvable? I repeat that: I shuffle the deck again and deal it again. I keep doing that until the layout I've dealt is solvable. All of that happens before the user sees anything, so the user doesn't know what I've been up to behind the scenes to guarantee that the layout makes sense.

  • In your case, where the possibilities are so limited, another obvious alternative would be this: use a simple combinatorial algorithm to generate beforehand all acceptable combinations of three nodes. Now use arc4random to pick one of those combinations. So, for example:

    var list = [[String]]()
    let possibilities = ["A","B"]
    for x in possibilities {
        for y in possibilities {
            for z in possibilities {
                list.append([x,y,z])
            }
        }
    }
    list.removeLast()
    

    Now list is an array of all possible triples of "A" or "B", but without ["B","B","B"]. So now pick an element at random and for each of its letters, if it is "A", use class A, and if it is "B", use class B. (Of course I suppose we could have done this with actual classes or instances, but it seems simplest to encode it as letters.)

matt
  • 515,959
  • 87
  • 875
  • 1,141
0

BOOLs and loops to the rescue...

BOOL classA = false;
BOOL classB = false;

for (int i=0; i<3; i++) {

    int r = arc4random() % 2;

    if(i < 2) {
        if(r == 0) {
            NSLog(@"Class A");
            classA = true;
        } else {
            NSLog(@"Class B");
            classB = true;
        }
    } else {
        if(classA == false)
            NSLog(@"Class A");
        if(classB == false)
            NSLog(@"Class B");
    }
}

The 2 BOOLs guarantee that each class has at least one member for each 3 cycle run.

sangony
  • 11,636
  • 4
  • 39
  • 55
  • 1
    FYI - Use `YES` and `NO` with `BOOL`, not `true` and `false`. – rmaddy Apr 12 '15 at 23:17
  • @rmaddy - What's the difference in the context above? I've been using true/false for some time without issues. – sangony Apr 12 '15 at 23:52
  • This is a bit pedantic and In the end they probably all mean the same thing but `BOOL` is specific to Objective-C and is meant to only ever have two values: `NO` and `YES`. `true` and `false` are meant to be used with different types. – rmaddy Apr 13 '15 at 01:32
  • 1
    One other thing. Never use `==` with `BOOL`. Just do `if (someBool)` or `if (!someBool)` to test for `YES` and `NO` respectively. – rmaddy Apr 13 '15 at 01:33