Lottozahlen

valentina2013

Bekanntes Mitglied
Hallo,
habe eine Frage,angenommen ich simmuliere ein Lottospiel- 6 aus 49 und erzeuge Random Zahlen. Es ist doch ziemlich Wahrscheinlich dass eine Zahl in meinen zufälligen Zahlen doppelt vorkommt, was ja ein Fehler wäre. Wie kann man das vermeiden?
 

Mujahiddin

Top Contributor
Nach jeder Zahl prüfen ob diese schon gezogen wurde. Wenn ja dann direkt eine neue generieren.

Das ist grundsätzlich keine so gute Idee. Bei 6 aus 49 wird das kein Problem erzeugen, aber in einem 40 aus 49 würde es zu sehr hohen Wartezeiten führen, bis 40 einzigartige Zahlen gewürfelt werden. Je größer die Zahl der Züge, desto höher die Wartezeit, das wächst exponentiell!!

Besser:
Ein Set oder eine Liste von 49 Zahlen und x-mal (in dem Fall 6) ein zufälliges Element daraus extrahieren.
 

Mujahiddin

Top Contributor
definiere sehr hoch?

Relativ hoch.
Das Programm durchläuft etliche Schritte, in denen es jedes Mal eine
Code:
contains
Abfrage anstößt, und oft Zahlen doppelt und somit umsonst würfelt. Das ist höchst ineffizient, auch wenn es sich auf heutigen PCs kaum bemerkbar macht.

Java:
        List<Integer> list = new ArrayList<>();
        Random r = new Random();
        int k = 49;
        int n = 49;
        int counter = 0;
        while ( list.size() < k ) {
            counter++;
            int i = r.nextInt(n);
            if ( list.contains(i) ) continue;
            list.add(i);
        }
        System.out.println(counter);

Code:
counter
ist in vielen Fällen bis zu 10x so hoch wie
Code:
n
 
Zuletzt bearbeitet:

valentina2013

Bekanntes Mitglied
So, habe mit viel ausprobieren dies hier geschrieben
Java:
public class LottoMein {
	public static void main(String[] args) {
		
		int counter=0;
		boolean liefern;
		int zahl;
		int []treffer={7,12,22,13,40,49};
	    boolean[]gezogeneZahlen=new boolean[50];
	    
	    for(int i=1;i<=49;i++){
	    	gezogeneZahlen[i]=false;
	    }
	    for(int j=0;j<6; j++){
	    	do{
	    		 zahl=(int)(Math.random()*49+1);
	    	}while(gezogeneZahlen[zahl]);
	    	gezogeneZahlen[zahl]=true;
	    }
	    liefern=true;
	    for(int k=0;k<treffer.length;k++){
	    	if(!gezogeneZahlen[treffer[k]])
	    		liefern=false;
	    	counter++;
	    }while(!liefern);
	    
	    for(zahl=1;zahl<=49;zahl++){
	    	if(gezogeneZahlen[zahl])
	    		System.out.print(zahl+" ");
	    	System.out.println();
	    	System.out.println(counter);
	    }

	}
dauert leider nur sehr lange, bin imer noch am warten,ob es so funktioniert hat wie ich es mir gewünscht habe. Möchte die angegebene zahlen in treffer mit zufälligen zahlen vergleichen und dabei zählen wie oft es gespielt werden muss,kan man es nachvolziehen?verbesserungsvorschläge???
 
K

kneitzel

Gast
Also bezüglich der Problematik der möglichen Neuziehung falls die Zahl schon gezogen wurde, gibt es aus meiner Sicht zwei Lösungen (So man die Problematik als n aus m auffasst und nicht als 6 aus 49):

a) Man kann den Algorithmus so abwickeln, wie es eben auch wirklich abläuft. Ich habe ein Array von verfügbaren Zahlen. In dem Beispiel eben 49 Stück. Wenn eine Zahl gezogen wurde, dann muss diese verschwinden und der Pool ist um eins kleiner. Dies ist z.B. mit einem Array lösbar. Am Anfang werden die Felder von 1 bis 49 gefüllt. Wenn eine Zahl gezogen wurde, wird die letzte Zahl im Array an die Stelle der gezogenen Zahl gelegt und dann die Hintere Grenze um eins verringert. Die nächste Zufallszahl ist dann halt nur noch von 1 - 48 weil ja nur noch 48 Zahlen zur Auswahl stehen.

Und wenn Du nur 6 Zahlen ziehen willst, reicht doch ein Array von 6 aus, um dann eben die 6 Zahlen zu speichern. So muss man eben nicht über ein großes Array gehen um alle gezogenen Zahlen zu finden.

b) Wenn man den Algorithmus n aus m wirklich durch überprüfen der bereits gezogenen Zahlen ermitteln möchte, dann ist das auch kein so großes Problem. Bei n aus m prüft man dann on b > m/2 ist. Ist dies der Fall, dann würde ich nicht mehr n Zahlen ermitteln, die gezogen wurden sonden die m-n Zahlen, die nicht gezogen wurden.
So wäre bei 48 aus 49 (nur als Beispiel) nur noch eine Zahl zu ermitteln.

Aber hier entfernt man sich dann von der "Lotto"-Aufgabe und implementiert etwas eigenes. Solch eine Abweichung mag manchmal sinnvoll sein, weil man so ggf. Performance-Probleme verhindert aber diese Notwendigkeit sehe ich hier nicht. Ich würde bei einem Code-Review schlicht fragen, was der Entwickler hier gemacht hat. Die eigentliche Aufgabe war ja erst einmal eine andere (Das Lotto-System ist halt als Aufgabe angegeben worden.)

Mit den besten Grüßen,

Konrad
 

nomuri

Aktives Mitglied
Das ist grundsätzlich keine so gute Idee. Bei 6 aus 49 wird das kein Problem erzeugen, aber in einem 40 aus 49 würde es zu sehr hohen Wartezeiten führen, bis 40 einzigartige Zahlen gewürfelt werden. Je größer die Zahl der Züge, desto höher die Wartezeit, das wächst exponentiell!!

Besser:
Ein Set oder eine Liste von 49 Zahlen und x-mal (in dem Fall 6) ein zufälliges Element daraus extrahieren.


Es steht aber explizit 6 aus 49 in der Aufgabenstellung :bahnhof:
 

nvidia

Bekanntes Mitglied
Hallo,
habe eine Frage,angenommen ich simmuliere ein Lottospiel- 6 aus 49 und erzeuge Random Zahlen. Es ist doch ziemlich Wahrscheinlich dass eine Zahl in meinen zufälligen Zahlen doppelt vorkommt, was ja ein Fehler wäre. Wie kann man das vermeiden?

Java:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;


public class Lotto {
	/**
	 * @param start  
	 * @param end
	 * @return Liste mit natürlichen Zahlen von start (inkl.) bis end (excl.)
	 */
	private static List<Integer> getNaturalNumberList(int start, int end){
		if(start > end){
			throw new IllegalArgumentException();
		}
		List<Integer> list = new ArrayList<>();
		for(int i = start; i < end; i++){
			list.add(Integer.valueOf(i));
		}
		return list;
	}
	
	/**
	 * @return Liste der ersten 6 Zahlen der übergebenen, zufällig umgemischten Liste
	 */
	public static List<Integer> drawLottoNumbers(List<Integer> zahlen){
		Objects.requireNonNull(zahlen);
		if(zahlen.size() < 6){
			throw new IllegalArgumentException();
		}
		
		Collections.shuffle(zahlen);
		return new ArrayList<>(zahlen.subList(0, 6));
	}
	
	public static void main(String ... args){
		System.out.println(drawLottoNumbers(getNaturalNumberList(1, 50)));
	}
}
 
Zuletzt bearbeitet:

Sogomn

Bekanntes Mitglied
Wahlweise könntest du auch einen Vector machen, alle Zahlen 'reinpacken und nach dem Ziehen die gezogene herausnehmen.
 

Ähnliche Java Themen

Neue Themen


Oben