Seite 1 von 2

Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 07.05.2011 01:24
von Sebastian
Ich benötige eine Zufallzahlenliste, d. h. ich brauche einen Code, bei dem ich Zufallszahlen ermitteln kann, die bei erneutem Aufruf nicht mehr zur Verfügung stehen (also Zufallsauswahl ohne zurücklegen). Der normale random()-Befehl funktioniert demnach nicht mehr. Meine Idee ist folgende, die auch funktioniert:

Code: Alles auswählen

 Dim RandomListArray(Elements-1)
 Dim RandomListArray_Temp(Elements-1)
 Protected NegativeStep
 Protected RandomParameter

 For i = 0 To Elements-1
  RandomListArray_Temp(i) = i
 Next
 
 NegativeStep = Elements		; Wird für das "rückwärtige" Zählen benötigt
 
 For i = 0 To Elements-1
  NegativeStep = NegativeStep - 1
  RandomParameter = Random(NegativeStep)
  RandomListArray(i) = RandomListArray_Temp(RandomParameter)
  For i2 = RandomParameter To NegativeStep
   If i2 < NegativeStep
    RandomListArray_Temp(i2) = RandomListArray_Temp(i2+1)
   EndIf 
  Next
 Next
Gibt es noch eine einfachere Variante, die vielleicht auch schneller ist? Das ständige Kopieren der Arraydaten könnte sich ja vielleicht auf die Performance auswirken...

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 07.05.2011 01:48
von HeX0R
Ich würde das so in der Art angehen:

Code: Alles auswählen

Procedure GetUniqueRandomNumber(InitNumbers = 0)
	Static Dim NUMS.i(0)
	Static MyNum
	Protected i, j, k
	
	If InitNumbers > 1
		;Init Array
		ReDim NUMS(InitNumbers)
		For i = 0 To InitNumbers - 1
			NUMS(i) = i
		Next i
		;Now lets randomize it.
		For i = 1 To InitNumbers * 25
			Repeat
				j = Random(InitNumbers - 1)
				k = Random(InitNumbers - 1)
			Until j <> k
			Swap NUMS(j), NUMS(k)
		Next i
		MyNum = InitNumbers
	Else
		MyNum - 1
		If MyNum >= 0
			ProcedureReturn NUMS(MyNum)
		Else
			;Finished, recall it to reinit
			ProcedureReturn -1
		EndIf
	EndIf
EndProcedure

GetUniqueRandomNumber(10)
For i = 1 To 10
	Debug GetUniqueRandomNumber()
Next i
Debug GetUniqueRandomNumber()

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 07.05.2011 01:53
von STARGÅTE
Ich würde den neuen Befehl RandomizeList() verwenden:

Code: Alles auswählen

NewList Integer()

For n = 1 To 10
	AddElement(Integer()) : Integer() = n
Next

RandomizeList(Integer())

ForEach Integer()
	Debug Integer()
Next
Einfach eine Liste (Urne) mit Zahlen füllen und diese dann durchmischen mit RandomizeList()
Danach einfach nacheinander auslesen ...
Das geht natürlich auch mit einem Array ...

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 07.05.2011 11:02
von Nino
STARGÅTE hat geschrieben:Ich würde den neuen Befehl RandomizeList() verwenden:
Ich auch (oder RandomizeArray()). :-)

Und wenn man eine ältere PureBasic-Version benutzt (z.B. weil PB 4.60 momentan erst im Beta-Stadium ist oder warum auch immer), empfehle ich dafür den(?)/die(?)/das(?) sog. Knuth Shuffle.

Grüße, Nino

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 29.05.2011 11:22
von Sebastian
Oh. Sieh an. In der neuen Purebasic-Version gibt es also endlich einen Befehl dafür? Klasse.

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 29.05.2011 11:31
von Sebastian
Okay. Ich habe mir den Knuth-Shuffle-Algorithmus angesehen. Das ist super! Schade, dass ich nicht selbst auf so eine elegante Lösung gekommen bin! Danke für den Tipp!

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 30.05.2011 12:30
von Zaphod
Ich bin nicht sicher das ich verstehe was du haben möchtest. Eigentlich startet Random() ja bei jedem Programmstart mit einem neuen Seed-wert, wenn du nicht manuell einen Seed vergibst, zumindest ist das bei Version 4.6 beta3 so.

Welche Version benutzt du denn?

Wenn du bei jedem Aufruf von Random einen neuen Seedwert haben willst - und ich verstehe nicht ganz warum du das wollen solltest - dann kannst du das auch deutlich kürzer haben:

Code: Alles auswählen


Procedure.l RandomRandom(max.l)
  RandomSeed(GetTickCount_())
  ProcedureReturn Random(max)
EndProcedure

Das bringt allerdings auch nicht wirklich viel mehr Entropie in deine Zufallszahlen.
Für welchen Zweck möchtest du das denn verwenden?

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 30.05.2011 12:44
von NicTheQuick
@Zaphod:
Du hast ihn falsch verstanden. Auch bei deinem Code kann es vorkommen, dass zwei mal die selbe Zahl nacheinander kommt. Sebastian hingegen möchte eine Liste erstellen, in der jede Zahl nur einmal vorkommt, aber in einer zufälligen Reihenfolge. Also es hat nichts damit zu tun, dass beim Start des Programms immer wieder die selben Zahlen kommen.

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 30.05.2011 12:56
von rolaf
Das liegt bestimmt an den Bananen im Ohr. :wink:

Da ich ja lange Zeit für Lotto programmiert habe und ich auch verschiedene Zahlen brauchte, lößte ich das Problem immer so:

Code: Alles auswählen

;Beispiel für 24 versch. Zahlen aus 49

Dim Zufall(24)

For A = 1 To 24
  Zufall(A) = Random(48) + 1
  For B = 1 To A - 1
    If Zufall(A) = Zufall(B)
      A - 1
      Break
    EndIf
  Next B
Next A

For A = 1 to 24
  Debug Zufall(A)
Next A

Re: Zufallsliste bzw. Zufallszahl "ohne zurücklegen"

Verfasst: 30.05.2011 13:14
von Zaphod
Ah okay, jetzt verstehe ich. Dafür kann ich mir Anwendungsfälle vorstellen. :D