Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#8

Re: Banner per "Zufall" auswählen

  Alt 26. Okt 2005, 06:55
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]
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat