Zufällige Auswahl mit Gewichtung:
Sei B die Liste der Banner, und P die der dazugehörigen Punkte. B[i] (0<=i<n) ist das i.te Banner und P[i] seine Punktzahl.
Dann liefert folgende Funktion einen Index i (0<=i<n), bei dem die Gewichtung P berücksichtigt wird:
Delphi-Quellcode:
Function WeighedIndex (P : Array Of Integer) : Integer;
Var
I,J,S : Integer;
Begin
S := 0;
For i:= Low (P) to High(P) do // Alle Gewichte summieren
Inc(S,P[i]);
J := Random (S); // Zufallszahl wählen
S := 0;
For i:= Low (P) to High(P) do begin // In welchem Bereich liegt sie
Inc(S, P[i]);
if J < S Then Begin // Abschnitt gefunden und fertig
Result := i;
Exit;
End;
End;
End;
Stell Dir die einzelnen Punkte als verschieden lange Rechtecke vor, die Du übereinanderstapelst. Dann wählst Du mit verbundenen Augen irgendeine Stelle von dem Stapel aus. Das Rechteck, das sich dort befindet, ist dein zufällig ausgewählter Kandidat. Je größer ein Recheck ist, desto größer die Wahrscheinlichkeit, das dieses Rechteck getroffen wird. Umgekehrt werden kleine Rechtecke entsprechend seltener getroffen.
Wenn du aber sichergehen willst, das wirklich alle Banner ausgewählt werden, musst Du eine Liste erstellen und diese zufällig permutieren. Anschließend gehst Du die Liste einfach von vorne nach hinten durch.
Die Liste wird einfach so erstellt, das für jeden Banner B[i] mit der Punktezahl P[i] genau P[i] mal der Index I in die Liste geschrieben wird:
Delphi-Quellcode:
For i:= Low (P) to High(P) do // Alle Gewichte summieren
Inc(S,P[i]);
SetLength (L, S); // L wird unsere Liste
k := 0;
For i:= Low (P) to High(P) do // Liste mit Werten füllen
For j:=0 to P[i]-1 do Begin // Je höher die Punktzahl dest
L[k] := i; // häufiger der Index
inc (k);
End
End;
// Beispiel: Drei Banner (5,3,1).
// Die Liste sieht so aus (0,0,0,0,0,1,1,1,2).
// Diese Liste muss nun noch 'durcheinandergewürfelt' werden, z.B. so:
// Algorithmus nach Fisher-Yates (ja, auch sowas Banales bekommt einen Namen)
Randomize; // reicht 1x beim Programmstart, hier nur zur Erinnerung
For i := 0 to S-1 do begin
J := i + random(S-I);
K := L[j];
L[J] := L[I];
L[I] := K;
end;
Nun ist die Liste durcheinander, z.B. So (0,0,1,2,1,0,0,1,0). Wenn du nun einfach die Banner entsprechend dieser Liste auswählst, wird das Banner #0 garantiert 5x, das Banner #1 3x und das Banner #2 1x ausgewählt, genauso, wie Du es wolltest, mathematisch korrekt und beweisbar. Falls du mit der Bannerauswahl Geld verdienen willst, hätte o.g. Verfahren (vorausgesetzt, es enthält keine Schusselfehler) auch vor Gericht Bestand.
[edit]Erste Version verbessert [/edit]