# How to script a Non Repeating Random Round Robin ?



## jfino (Jan 1, 2018)

Hi Everyone!
Happy new year to you all.

I need some help scripting a non-repeating random round robin.
How is this achieved? 

An example or Pseudo code would be very helpful since I'm new to programming. 

Thanks so much for your help. 
Jimmy


----------



## d.healey (Jan 1, 2018)

If it's non-repeating then it aint random  but I know what you mean.

So you need a variable to keep a record of the last RR and then a loop to generate a new RR and compare it against the last one.

Some rough code below, a mix of KSP and pseudo because I'm tired .

```
on init
    declare lastRR = 0
    declare RR = 0
end on

on note
    while RR = lastRR
        RR = random(0, max_rrs)
    end for
    lastRR = RR
end on
```


----------



## magneto538 (Jan 2, 2018)

d.healey said:


> If it's non-repeating then it aint random  but I know what you mean.
> 
> So you need a variable to keep a record of the last RR and then a loop to generate a new RR and compare it against the last one.
> 
> ...



The problem with this is: if you don't have a lot of round robins, the while loop might (potentially) be executed a ridiculous amount of times, so there should be a control over the amount of times the loop is executed.


----------



## d.healey (Jan 2, 2018)

magneto538 said:


> if you don't have a lot of round robins, the while loop might (potentially) be executed a ridiculous amount of times, so there should be a control over the amount of times the loop is executed.


This shouldn't be an issue unless you have hundreds of RRs. Another way to do it which might be more efficient is to have all the potential RRs in an array, randomise the array once and play through the RRs, once all RRs have been played you can randomise the array again (checking that the last played RR isn't played again of course).


----------



## magneto538 (Jan 2, 2018)

d.healey said:


> This shouldn't be an issue unless you have hundreds of RRs.



Actually, you have a much higher rate of getting the same number generated twice in a row with less Round Robins. If you have 2 RRs, there is a 50% chance (theoretically) to get the same number that was generated in the previous call to the random() function, thus the while loop might perform more cycles. On the other hand, with a large number of RRs there is a lower chance of getting the same number, so paradoxically the whole process is lighter on the CPU. 



d.healey said:


> Another way to do it which might be more efficient is to have all the potential RRs in an array, randomise the array once and play through the RRs, once all RRs have been played you can randomise the array again (checking that the last played RR isn't played again of course).


I would definitely go this way. You might also generate a really long random sequence and when the selected index is the last one, just start over - if it's long enough, I'm pretty sure no one will notice that the sequence is repeating. Otherwise, you can generate a non-repeating sequence which has the same length of the total number of RRs and generate a new sequence once the current one has been played entirely as you said. To generate the non-repeating random sequence, you might also use search() inside the while loop to ensure that the generated number hasn't been used yet.


----------



## EvilDragon (Jan 2, 2018)

This is also a pretty good variant, without using any loops at all:

https://www.orangetreesamples.com/blog/scripting-non-repeating-round-robin


----------



## magneto538 (Jan 2, 2018)

EvilDragon said:


> This is also a pretty good variant, without using any loops at all:
> 
> https://www.orangetreesamples.com/blog/scripting-non-repeating-round-robin



That's really nice! Now that I think about it, I have used something vaguely similar (but much simpler as I didn't need that kind of precision) in an older project. There is a bit of +1/-1 to take care of according to the format you need the output to be (either zero or 1-based) but this one is probably the best solution I've seen.


----------



## EvilDragon (Jan 2, 2018)

Yes, it really is.

Also, I'm not sure if that polyphonic variable there is really necessary (you only have one array of 128 indices to remember the last played RR, so why would you need a polyvar, I see no point. Might've even been a typo). I've had identical results with a regular variable instead.


----------



## magneto538 (Jan 2, 2018)

I guess the only case where it might be needed is if a new NCB is executed exactly when the current NCB is between the two lines in the if ($total_round_robin > 1) statement - which is a really unlikely event. Really unlikely. Close to impossible I would say.


----------



## d.healey (Jan 2, 2018)

magneto538 said:


> Actually, you have a much higher rate of getting the same number generated twice in a row with less Round Robins. If you have 2 RRs, there is a 50% chance (theoretically) to get the same number that was generated in the previous call to the random() function, thus the while loop might perform more cycles. On the other hand, with a large number of RRs there is a lower chance of getting the same number, so paradoxically the whole process is lighter on the CPU.


Ah yeah I see what you mean.

That orange tree example reminds me of another way I've done it. Generate a random RR, then check if it's the same as the last RR, if it is then just increase it by one % the max RRs.


----------



## EvilDragon (Jan 2, 2018)

magneto538 said:


> I guess the only case where it might be needed is if a new NCB is executed exactly when the current NCB is between the two lines in the if ($total_round_robin > 1) statement - which is a really unlikely event. Really unlikely. Close to impossible I would say.



It's completely unlikely, actually, if there are no waits in NCB all note callbacks are executed sequentially!


----------



## Mike Greene (Jan 2, 2018)

Greg's way is definitely slick. I tried to do something similar once myself, but my version was a complicated mess.  My hat's off once again.

I sometimes wonder whether "randomness" is really the best objective, though. A truly random series (even one which disallows repeating a sample twice in a row) might have a repetitive string of A,B,A,B,A,B in it, which I don't want, so I've been writing my own sequences of what I _wish_ a randomizer would generate.

Here's an example with three samples. Rather than random, I'll specify that this is the order: A,B,C,A,C,B,A,C,B,A,C. This way I'm sure to always get a nice mix of all three samples, and since it's an 11 element sequence, when it repeats, the pattern is unlikely to ever be noticed.


----------



## jfino (Jan 2, 2018)

great info! never thought of just making a long array with loads of permutations that don't repeat.


----------

