Zufallszahlen gegenseitig ausschliessen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Thomebau
Beiträge: 6
Registriert: Fr 24. Sep 2010, 20:32

Zufallszahlen gegenseitig ausschliessen

Beitrag von Thomebau »

Hi,
Ich möchte 5 unterschiedliche Zufallszahlen erzeugen und in einem Array die Variablen dessen Index der zuvor erstellten Zufallszahl von :=false nach :=true ändern.

also ich habe bisher das folgende:

Code: Alles auswählen

procedure TForm1.ScheisselosbuttonClick(Sender: TObject);
var Kuhposition:array  [1..25]of boolean;
var Index:integer;
var Kuh:array [1..5] of integer;
var Index2:integer;
var Index_aus1:integer;
var Index_aus2:integer;
 
begin
for Index :=1 to 25 do
    begin
         Kuhposition [Index]:=false;
    end;
for Index2 :=1 to 5 do
    begin
         Kuh[Index2]:=0;
    end;
     Kuh [1]:=random(25)+1;
     Kuh [2]:=random(25)+1;
     Kuh [3]:=random(25)+1;
     Kuh [4]:=random(25)+1;
     Kuh [5]:=random(25)+1;
 
    //Kuhpositionen gegenseitig ausschliessen
     for Index_aus1:12 to 5 do
        begin
             for Kuh [Index_aus1]:= Kuh[Index_aus2] to
     //Kuh [1] in Kuhposition schreiben
     if Kuh [1]=1 then
        begin
             Kuhposition [1]:=true;
        end;
     if Kuh [1]=2 then
        begin
             Kuhposition [2]:=true;
        end;
        .
        .
        .
        .
     if Kuh [1]=25 then
        begin
             Kuhposition [25]:=true;
        end;
 
     //Kuh [2] in Kuhposition schreiben
     if Kuh [2]=1 then
        begin
             Kuhposition [1]:=true;
        end;
        .
        .
        .
        .
     if Kuh [2]=25 then
        begin
             Kuhposition [25]:=true;
        end;
 
 
    //Kuh [3] in Kuhposition schreiben
     if Kuh [3]=1 then
        begin
             Kuhposition [1]:=true;
        end;
        .
        .
        .
        .
     if Kuh [3]=25 then
        begin
             Kuhposition [25]:=true;
        end;
 
 
     //Kuh [4] in Kuhposition schreiben
     if Kuh [4]=1 then
        begin
             Kuhposition [1]:=true;
        end;
        .
        .
        .
        .
     if Kuh [4]=25 then
        begin
             Kuhposition [25]:=true;
        end;
 
 
     //kuh[5] in Kuhposition schreiben
     if Kuh [5]=1 then
        begin
             Kuhposition [1]:=true;
        end;
        .
        .
        .
        .
     if Kuh [5]=25 then
        begin
             Kuhposition [25]:=true;
        end;
 
 
 
 
//Kühe platzieren
Kuh1.Visible:=Kuhposition[1];
Kuh2.Visible:=Kuhposition[2];
Kuh3.Visible:=Kuhposition[3];
Kuh4.Visible:=Kuhposition[4];
Kuh5.Visible:=Kuhposition[5];
Kuh6.Visible:=Kuhposition[6];
Kuh7.Visible:=Kuhposition[7];
Kuh8.Visible:=Kuhposition[8];
Kuh9.Visible:=Kuhposition[9];
Kuh10.Visible:=Kuhposition[10];
Kuh11.Visible:=Kuhposition[11];
Kuh12.Visible:=Kuhposition[12];
Kuh13.Visible:=Kuhposition[13];
Kuh14.Visible:=Kuhposition[14];
Kuh15.Visible:=Kuhposition[15];
Kuh16.Visible:=Kuhposition[16];
Kuh17.Visible:=Kuhposition[17];
Kuh18.Visible:=Kuhposition[18];
Kuh19.Visible:=Kuhposition[19];
Kuh20.Visible:=Kuhposition[20];
Kuh21.Visible:=Kuhposition[21];
Kuh22.Visible:=Kuhposition[22];
Kuh23.Visible:=Kuhposition[23];
Kuh24.Visible:=Kuhposition[24];
Kuh25.Visible:=Kuhposition[25];
 
Ausgabefenster1.Lines.Add('Die Kühe sitzen auf:'+inttostr(Kuh [1])+'; '+inttostr(Kuh [2])+'; '+inttostr(Kuh [3])+'; '+inttostr(Kuh [4])+'; '+inttostr(Kuh [5]));
 
end;




der Teil
//Kuhpositionen gegenseitig ausschliessen
ist wie ihr seht sehr unvollständig, da ich ab da nicht weiter wusste. Am einfachsten währe es wenn man beim erzeugen der Randomzahl nicht nur Minimum und Maimum setzen könnte, sondern gleich Zahlen ausschliessen könnte. Aber eine solche Funktion ist mir nicht bekannt.

Ich weiss ziemlich viel Programmtest und ich bin mir sicher dass sich dieser ganz einfach reduzieren ließe, aber ich bin im Moment froh dass es jetzt einigermaßen Funktioniert und die 5 Kühe ordentlich über die Wiese verteilt werden.
Bitte nicht übe die namen der Variablen wundern, ich programmiere ein Spiel in dem es darum geht dass Kühe an verschiedenen Positionen auf eine Wiese "koten" und man vorher auf die Position setzen kann. (klingt doof, ist aber ganz lusitg...)

Hoffentlich könnt ihr mir helfen.

Gruß

Thomebau
Zuletzt geändert von Thomebau am Fr 24. Sep 2010, 22:15, insgesamt 1-mal geändert.

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von carli »

Probiers einfach mal etwas kürzer:

Code: Alles auswählen

for i:=1 to 5 do begin
 Kuhposition[Kuh[i]]:=true;
end;
Außerdem weiter hinten wäre folgendes sinnvoller:

Code: Alles auswählen

Kuh1.Visible:=Kuhposition [14];
Änder das mal, damit dein Code auf unter 80 Zeilen schrumpft, dann reden wir weiter.

Thomebau
Beiträge: 6
Registriert: Fr 24. Sep 2010, 20:32

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von Thomebau »

was ist "i" ?
Einfach ein Platzhalter oder hat das eine bestimmte Bedeutung ?


EDIT:
Das mit dem

Code: Alles auswählen

KuhX.Visible:=Kuhposition[x];
Kuhx+1.Visible:=Kuhposition[x+1];
Hab ich jetzt umgesetzt, war eigentlich auch in meinem Konzept so vorgesehen deshalb hatte ich ja das Boolean Array gemacht. Keine Ahnung wiso ich es dann doch anders hatte...

Das spart auf jeden Fall schonmal einiges an Zeilen.


Nur bei deinem ersten Änderungsvorschlag bin ich mir nicht ganz klar wie das funktioniert und vor allem wo (und wie) ich das einsetzen soll, ich übernehme nur sehr ungerne Sachen die ich nicht verstehe.


EDIT2:
Ich hab der Übersichtlichkeit halber mal den ersten Post ein wenig eingekürzt, hätte ich besser mal von Anfang an gemacht.

u-boot
Beiträge: 308
Registriert: Do 9. Apr 2009, 10:10
OS, Lazarus, FPC: Ubuntu 9.10 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 785..

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von u-boot »

Für 5 aus 25 kann man getrost ne Zufallszahl "ziehen" lassen und überprüfen ob die Position schon vergeben ist. Falls die Position schon vergeben ist einfach nochmal "ziehen" lassen. So wäre der Algorithmus wohl in Worten beschrieben ... als Übung darfst es auch selber umsetzen (für 4.999.998 mal ziehen aus 5.000.000 gings wohl anders besser).

Weiterhin ist dieses Ding (immer noch) elend lang zum durchlesen. Verwende bitte Variablen als Arrayindex.

noch als Anregung:

Code: Alles auswählen

for i:=1 to 25 do  begin
   TControl(Findcomponent('Kuh' +  inttostr(i))).Visible := Kuhposition[i];
end;
Ubuntu 9.10 (L 0.9.28 FPC 2.4.x)

felix96
Beiträge: 287
Registriert: So 29. Nov 2009, 17:44
CPU-Target: 32BitWin+64bitUbunt

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von felix96 »

Thomebau hat geschrieben:was ist "i" ?
Einfach ein Platzhalter oder hat das eine bestimmte Bedeutung ?
Bei einer For-Schleife, gibt es immer eine Variable, welche um 1 erhöht wird (oder auch -1).
Man könnte diese Variable auch Hans nennen: - ), aber meistens nimmt man i,j,k,l usw.
so was nutzt man, wenn man z.B. in ein Array zahlen werte ein speichern will:

Code: Alles auswählen

var mein_array: array[1..7] of byte;
                    Hans: byte;
Begin
randomize;
for Hans:=1 to 7 do
     mein_array[Hans]:=random(49)+1;
Lotto-Zahlen-Generator^^ :P
Danke schonmal für eure Antworten
it´s not a bug, it´s a feature!

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von Scotty »

Kombinatorik ist keine Sache, die man mal nebenbei machen kann. Bei einem Lotto-Zahlen-Generator darf eine Zahl nicht 2x vorkommen (Kombination ohne Zurücklegen). Man macht so etwas am besten, indem eine Liste aller Elemente erstellt wird, aus der dann zufällig Einträge in eine zweite Liste verschoben und aus der Gesamtmenge gelöscht werden.

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von Hitman »

Scotty hat geschrieben:Kombinatorik ist keine Sache, die man mal nebenbei machen kann. Bei einem Lotto-Zahlen-Generator darf eine Zahl nicht 2x vorkommen (Kombination ohne Zurücklegen). Man macht so etwas am besten, indem eine Liste aller Elemente erstellt wird, aus der dann zufällig Einträge in eine zweite Liste verschoben und aus der Gesamtmenge gelöscht werden.
Im Prinzip richtig, aber wie u-boot schon sagte, ist es bei dieser kleinen Menge von Zahlen vertretbar, trial & error zu verwenden.

Thomebau
Beiträge: 6
Registriert: Fr 24. Sep 2010, 20:32

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von Thomebau »

also ich werde es dann mal so probieren:
ich schreibe einen Zufallswert ins Array.
ich erstelle die zweite Zufallszahl und schaue nach ob diese schon an der Position 1 vorkommt.
ja-> neue Zahl + überprüfen nein-> an Position 2 schreiben
ich erstelle eine neue Zufallszahl und schaue nach ob diese an Position 1 oder 2 schon vorkommt.
ja-> neue zahl + überprüfen nein-> an Position 3 schreiben
ich erstelle eine neue Zufallszahl und schaue nach ob diese an Position 1 oder 2 oder 3 schon vorkommt.
ja-> neue Zahl + überprüfen nein-> an Position 4 schreiben
ich erstelle eine neue Zufallszahl und schaue nach ob diese an Position 1 oder 2 oder 3 oder 4 schon vorkommt.
ja-> neue Zahl + überpdüfen nein-> an Position 5 schreiben


muss ich das so umsetzen oder geht das kompakter ?

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von theo »

Thomebau hat geschrieben: muss ich das so umsetzen oder geht das kompakter ?
Die Idee ist schon richtig imho, aber programmieren solltest du es mit Schleifen und Laufvariablen.
Merke: Ein richtiger Programmierer ist faul, der schreibt nicht hundertmal (fast) das gleiche, sondern macht Funktionen, Schleifen etc.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von mschnell »

Ich vermute Du willst zufällige Positionen berechnen.

Das würde ich anders anfangen:

Definiere einen Typ record i: integer; z: real

Erstelle ein Array von diesen Elementen und schreibe in den "z"-Teil jedes Elements eine Zufallszahl (zwischen 0 und 1) und in den "i" Teil den Index.

Sortiere das Array mit Hilfe von QuickSort aus der RTL.

Nun bilden die "i"-Teile eine zufällige Reihenfolge der entsprechenden Zahlen.

So ist das Ganze nur wenige eigene Sourcecode-Zeilen lang. und vermutlich optimal schnell, da QuickSort eine gut optimierte Methode ist.

-Michael

u-boot
Beiträge: 308
Registriert: Do 9. Apr 2009, 10:10
OS, Lazarus, FPC: Ubuntu 9.10 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 785..

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von u-boot »

hm mschnell wenn ich deinen Algorithmus richtig nachvollziehe ist deine Beschreibung eine zufällige Anordnung von fünf zahlen nicht aber ein Ziehen ohne Zurücklegen von 5 aus 25.
Ubuntu 9.10 (L 0.9.28 FPC 2.4.x)

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von mschnell »

u-boot hat geschrieben:hm mschnell wenn ich deinen Algorithmus richtig nachvollziehe ist deine Beschreibung eine zufällige Anordnung von fünf zahlen nicht aber ein Ziehen ohne Zurücklegen von 5 aus 25.
Stimmt. so hatte ich die Aufgabe (möglicherweise falsch) verstanden.

-Michael

Korkenkrone
Beiträge: 33
Registriert: Sa 18. Sep 2010, 20:33
OS, Lazarus, FPC: OpenSUSE 11.3 (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: x86-64

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von Korkenkrone »

Sortieren ist trotzdem keine schlechte Idee. Nehmen wir mal x Kühe auf n möglichen Positionen. Du fügst die Kühe jetzt eine nach der anderen in eine Liste ein. Dazu ziehst du eine Zufallszahl von 1 bis n - x. Bei der ersten Kuh (x = 0) also 1..n, bei der zweiten Kuh (x = 1) 1..n-1 und so weiter. Jetzt iterierst du solange über die (nach Position sortierte) Liste, bis deine Zufallszahl größer ist als die Position der derzeitigen Kuh. Jedesmal, wenn sie kleiner oder gleich ist, addierst du eins drauf. Danach hast du die neue Position für die Kuh.

Der Sinn dahinter: Mit jeder platzierten Kuh sinkt die Anzahl der verfügbaren Plätze um eins. Du ziehst aus der Anzahl der noch verfügbaren Plätze und berechnest dann, wieviele Kühe bereits vor oder auf dieser Position stehen.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Zufallszahlen gegenseitig ausschliessen

Beitrag von mschnell »

5 aus 25 ohne zurücklegen:

Entsprechend meinem ersten Vorschlag 25 Elemente Ziehen und Sortieren.

Die ersten 5 sind's dann.

-Michael

Antworten