Random List

Für allgemeine Fragen zur Programmierung mit PureBasic.
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Random List

Beitrag von Nino »

diceman hat geschrieben:Eine Möglichkeit ist es natürlich, die Liste zu randomisieren, und dann einfach mit FirstElement(myList()) das erste Element auszuwählen. Alternativ, wenn du dir ein zufälliges Element aus einer Liste herauspicken möchtest (meine bevorzugte Methode), geht das so:

Code: Alles auswählen

SelectElement(myList(), Random(ListSize(myList())-1))
Es kommt darauf an, was man machen will. Braucht man nur einen zufällig aus der Liste ausgewählten Wert, gehen beide Methoden.

Braucht man allerdings mehrere zufällig aus der Liste ausgewählte Werte, so arbeitet die erste Methode "ohne Zurücklegen" (z.B. Ziehen von Lottokugeln: Liste mit 49 verschiedenen Elementen randomisieren, dann die ersten 6 Elemente auswählen) und die zweite Methode "mit Zurücklegen" (d.h. es ist stets erlaubt dass auch solche Element gezogen werden, die zuvor schon ausgewählt wurden).
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Random List

Beitrag von diceman »

Das ist selbstverständlich. :D
Möglich sind auch hier beide Methoden.
Je nachdem was du damit vorhast, mußt du nach dem auswählen und "abarbeiten" des Elementes (was immer du damit vorhast), dieses natürlich löschen. Ich finde die Methode mit dem zufälligen SelectElement() eleganter, da sie mit einer Zeile auskommt.
Generell empfiehlt sich für solche Zwecke eine temporäre "offene" Liste, in die alle zu verarbeitenden Elemente kopiert werden.
In meinem Roguelike nutze ich dies z.B. für das Verteilen von Items in einem Level: ich setze alle Felder auf eine offene Liste, wähle ein zufälliges aus, platziere dort ein Item, lösche das Feld von der offenen Liste, ziehe ein neues zufälliges Feld, platziere ein Item, etc.
Bei der Methode mit Zurücklegen brauchst du die Liste selbst in Prinzip GAR nicht anzufassen, sondern pickst dir einfach mit Random (ListSize(myList())-1) eine Nummer und suchst dann mit SelectElement() das entsprechende Element heraus, setzt optional einen Zeiger und tust dann damit, was du tun mußt. Oder du machst beides in einer Zeile, wie ich das tue ...
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Random List

Beitrag von Nino »

diceman hat geschrieben:Das ist selbstverständlich. :D
Da ich nicht jede/n kenne, die/der hier mitliest, kann ich nicht sagen ob das für jede/n selbstverständlich ist. :D Daher hielt ich es durchaus für sinnvoll, den prinzipiellen Unterschied der beiden Methoden darzustellen.
diceman hat geschrieben:Möglich sind auch hier beide Methoden..
Je nachdem was du damit vorhast, mußt du nach dem auswählen und "abarbeiten" des Elementes (was immer du damit vorhast), dieses natürlich löschen. Ich finde die Methode mit dem zufälligen SelectElement() eleganter, da sie mit einer Zeile auskommt.
Generell empfiehlt sich für solche Zwecke eine temporäre "offene" Liste, in die alle zu verarbeitenden Elemente kopiert werden.
Um ein ausgewähltes Element später zu löschen und außerdem eine temporäre "offene" Liste anzulegen, braucht es wohl mehr als 1 Zeile.
Sicher ist eine Zufallsauswahl "ohne Zurücklegen" auch mit Deiner Methode irgendwie möglich. Das geht aber nur auf Krampf und ist alles andere als elegant.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Random List

Beitrag von diceman »

Ist echt Geschmackssache, finde ich. :D
Aber schön, daß wir drüber gesprochen haben, ist sicher ein spannendes Thema. :)
Krampfig finde ich übrigens keine der drei Methoden ...
//EDIT:
Wenn es um pure Geschwindigkeit geht, gewinnt natürlich Methode 1, keine Frage - richtig ins Gewicht fällt das aber erst, wenn man das in 10 Mio. Durchläufen simuliert (gerade getestet, ~14 Sekunden für Methode 1). Eindeutiger Verlierer vong speed her ist Methode 2, da jedesmal die Liste neu erstellt werden muß (~70 Sekunden). Methode 3 schlägt mit ~28 Sekunden zu Buche:

Code: Alles auswählen

EnableExplicit
Declare createLotto()
Declare drawNumbers1()
Declare drawNumbers2()
Declare drawNumbers3()



Global NewList lotto()
createLotto()
;drawNumbers1()
;drawNumbers2()
;drawNumbers3()
End





Procedure createLotto()
	Define count
	
	ClearList(lotto())
	For count = 1 To 49
		AddElement(lotto())
		lotto() = count
	Next
EndProcedure



Procedure drawNumbers1()	;Liste randomisieren, kein Löschen von Elementen
	Define count
	
	RandomizeList(lotto())
	ForEach lotto()
		Debug lotto()
		count +1
		If count = 7
			Break
		EndIf
	Next
EndProcedure



Procedure drawNumbers2()	;zufälliges Element wählen, Elemente löschen
	Define count
	
	For count = 1 To 6
		SelectElement(lotto(),Random(ListSize(lotto())-1))
		Debug lotto()
		DeleteElement(lotto())
	Next
EndProcedure



Procedure drawNumbers3()	;temporäre Liste, zufälliges Element wählen, Elemente löschen
	Define count
	NewList lottoTemp()
	CopyList(lotto(),lottoTemp())
	
	For count = 1 To 6
		SelectElement(lottoTemp(),Random(ListSize(lottoTemp())-1))
		Debug lottoTemp()
		DeleteElement(lottoTemp())
	Next
EndProcedure
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Antworten