# Elemente zufällig in ein Array verteilen



## Lain_Iwakura (22. Nov 2012)

Hi,


ich hab folgendes Problem:

Ich habe ein 2D-Array, mit zum Beispiel 8x8 Elementen.
Dieses Array wird zufällig mit 0 und 1 gefüllt. 
Aber die 0 darf nur 8 mal vorkommen.

Mein Versuch:



```
int a=0;
int x = 8 ;
int y = 8;
         
          int[][] array  = new int [x][y];
       
        
         for(int i=0; i<x; i++)
          {
              for(int n=0; n<y; n++)
              {
                array[i][n] = (int) Random(0,1);  
                  
                 
                if(array[i][n] == 0)
                  {
                      a++;
                      if(a > 8)
                      {
                          array[i][n] = 1;
                      }
                  }
                  
                
                  System.out.print(array[i][n]);
              }
          }

//ausserhalb von main
 public static int Random(int minval, int maxval){
     
       return minval + (new java.util.Random()).nextInt(maxval-minval+1);
      }
```

Was dann aber natürlich immer rauskommt, ist dann eine Zahlenkette, mit sehr vielen 1 hinten, weil die ersten 8 Nullen schon verbraucht werden.

Mir will aber partout nicht einfallen, wie ich diese Nullen unter die ganzen 1 vermischen soll.
Ich hatte höchstens die Idee, für diese Nullen ein extra Array mit 8 Nullen zu schreiben, dessen Elemente dann in das Feld verstreut werden. Die Position soll zufällig bestimmt werden.
Würde diese Idee Sinn machen ?

Würde mich über Tipps freuen^^


----------



## SlaterB (22. Nov 2012)

schau dir an was die Forum-Code-Formatierung aus deiner Methode Random macht,
Methoden NIE groß schreiben und schon gar nicht wie bekannte Klassen benennen

-------

du kannst wie bei Lottozahlen mehrfach Werte zwischen 0 und 64 wählen bzw. zwei Zufallszahlen von 0 bis 8 und an diesem Index die 0 setzen (in etwa deine Idee, ja),
auf doppelte Ziehungen achten

komfortabel, auch bei Lotto, ist Einfügen aller 64 Werte, 8x 0, 56x 1, in eine Liste,
dann Collections.shuffle() und die nun zufällig verteilten 64 Werte der Reihe nach ins Array schreiben


----------



## KSG9|sebastian (22. Nov 2012)

Warum änderst du den Random nicht?

- es gibt 64 Stellen zu füllen
- maximal 8x mit einer 0
- minimal 56x mit einer 1

=> Nullen : Einsen > 1 : 7


```
double rand = Math.random();

if(rand < 0.7){
 arr[a][b] = 1;
} else {
 arr[a][b] = 0;
}
```

Ich versteh denn Sinn in der Aufgabe aber nicht so ganz?

Ach...Methoden werden in Java klein geschrieben mit Camel-Case  -> calculateNextRandomBetween(int min, int max)

Du kannst auch die Arrays füllen und anschließende shuffeln..aber das Ergebnis bleibt gleich - viele Einsen, wenig Nullen


----------



## tfa (22. Nov 2012)

Außerdem sollte nur ein Random-Objekt erzeugt werden, und nicht bei jedem Methodenaufruf ein neues.


----------



## SlaterB (22. Nov 2012)

@KSG9|sebastian
klingt so nach vollständiger Lösung, aber mit diesem Random können genausogut 5 oder 12 0en eingefügt werden, nicht nur 8,
gut, nach oben wohl begrenzt, dennoch Nachbearbeitungsbedarf

1:7 ist auch nicht gerade bei 0.7


----------



## Lain_Iwakura (22. Nov 2012)

@Sebastian

Hab deinen Code eingefügt (und angepasst usw....)
Math.Random() steht auch ausserhalb der Schleife.

Aber jetzt kommen entweder nur 0 und nur 1 raus. 
Und das natürlich dann mit verschiedenen Wahrscheinlichkeiten.


----------



## SlaterB (22. Nov 2012)

was wohl an
> Math.Random() steht auch ausserhalb der Schleife.
liegt und offensichtlich nicht zwingend gefordert/ richtig ist,
nur ein Zufallsereignis auf alle anwenden, das kann ja nicht gut gehen


----------



## Lain_Iwakura (22. Nov 2012)

ok , dann hatte ich das oben missverstanden. 
ich musste das noch etwas ändern, aber mit Sebastians-Code klappt es. 
das " rand < 0.7" kannte ich noch nicht (also wie man die Wahrsceinlichkeit ändern kann.

thx^^


----------



## SlaterB (22. Nov 2012)

die Wahrscheinlich ist bisschen hoch, ~ jedes dritte Element ne 0, damit kommst du wahrscheinlich nahezu immer auf genug 0en 
(die Wahrscheinlichkeit dafür kann man wieder ausrechnen, bestimmt 99,99999..%) 
allerdings werden die sich schon weit vorne ansammeln, hinten bleibt es recht 0-frei

vorher hattest du ja 50%, also 0,5 implementiert, 1:7 wäre 0.875,
dann wie gesagt mit dem Risiko dass es auch mal weniger als acht 0en sind


----------



## Lain_Iwakura (22. Nov 2012)

ich versuch's grad mit ner If-Abzweigung wieder wett zu machen.
Klappt aber doch nicht so ganz,wie es vorhin den Anschein hatte.
Der spuckt ab und zu immer noch weniger als 8 Nullen aus...
Aber es sind zumindest nicht mehr mehr als 8 und die Nullen sind schöner verteilt.


----------



## KSG9|sebastian (22. Nov 2012)

Ok, ich dachte der Code ist so schlecht das man sieht das es keine fertige Lösung sein soll..dafür gibt's doch immer auf die Finger. 

Die 70% sind auch nicht ganz korrekt..ich wollte doch nur Ansätze bieten 

** Edith **
Natürlich sind es nicht immer 8 Nullen..die Chance das der Zufallsgenerator nur 5x eine Null "errechnet" ist doch auch relativ hoch


----------



## nillehammer (22. Nov 2012)

Das mit Random ist der falsche Ansatz. Wenn die Wertemenge festgelegt ist (hier 8 Nullen und 56 Einsen), dann braucht man sie genau so. Fülle also erst eine Liste mit 8 Nullen und 56 Einsen. Jetzt hast du einen "Topf" aus dem Du ziehen kannst. Leider noch nicht zufällig verteilt. Wie das geht, hat SlaterB schon angedeutet (auch, wenn manchmal etwas kryptisch, lohnt es sich, seine Posts zu lesen ). Du musst die Elemente in dem Topf mischen (engl: to shuffle). Da gibt es im API schon eine tolle Methode für 
	
	
	
	





```
Collections.shuffle
```
. Nun hast Du den Topf mit zufällig verteilten Elementen. Dann einfach diesen Topf von vorne nach hinten durchiterieren und auf Deinen Array verteilen. Wie findest Du den richtigen Index für die Übertragung aus der eindimensionalen Liste in den zweidiemnsionalen Array? Da helfen Dir die Ganzzahldivision mit 
	
	
	
	





```
/
```
 sowie er "Resterechner" Modulo 
	
	
	
	





```
%
```
. Das ganze in lauffähigen Java-Code gegossen, sieht dann so aus:

```
public class AppTest {

  public static void main(String[] args) {

    final List<Integer> values = createOneZeroList(8, 64);

    final int[][] intTable = createIntTable(values);

    System.out.println(Arrays.deepToString(intTable));
  }

  public static List<Integer> createOneZeroList(final int zeroAmount,
      final int totalElemAmount) {

    final List<Integer> result = new ArrayList<Integer>(totalElemAmount);

    // gewünsche Anzahl Nullen zur List adden
    for (int i = 0; i < zeroAmount; i++) {

      result.add(0);
    }

    // restliche Einsen adden
    for (int i = 0; i < totalElemAmount - zeroAmount; i++) {

      result.add(1);
    }

    System.out.println(result.size());

    // Liste "mischen"
    Collections.shuffle(result);

    return result;

  }

  public static final int[][] createIntTable(final List<Integer> values) {

    final int dimension = 8;

    final int[][] result = new int[dimension][dimension];

    for (int i = 0, valuesSize = values.size(); i < valuesSize; i++) {

      final int rowIndex = i / dimension;

      final int colIndex = i % dimension;

      result[rowIndex][colIndex] = values.get(i);
    }

    return result;
  }
}
```
Der Code ist jetzt genau auf Deinen Anwendungsfall programmiert. Man könne ihn sicher noch flexibler machen, indem mehr Parameter übergebbar macht.


----------



## Lain_Iwakura (22. Nov 2012)

ok erstmal danke ! oO"

Ich habs eben schnell eingefügt, der zeigt mir jedoch überall rote Kringel. Ich werds nachher mir genauer ansehen.
Aber die Idee mit den Töpfen klingt logisch.  Hatte vorhin in meinem Eröffnungsbeitrag so etwas ähnliches mit dem Extra-Array gemeint, ging  jedoch in die falsche Richtung.


----------

