Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy precedence issue

Tags:

groovy

I'm implementing a weighted lottery in groovy. It allows some participants to have a better chance at winning than others (basically exactly like the NBA draft). It works by tossing each participant into an array N times where N is the number of chances you have to win. It then picks a random index from that array.

Like a good little coder, I wrote a test. It picks a winner from the group 100 times and outputs how many times each participant was picked. The expectation being that it would fall roughly in line with how many times they should be picked (based on their number of chances). The results were...off.

I narrowed the issue down to a single line that, if split into 2 separate statements, works perfectly. A slimmed down version of the routine is below. The "bad" version is active and the "good version" is commented out

def randomInRange(int min, int max) { 
       Random rand = new Random()
       rand.nextInt((max - min) + 1) + min
}

def bob = [name:'bob', timesPicked:0]
def joe = [name:'joe', timesPicked:0]
def don = [name:'don', timesPicked:0]

def chanceWheel = []

//don should get picked a lot more
2.times{chanceWheel << bob}
2.times{chanceWheel << joe}
6.times{chanceWheel << don}

//pick somebody at random from the chance wheel 
100.times{
    //this will produce timesPicked counts that do NOT sum to 100 and usually under-represents don
    chanceWheel[randomInRange(0,9)].timesPicked++

    //splitting the logic into 2 lines will always have the correct sum of timesPicked with roughly the right distribution of winners
    //def picked = chanceWheel[randomInRange(0,9)] 
    //picked.timesPicked++
}

println bob
println joe
println don

My question is what is wrong with the one liner version? My guess is that its an order of execution issue but I cannot for the life of my figure out where its going off the rails.

like image 663
Lance Staples Avatar asked Oct 14 '14 18:10

Lance Staples


People also ask

What is ?: In Groovy?

Yes, the "?:" operator will return the value to the left, if it is not null. Else, return the value to the right. "Yes, the "?:" operator will return the value to the left, if it is not null." - That is incorrect.

Is def mandatory in Groovy?

It's somewhat acceptable in scripts (Groovy scripts and groovysh allow you to do so), but in production code it's one of the biggest evils you can come across which is why you must define a variable with def in all actual groovy code (anything inside a class).

How do you use logical operators in Groovy?

Logical operators Groovy offers three logical operators for boolean expressions: && : logical "and" || : logical "or" ! : logical "not"


1 Answers

chanceWheel[randomInRange(0,9)].timesPicked++ 

is

chanceWheel[randomInRange(0,9)].timesPicked = 
    chanceWheel[randomInRange(0,9)].timesPicked + 1 

which calls randomRange() twice in contrast to the working example where it is called once and assigned to a variable.

like image 148
dmahapatro Avatar answered Nov 05 '22 01:11

dmahapatro