Thema: Delphi Ordung muss sein

Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 

Re: Ordung muss sein

  Alt 3. Okt 2003, 00:55
Ich weiß ja nicht ob der Lehrer für die bisherigen Lösungen gute Noten vergibt.

Es soll 6 aus 49 programmiert werden, richtig ? Nun wenn ich die Ziehung von 6 aus 49 mal genauer betrachte so sind am Anfang 49 Kugeln in der Urne. Dann wird eine Zahl gezogen und schupps da waren es nur noch 48. Das geht so weiter bis 6 Kugeln aus der Urne rausgenommen wurden und somit nur noch 43 in der Urne sind.

Die bisherigen Lösungsvorschläge ziehen per Random(49) +1 aber immer eine Kugel aus 49 möglichen. Wird eine Kugel gezogen die schon aus der Urne genommen wurde, was ja eigentlich gar nicht möglich sein dürfte, schmeisst der Ziehungsleiter im Fernsehen sie dann ganz still und leise zurück in die Urne ??

Setzen, 5, Thema verfehlt

D.h. bei 6 aus 49 sind die Wahrscheinlichkeiten für eine Zahl jeweils

1. Zug = 1/49
2. Zug = 1/48
3. Zug = 1/47
4. Zug = 1/46
5. Zug = 1/45
6. Zug = 1/44


Delphi-Quellcode:
type
  TZahlen = array of Integer;

procedure Lotto(var Sortiert,Gezogene: TZahlen; Ziehungen: Integer = 6; Elemente: Integer = 49);
var
  I,J,K,N: Integer;
begin
  Sortiert := nil; // stellt sicher das Sortiert <> Gezogene ist
  Gezogene := nil;

  if Ziehungen > Elemente then
    raise Exception.Create('Man kann nicht mehr Kugeln ziehen als in der Urne sind');

  SetLength(Sortiert, Ziehungen);
  SetLength(Gezogene, Ziehungen);

  for I := 0 to Ziehungen -1 do
  begin
    K := 0;
    N := Random(Elemente - I) + 1;
    for J := 0 to I -1 do
      if N >= Sortiert[J] then
      begin
        Inc(N);
        Inc(K);
      end else Break;
    for J := I downto K +1 do
      Sortiert[J] := Sortiert[J -1];
    Sortiert[K] := N;
    Gezogene[I] := N;
  end;
end;

procedure Test;

  procedure Print(const Title: String; const Zahlen: TZahlen);
  var
    I: Integer;
  begin
    Write(Title);
    for I := 0 to High(Zahlen) do Write(Zahlen[I]:4);
    WriteLn;
  end;

var
  Sortiert,Gezogene: TZahlen;
begin
  Lotto(Sortiert, Gezogene, 6, 49);

  Print('gezogene : ', Gezogene);
  Print('sortiert : ', Sortiert);
  WriteLn;
end;
Um obigen Source etwas zu erklären:
Man zieht bei 6 aus 49 jeweils aus 49,48,47,46,45,44 Zahlen eine per Random. Um die Sache schön Speichereffizient zu machen verzichten wir auf ein Array[0..48] of Boolean o.ä. Techniken und nutzen eine "Lücken-Sprung" Technik. Wir korregieren also die gezogene Zahl jeweils so das sie die schon gezogenen Zahlen mit berücksichtigt, denn eine einmal gezogene Zahl darf nicht zweimal gezogen werden.

Beispiel 5 aus 5:
1. Zug = 3 aus 5, das 3. Element aus 1,2,3,4,5 ist 3, effektive Zahl = 3, es bleiben 1,2,4,5
2. Zug = 1 aus 4, das 1. Element aus 1,2,4,5 ist 1, effektive Zahl = 1, es bleiben 2,4,5
3. Zug = 2 aus 3, das 2. Element aus 2,4,5 ist 4, effektive Zahl = 4, es bleiben 2,5
4. Zug = 1 aus 2, das 1. Element aus 2,5 ist 2, effektive Zahl = 2
5. Zug = 1 aus 1, das 1. Element aus 5 ist 5, effektive Zahl = 5

Somit haben wir 3,1,4,2,5 gezogen.

Exakt so geht obiger Algorithmus vor. Er benötigt dazu eine sortierte Liste aller bisher gezogenen Zahlen und muß N nur noch so korrigieren das es die in der Urne verbleibenden Zahlen berücksichtigt.

Somit simuliert obiger Algorithmus exakt die Realitäten und Wahscheinlichkeiten beim Lotto.
Alle anderen bisherigen Vorschläge verfälschen die Wahrscheinlichkeiten, denn wenn z.B. im 3. Zug die 5 aus 49 Kugeln gezogen wurde und die 5 schon vorher gezogen wurde dann ist die effektive Wahrscheinlichkeit 1/49 + 1/49 = 2/49 für jede Zahl gewesen. Es müsste aber exakt 1/47 sein.


Gruß Hagen

PS: falls du eine Eins bekommst schuldest du uns aber was
PPS: Übrigens, exakt diese Aufgabe habe ich immer meinen Informatik-Lehrlingen gestellt !
  Mit Zitat antworten Zitat