# Lotto Programm



## Magahretzius (23. Nov 2012)

Guten Tag, ich soll ein Programm erstellen das zufällig 6 Zahlen ausgibt diese speichert, ordnet und es darf keine doppelte Zahlen geben.
Das ist mein ansatz bis jetzt.
Wo habe ich fehler? =)




```
public class lotto {
	public static void main(String[] args) {
		
		int i;
		int zaehler;
		
		
		int [] feld = new int[6];
				
				
		feld[0] = (int) (Math.random()*49)+1;
		
		for(zaehler=0;zaehler<6;zaehler++)
			
			feld[zaehler] = (int) (Math.random()*49)+1; 
		
		for(i=0;i<zaehler;i++){
			
			while(feld[zaehler]==feld[i]){
				feld[zaehler] = (int) (Math.random()*49)+1;
				
				i=0;
			}
		

				for(i=0;i<6;i++){
				System.out.print(feld[i]+" ");
	        
	
	
   }
  }
 }
}
```


----------



## SlaterB (23. Nov 2012)

fragst du nur auf Verdacht nach Fehler oder hast du selber Unstimmigkeiten bemerkt?

sinnvoll wäre in jedem Fall, Ordnung in Klammern + Einrückung zu bringen,
hier mal nicht von mir, wäre ja irre, sondern von Eclipse gestiftet:


```
public class lotto
{
    public static void main(String[] args)
    {

        int i;
        int zaehler;


        int[] feld = new int[6];


        feld[0] = (int)(Math.random() * 49) + 1;

        for (zaehler = 0; zaehler < 6; zaehler++)

            feld[zaehler] = (int)(Math.random() * 49) + 1;

        for (i = 0; i < zaehler; i++)
        {

            while (feld[zaehler] == feld[i])
            {
                feld[zaehler] = (int)(Math.random() * 49) + 1;

                i = 0;
            }


            for (i = 0; i < 6; i++)
            {
                System.out.print(feld[i] + " ");


            }
        }
    }
}
```
ob die Ausgabe-Schleife in einer anderen Schleife stehen sollte?..
andererseits immer gut, Zwischenstände der Berechnung und nicht nur das Endergebnis anzuschauen


----------



## Magahretzius1 (23. Nov 2012)

Ecplise sagt mir folgendes.


Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
	at lotto.main(lotto.java:20)


----------



## SlaterB (23. Nov 2012)

in der Tat, dann mag ich mal noch paar anders gesetzte Klammern vorschlagen:

```
public static void main(String[] args)
    {
        int i;
        int zaehler;


        int[] feld = new int[6];


        feld[0] = (int)(Math.random() * 49) + 1;

        for (zaehler = 0; zaehler < 6; zaehler++)
        {

            feld[zaehler] = (int)(Math.random() * 49) + 1;

            for (i = 0; i < zaehler; i++)
            {

                while (feld[zaehler] == feld[i])
                {
                    feld[zaehler] = (int)(Math.random() * 49) + 1;

                    i = 0;
                }
            }


        }

        for (i = 0; i < 6; i++)
        {
            System.out.print(feld[i] + " ");
        }
    }
```

schau dir an was wie oft zu wiederholen ist, 
zuvor wurde zaehler von der ersten Schleife auf 6 hochgezählt und danach überall verwendet,
aber Index 6 ist ja nicht gut


----------



## Magahretzius1.1 (23. Nov 2012)

Oh okay danke,
jetzt bleibt noch die frage wie ordne ich die Ausgabe?


----------



## SlaterB (23. Nov 2012)

in meiner Version werden nur noch 6 Zahlen am Ende ausgegeben, das scheint mir ordentlich genug,
oder willst du sie der Größe nach sortieren? 

da reicht wohl der Verweis auf Suchmaschinen 'java array sortieren'
bzw. besser gleich entsprechende Lehrbuchkapitel


----------



## Magahretzius1.2 (23. Nov 2012)

Danke für die Hilfe bis jetzt .
Habe jetzt noch geschafft das 10 Tippscheine ausgestellt werden aber das mit dem Sortieren will ich nicht hinkriegen

```
public class test
{
public static void main(String[] args)
    {
        int i;
        int x;
        int zaehler;
        int zaehler2;
        
        int[][] feld = new int[6][10]; {
 
        //feld[0] = (int)(Math.random() * 49) + 1;
 
        for(zaehler2 = 0; zaehler2 < 10;zaehler2++)
        {
        	for (zaehler = 0; zaehler < 6; zaehler++)
        	{
 
            	feld[zaehler][zaehler2] = (int)(Math.random() * 49) + 1;
 
            	for (i = 0; i < zaehler; i++)
            	{
 
                	while (feld[zaehler] == feld[i])
                	{
                    	feld[zaehler][zaehler2] = (int)(Math.random() * 49) + 1;
 
                    	i = 0;
                	}
            	}
 
        	}							//
        }
        for(x = 0; x < 10;x++)
        {
        	for (i = 0; i < 6; i++)
        	{
        		
        		System.out.print(feld[i][x] + " ");
        	}
        	System.out.print("\n");
        }
    }
}
}
```


----------



## Magahretzius1.3 (23. Nov 2012)

so weit bin ich jetzt 
Ausgabe :
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 49
	at java.util.ComparableTimSort.rangeCheck(Unknown Source)
	at java.util.ComparableTimSort.sort(Unknown Source)
	at java.util.Arrays.sort(Unknown Source)
	at lotto.main(lotto.java:40)


```
import java.util.Arrays;

public class lotto
{
public static void main(String[] args)
    {
        int i;
        int x;
        int zaehler;
        int zaehler2;
        
        int[][] feld = new int[6][10]; {
 
        //feld[0] = (int)(Math.random() * 49) + 1;
 
        for(zaehler2 = 0; zaehler2 < 10;zaehler2++)
        {
        	for (zaehler = 0; zaehler < 6; zaehler++)
        	{
 
            	feld[zaehler][zaehler2] = (int)(Math.random() * 49) + 1;
 
            	for (i = 0; i < zaehler; i++)
            	{
 
                	while (feld[zaehler] == feld[i])
                	{
                    	feld[zaehler][zaehler2] = (int)(Math.random() * 49) + 1;
 
                    	i = 0;
                	}
            	}
 
        	}
        }
        for(x = 0; x < 10;x++)
        {
        	for (i = 0; i < 6; i++)
        	{
        		Arrays.sort (feld, 1, 49);
        		System.out.print(feld[i][x] + " ");
        		System.out.print(feld[i][x] + " ");
        	}
        	System.out.print("\n");
        }
    }
}
}
```


----------



## hüteüberhüte (23. Nov 2012)

Hat gerade neulich jemand nach gefragt:

```
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
 
/**
 * @author hütte
 */
public class LottoZiehung {
    
    private static final Random random = new Random();
    private final int[] ziehung;
    
    public LottoZiehung(int[] ziehung) {
        if (ziehung == null || ziehung.length != 6) {
            throw new IllegalArgumentException(Arrays.toString(ziehung));
        }
        Arrays.sort(ziehung);
        if (ziehung[0] < 1 || ziehung[5] > 49) {
            throw new IllegalArgumentException(Arrays.toString(ziehung));
        }
        for (int i = 0; i < ziehung.length - 1; i++) {
            if (ziehung[i] == ziehung[i + 1]) {
                throw new IllegalArgumentException(Arrays.toString(ziehung));
            }
        }
        this.ziehung = ziehung; // <- Kopie wäre besser
    }
    
    public LottoZiehung() {
        ziehung = generiereZiehung();
    }
    
    private int[] generiereZiehung() {
        int[] ia = new int[6];
        a:
        for (int i = 0; i < ia.length;) {
            int r = random.nextInt(49) + 1;
            for (int j = 0; j < i; j++) {
                if (ia[j] == r) {
                    continue a;
                }
            }
            ia[i++] = r;
        }
        Arrays.sort(ia);
        return ia;
    }
    
    public int[] getZiehung() {
        int[] ia = new int[ziehung.length];
        System.arraycopy(ziehung, 0, ia, 0, ziehung.length);
        return ia;
    }
    
    public int richtige(LottoZiehung other) {
        int c = 0;
        for (int i : other.ziehung) {
            if (Arrays.binarySearch(this.ziehung, i) >= 0) {
                c++;
            }
        }
        return c;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final LottoZiehung other = (LottoZiehung) obj;
        if (!Arrays.equals(this.ziehung, other.ziehung)) {
            return false;
        }
        return true;
    }
    
    @Override
    public String toString() {
        return "LottoZiehung{" + "ziehung=" + Arrays.toString(ziehung) + '}';
    }
    
    public static void main(String[] args) {
        List<LottoZiehung> ziehungen = new ArrayList<LottoZiehung>();
        for (int i = 0; i < 10; i++) {
            ziehungen.add(new LottoZiehung());
        }
        
        LottoZiehung meineZiehung = new LottoZiehung(
                new int[]{1, 49, 2, 48, 3, 47});
        System.out.println("meineZiehung = " + meineZiehung);
        System.out.println("equals = " + meineZiehung.equals(new LottoZiehung(meineZiehung.getZiehung())));
        
        for (int i = 0; i < ziehungen.size(); i++) {
            System.out.println(i + 1 + ": " + ziehungen.get(i) + ", richtige: " + ziehungen.get(i).richtige(meineZiehung));
        }
    }
}
```


----------



## SlaterB (23. Nov 2012)

@Magahretzius1.3
> Arrays.sort (feld, 1, 49);
ist falsch, da hast du wohl keine Begründung für?

du kannst jedes Teilarray mit z.B.
Arrays.sort (feld[2]);

sortieren, allerdings hast du im Moment 6 Unterarrays von je 10 Werten,
baue das besser um zu 10 Unterarrays von je 6 Werten

wenn man mit Indexen zugreift kann man die beiden Varianten kaum unterscheiden, hier fürs Sortieren wird es relevant


----------



## bananajoe (24. Nov 2012)

Ich finde den Ansatz "keine doppelte Zahlen" recht unständlich umgesetzt. Normalerweise verwendet man hierzu eine ArrayList und mischt diese mit Collections.shuffle(arraylist) oder man verwendet ein hashSet der automatisch false zurückgibt, falls das Element in der Liste schon schon vorhanden ist. So kann mit einem Dreizeilen wie


```
while (set.size() < w) {
			i = (int) (Math.random()*z)+1;
			set.add(i);
		}
```

eine Liste mit einer beliebigen Anzahl w von Elementen. Hier ist meine Lösung mit obigem Code


```
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;

public class Lottoziehung {

	// z bestimmt den Zahlenbereich und w wieviele Zahlen gezogen werden sollen
	public Integer[] lottoziehung(int z, int w) {
		HashSet<Integer> set = new HashSet<Integer>();

		int i = 0;
		// es wird solange gezogen, bis die gewünschte Anzahl Zahlen vorhanden
		// ist
		while (set.size() < w) {
			i = (int) (Math.random() * z) + 1;
			set.add(i);
		}
		// Konvertierung von set nach Array
		Integer[] zahlen = set.toArray(new Integer[0]);
		return zahlen;
	}

	public static void main(String[] args) {
		// Simuliere Lottoziehung 6 aus 45
		Integer[] z = new Lottoziehung().lottoziehung(45, 6);

		// Die Zahlen werden vor der Ausgabe sortiert
		Arrays.sort(z);
		System.out.println(Arrays.toString(z));
	}
}
```


----------



## hüteüberhüte (24. Nov 2012)

Math.random() mehrmals aufrufen sollte man vermeiden.


```
(int) (Math.random() *   46   ) + 1
```
 wäre korrekt.

int[] bevorzugen.

Methoden statisch machen, wenn sie ohnehin nicht auf Daten zugreifen.

Der Rest ist in Ordnung.

Edit: Scope von i begrenzen => mehr Übersicht.


----------



## Bernd Hohmann (24. Nov 2012)

Der klassische Ansatz für 6 aus 49 ist ein booelan Array mit 49 Einträgen zu erzeugen und den Generator eine Zahl zwischen 0 und 48 erzeugen zu lassen. Ist im Array auf der gezogenen Position ein FALSE, dann auf TRUE setzen und einen Zähler zu erhöhen. Ist der 6, dann sind 6 unterschiedliche Zahlen gezogen worden. Array abklappern, gut ist.


```
public static void main(String[] args) {
		boolean b[] = new boolean[49];
		int cnt = 0;
		while (cnt < 6) {
			int rnd = (int) (Math.random() * 48);
			if (!b[rnd]) {
				b[rnd] = true;
				cnt++;
			}
		}
		for (int i = 0; i < b.length; i++) {
			if (b[i]) System.out.println(i + 1);
		}
	}
```


----------



## hüteüberhüte (24. Nov 2012)

Ist der schnellste Ansatz, wenn man ein boolean[] haben möchte. Ansonsten meine Variante.


----------



## bananajoe (25. Nov 2012)

hüteüberhüte hat gesagt.:


> Ansonsten meine Variante.



Ich habe einen Zeitgleich mit "meine Variante" gemacht und musste feststellen, dass diese um Faktoren langsamer läuft als die HashSet Variante. Wenn man den Code anschaut wird schnell klar, dass die Schleifen und die ifs nach der Ziehung eines jeden Elements Zeit kosten. Die Zeiten steigen proportional mit der Grösse des Zahlenbereichs und der Anzahl der zu ziehenden Element an!


----------



## Bernd Hohmann (25. Nov 2012)

hüteüberhüte hat gesagt.:


> Ansonsten meine Variante.



... die ich eher als Beispiel für obfuscated code sehe :-D Ich hab nicht mal auf den dritten Blick verstanden, was da eigentlich passiert.

Bernd


----------



## Ark (25. Nov 2012)

hüteüberhüte hat gesagt.:


> Ist der schnellste Ansatz


Nö. Wenn immer die gleiche Zufallszahl gezogen wird (zufälligerweise ), dauert das ewig.

So eine Fragestellung gab es übrigens schon einmal: http://www.java-forum.org/mathematik/116289-random-sample.html In dem verlinkten Thread gibt es auch Algorithmen, die zum eigentlichen Ziehen der Zufallszahlen nur höchstens so viele Schritte brauchen, wie Zufallszahlen benötigt werden. (Hinzu kommt noch etwas Vorbereitung, die so viele Schritte benötigt, wie es Zahlen gibt, aus denen zufällig gewählt werden soll.)

Ark


----------



## hüteüberhüte (25. Nov 2012)

Es wird aber nicht immer die gleiche Zahl generiert.

Wenn man ein int[] benötigt, ist meine deshalb die schnellste, weil HashSet erzeugen, prüfen, ob vorhanden, und einfügen eben nicht genau eine Operation ist, sondern länger dauert als 1+2+3+4+5=15 Vergleichsoperationen. Also labert nicht so d*mm rum.


----------



## hüteüberhüte (26. Nov 2012)

Kann ja mal jeder selber testen:

```
final int n = 100000;

        int[][] array = new int[n][];
        long t1 = System.currentTimeMillis();
        for (int x = 0; x < n; x++) {
            int[] ia = new int[6];
            a:
            for (int i = 0; i < ia.length;) {
                int r = random.nextInt(49) + 1;
                for (int j = 0; j < i; j++) {
                    if (ia[j] == r) {
                        continue a;
                    }
                }
                ia[i++] = r;
            }
            array[x] = ia;
        }
        long t2 = System.currentTimeMillis();
        System.out.println("array = " + array);

        HashSet[] harray = new HashSet[n];
        long t3 = System.currentTimeMillis();
        for (int x = 0; x < n; x++) {
            HashSet<Integer> h = new HashSet<Integer>();
            while (h.size() < 6) {
                h.add(random.nextInt(49) + 1);
            }
            harray[x] = h;
        }
        long t4 = System.currentTimeMillis();
        System.out.println("harray = " + harray);

        System.out.println(t2 - t1);
        System.out.println(t4 - t3);
```
Bei mir kommt etwa so was raus:

```
array = [[I@...
harray = [Ljava.util.HashSet;@...
78
733
```
~ 939,74 %


----------

