2014-10-14 9 views
8

Ich implementiere eine gewichtete Lotterie in groovy. Es ermöglicht einigen Teilnehmern eine bessere Gewinnchance als andere (im Prinzip genau wie der NBA-Entwurf). Es funktioniert, indem Sie jeden Teilnehmer N-mal in ein Array werfen, wobei N die Anzahl der Chancen ist, die Sie gewinnen müssen. Es wählt dann einen zufälligen Index von diesem Array aus.Groovy Precedence Ausgabe

Wie ein guter kleiner Coder schrieb ich einen Test. Er wählt 100 Mal einen Gewinner aus der Gruppe aus und gibt aus, wie oft jeder Teilnehmer ausgewählt wurde. Die Erwartung ist, dass es ungefähr in Übereinstimmung mit der Anzahl der Male sein würde, die ausgewählt werden sollten (basierend auf ihrer Anzahl von Chancen). Die Ergebnisse waren ... aus.

Ich verringerte das Problem auf eine einzige Zeile, die, wenn in zwei separate Anweisungen aufgeteilt, perfekt funktioniert. Eine abgespeckte Version der Routine ist unten. Die "schlechte" Version ist aktiv und die "gute Version" ist auskommentiert

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 

Meine Frage ist, was ist falsch mit der Einliner-Version? Meine Vermutung ist, dass es eine Reihenfolge der Ausführung Problem ist, aber ich kann nicht für das Leben von mir herausfinden, wo es von den Schienen geht.

+3

chanceWheel [randomInRange (0,9)]. TimesPicked ++ 'ist' chanceWheel [randomInRange (0,9)]. TimesPicked = chanceWheel [randomInRange (0,9)]. TimesPicked + 1', die randomRange zweimal im Gegensatz dazu aufruft zum Arbeitsbeispiel, wo es einmal aufgerufen und einer Variablen zugewiesen wird. ;) – dmahapatro

+0

Ahhh. Im Wesentlichen besteht das Problem darin, dass das TimesPicked eines Teilnehmers nicht inkrementiert wird. Es wird von TimesPicked eines anderen zufälligen Teilnehmers überschrieben (nachdem es inkrementiert wurde). Ich habe das getestet, indem ich die aktuellen Pick-Zähler innerhalb der Schleife abspeicherte und sehe, dass dies das Verhalten ist, das auftritt. Danke sir Sir –

+0

Sie können das 'randomInRange()' auch aus dem '[]' in eine var verschieben, um es "zu reparieren". Dies sieht jedoch eher wie ein Fehler im hier generierten Code aus. Oder ist das Java-Verhalten? – cfrick

Antwort

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

ist

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

die randomRange() zweimal im Gegensatz zu dem Arbeitsbeispiel nennt, wo es einmal und einer Variablen zugewiesen aufgerufen wird.