# Abzählreim über ein Array



## blane.de (24. Nov 2007)

Hallöchen....

Bräuchte für eine Aufgabe im Studium dringend eure Hilfe....

Undzwar haben wir folgende Aufgabe.

Entwickeln Sie eine statische Methode zum Ermitteln des Siegers bei einem Abzählen. Die 
Methode  bekommt  die  Informationen  Kinderanzahl  sowie  die  Anzahl  der  Silben  des 
Abzählreims übergeben. Das Ergebnis  ist eine Zahl, die sagt, welches Kind gewinnt (übrig 
bleibt). Das Abzählen beginnt immer mit dem ersten Kind.  
Der Aufruf  der Methode  abzaehlen(12,9)    (12 Kinder  und  9  Silben  im Reim) müsste  das 
Ergebnis 2 liefern. 
Hinweise:  
Man verwende ein Array in der Methode, in dem für jedes Kind gespeichert ist, ob es noch 
„drin“ ist, oder schon abgezählt wurde.  
Mit kleiner Reimanzahl (1 oder 2) lässt sich die Methode gut überprüfen.  
Bauen Sie ab- bzw. zuschaltbare Zwischenausgaben ein.

Wäre für Hilfe sehr hilfreich....

Haben gerade erst begonnen mit Java und daher seh ich noch nicht wirklich richtig durch...


DANKE


----------



## anfänger15 (24. Nov 2007)

du könntest ja mal deinen ansatz posten. Dann können wir dir helfen ihn zu verfolständigen


----------



## blane.de (24. Nov 2007)

naja da fängt mein Problem ja an.

Also ich hab mir gedacht, das ich erstmal eine main- Methode brauche, die ich als Klasse anlegen würde.
Dann würde ich noch zwei Methoden anlegen für die Kinder und eine evtl. für den Reim. Und dann noch für den Kinderkreis.

Den Kinderkreis, also das Array würde ich in etwa so machen...



```
public class Kreis
{
     private Kind[] kreis;
     private int       zKeam;
    
    public Kreis(int i)
    {
        this.kreis =new Kind[i];
    }


// Methode um Kinder in den Kreis aufzunehmen
    public void einfuegen(Kind s)
    {
        for(int i = 0; i < kreis.length; i++)
        {
            if(kreis[i] == null)
            {
                kreis [i] = s;
                break;
            }
        }
    }


// Methode um ein ausscheidendes Kind zu entfernen...
    public void entfernen(Kind s)
    {
        int i= 0;
        for(i = 0; i < kreis.length; i++)
        {
            if(kreis[i].equals(s))
            {
                kreis [i] = null;
                break;
            }
        }
        for (i=i; i < kreis.length-1; i++)
        {
         kreis[i]=kreis[i+1];
         kreis[i+1] = null;
        }
    }
 
}
```


Die nächste Methode wäre wie ich die Kinder anlege.....


```
public class Kind
{
    String name;
    
    public Kind(String name)
    {
        this.name = name;
    }

    public String gibName()
    {
        return name;
    }       
}
```


Mein Problem ist nun der Abzählreim ansich und die statische Methode (Main)....


----------



## HLX (24. Nov 2007)

Schön, dass du objektorientiert anfängst, was jedoch hier offensichtlich nicht erforderlich ist.

Das einzige, was du zunächst brauchst ist ein Blatt Papier und einen Stift. Male ein paar Strichmännchen und zähle sie ab. Dann nehme eine andere Anzahl und zähle sie wieder ab. Versuch eine Algorithmus daraus abzuleiten.

Kleiner Tipp:


> Man verwende ein Array in der Methode, in dem für jedes Kind gespeichert ist, *ob* es noch
> „drin“ ist, oder schon abgezählt wurde.


Hierfür verwendest du ein Boolean-Array.


----------



## blane.de (24. Nov 2007)

Hab den Schritt mit dem Stift mal hier niedergelegt....








Komm jetzt aber nicht weiter...

Ist as abzählen eine Modulo Funktion?!?!?!?


----------



## masta // thomas (24. Nov 2007)

Nein, eine Schleife. Dein Diagramm ist doch super  denk nicht zu kompliziert.


----------



## HLX (24. Nov 2007)

> Man verwende ein Array in der Methode, in dem für jedes Kind gespeichert ist, ob es noch
> „drin“ ist, oder schon abgezählt wurde.



Achte genau auf diesen Satz. Es werden keine Kinder entfernt. Das Array hält für jedes Kind ein Flag. Wenn du ein Kind abgezählt hast, legst du den Wert um. Irgendwann bleibt nur noch 1 Flag z.B. auf true stehen. Das "irgendwann" lässt sich genau bestimmen.


----------



## blane.de (24. Nov 2007)

Mal ne kleine Zwischenfrage zur Eingabe....


```
int n=System.out.println("Wie viele Kinder ? ");  // erfrage Kinderzahl
```

Hab mal das versucht zur Eingabe für die Anzahl der Kinder.... , weil ich die Variablen n und nachher noch k, also die Länge des Reims brauche..... Wie ordne ich diesen Variablen meine Eingabe richtig zu?????

omentan kommt ja Fehlermeldung, dass void rauskommt aber int verlangt wird.....


----------



## masta // thomas (24. Nov 2007)

Hm.. ich vermute, die Klassen, die du oben gepostet hast, hast du genauso wie dein Diagramm, nicht selbst gemacht, richtig? 
Wie du einen Wert über die Konsole einliest, findest du über die Suche hier im Forum.

Hast du denn schon einen Ansatz der Methode? Ich hab dir mal eine Musterlösung erstellt, wenn du nicht klarkommst, kann ich sie dir hier schreiben - aber ich erwarte schon einen Ansatz


----------



## blane.de (24. Nov 2007)

Hab jetzt zum einlesen im Forum das hier rausgefunden. 


```
int n=Integer.parseInt("Wie viele Kinder ? ");  // erfrage Kinderzahl
```

Und soweit beim übersetzen keine Fehler aber wenn ich es ausführe kommt folgendes...

java.lang.NumberFormatException: For input string: "Wie viele Kinder ? "
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
	at java.lang.Integer.parseInt(Integer.java:447)
	at java.lang.Integer.parseInt(Integer.java:497)
	at VerweisAbzaehlreim1.main(VerweisAbzaehlreim1.java:16)


----------



## HLX (24. Nov 2007)

In der Aufgabe steht nichts von einer Eingabemöglichkeit. Du brauchst die Abzähl-Methode lediglich mit verschiedenen Werten aus der main heraus aufzurufen.

Wenn du unbedingt willst, kannst du dieses Feature später noch einbauen. Stichwort ist hier InputStream. Fang aber erstmal an die Aufgabe zu lösen.


----------



## blane.de (24. Nov 2007)

Soweit meine abzähmethode...
Die Kinderklasse ist fertig und kein Problem..... 

```
public class abzaehlen {

  public static void main (String [] argv) {
      

    int i;
    Kind erster, letzter, index; 
    erster = letzter =  new Kind(0);

    for (i=1; i < n; i++){              
      index = new Kind(i);             
      letzter.next = index;                 
      letzter = index;                       
    }

    letzter.next = erster;            
}
```

Muss dazu sagen, dass ich das bis hierhin auch nur mit Hilfe hinbekommen habe....
zumindestens versteh ich das bis dato....

Doch wie nun weiter?????


----------



## HLX (24. Nov 2007)

Oh, oh, oh..ich wette du hast nichts von dem was in deinem Code steht verstanden. Wie nennt man denn die Datenstruktur, die du da aufgebaut hast? Wenn du das raus hast, schau nochmal in die Aufgabenstellung! Wo ist das Array?

Du redest von einer Abzählenmethode, schreibst aber eine Abzählenklasse. Wo ist die statische Methode? 

Das hat so keinen Zweck. Schau mal hier rein - für die Basics/Grundbegriffe (fang bei Kapitel 2 an):
www.galileocomputing.de/openbook/javainsel6


----------



## blane.de (24. Nov 2007)

handelt es sich hierbei nicht um eine statische main methode???


```
public static void main (String [] argv) {
```

[] --> Array


----------



## HLX (24. Nov 2007)

Nein. Die Main-Methode ist für den Programmstart. Das String-Array ist für Anwendungsparameter, die du beim Programmstart übergeben kannst.


----------



## blane.de (24. Nov 2007)

Laut...
http://www.gailer-net.de/tutorials/java/Notes/chap25/ch25_13.html
ist das eine statische Methode....


----------



## masta // thomas (24. Nov 2007)

Du hast glaube ich nicht verstanden, was HLX meinte.

Laut Aufgabenstellung sollst du eine statische Methode entwickeln, um das Abzählreim-Problem zu lösen. Nach dem Motto:


```
public static int abzaehlen(int anzahlKinder, int anzahlSilben)
{
    // hier muss was rein
}
```

Die Klassen, die du da gepostest hast, sind absolut überflüssig. Du sollst nur diese eine Methode schreiben. Du solltest dich unbedingt mit Java Grundlagen befassen, sonst wird das nichts..


----------



## HLX (24. Nov 2007)

Korrekt. 



			
				blane.de hat gesagt.:
			
		

> Der Aufruf  der Methode  *abzaehlen(12,9)*    (12 Kinder  und  9  Silben  im Reim) müsste  das Ergebnis *2 liefern*.



Hmm, aber die main ist void...und das kann man auch nicht ändern. Was machen wir denn da? Kein Rückgabewert  :cry: 

Also: Du musst eine eigene statische Methode schreiben. So steht´s in deiner Aufgabe. So, und jetzt bin ich mal gespannt auf deinen Ansatz. Wenn er zufriedenstellend ist, zeige ich dir, wie du deine Werte über Programmargumente im Java-Aufruf übergeben kannst.


----------



## blane.de (26. Nov 2007)

```
main methode
int i;
int k;
i=0;
k=0;
 rufe Klasse Kind auf um Anzahl einzugeben -- k
 rufe abzaehlreim auf um Reimanzahl anzugeben – n
 führe abzaehlen aus

Klasse Kind
public class Kind {
  int  nr;                                    // Nummer für jedes Kind
  Kind next;                                  // Verweis auf naechstes Kind 
// Datenfelder  
  public Kind (int nr) {                      // Konstruktor fuer Kind
    this.nr   = nr;                           // initialisiere Nummer 
  }
}

Statische methode [] abzaehlen

private Kind[] kreis;
private int zkreis; //Zeiger auf Array kreis = Anzahl der Kinder

// kreis
public void add(Kind neu) {
if(zkreis<kreis.length) {
kreis[zkreis] = neu;
zkreis++;

public int size(){ return zkreis;}
public Kind get(int index){
if(index>=0 &&index<zkreis) return kreis[index];
else return null;
abzaehlreim
```


So mein nächster Vorschlag denn.....


----------



## masta // thomas (26. Nov 2007)

Eigentlich verstoße ich hiermit gegen meine Prinzipien, aber das kann ich mir nicht ansehen...
Warum hast du unseren Tip nicht befolgt, dir Java Grundlagen reinzuziehen? Und warum kommst du nicht von deiner Kind-Klasse weg, die bei der Aufgabenstellung überhaupt nicht gefragt ist?


```
public class Test  {
	
	public static void main(String[] args) {
		int children = 12;
		int syllables = 9;
		System.out.println("Sieger: Kind " + abzaehlen(children, syllables));
	}
	
	public static int abzaehlen(int childrenAmount, int syllables)
	{
		boolean[] children = new boolean[childrenAmount];
		
		int currentChild = -1;

		for(int i = 0; i < childrenAmount-1; i++)
		{
			for(int j = 0; j < syllables; j++)
			{
				if(currentChild + 1 < childrenAmount)
					currentChild++;
				else
					currentChild = 0;
			}
			while(children[currentChild])
			{
				if(currentChild + 1 < childrenAmount)
					currentChild++;
				else
					currentChild = 0;
			}
			children[currentChild] = true;
		}
		for(int i = 0; i < childrenAmount; i++)
		{
			if(children[i])
				continue;
			return i + 1;
		}
		return -1;
	}
	
}
```

Edit: eigentlich hab ich dir alles schön kommentiert, die Kommentare habe ich aber gerade rausgenommen. Ich fänds schön, wenn du versuchst, den Code selbst nachzuvollziehen und hier dann den kommentierten Code reinpostest. Dann können wir darüber bisschen diskutieren .


----------



## blane.de (26. Nov 2007)

Von der Kindklasse bin ich nicht weggekommen, weil wir das zuvor so akribisch behandelt hatten....
Und zu den Grundlagen muss ich sagen, das ich mir das Buch Java lernen mit BlueJ reingezogen habe, bzw. dabei bin damit Java zu verstehen. Allerdings mus sich sagen, das dieses Buch sehr an Beispiele angelegt ist und nicht allgemein. Wäre evtl ein Manko. Aber da ich das vom Prof. aufgebrumt bekommen habe wollte ich mich daran halten. Wenn ich damit durch bin, hatte ich vor mir Java in 21 Tagen durch zu arbeiten, da mir das empfohlen wurde....

Daher denke ich kommt das Verständniss bei mir nach und nach... Ich werde mich denn jetzt mal an den Quelltext setzten und verstehen....

Danke schonmal


----------



## blane.de (26. Nov 2007)

kleine Zwischenfrage....

Worin besteht der Unterschied zwischen


```
i++
```
und

```
i+1
```

Ist doch eigentlich synonym oder nicht?

???


----------



## masta // thomas (26. Nov 2007)

look here


----------



## HLX (26. Nov 2007)

@Masta // Thomas:  nach dem letzten Ansatz muss ich dir zustimmen.  :wink: 



			
				blane.de hat gesagt.:
			
		

> Von der Kindklasse bin ich nicht weggekommen, weil wir das zuvor so akribisch behandelt hatten....



Hätte in der Aufgabe etwas von verketteter Liste gestanden, wärst du vielleicht auch auf dem richtigen Weg gewesen. Vielleicht ist das dann eure nächste Aufgabe.

Falls euer Prof nicht auf "continue" steht kannst du in der letzten For-Schleife übrigens auch

```
for (int i = 0; i < childrenAmount; i++) {
    if (!children[i])
        return i + 1;
}
```
schreiben.


----------



## blane.de (26. Nov 2007)

So erstmal ins Allgemeindeutsche gebracht


```
public class Test                                                       // Klasse Test
{
   
   public static void main(String[] args)                               // Mainmethode ohne rückgabe mit Stringarray
   {
      int kinder = 12;                                                  // kinder werden auf 12 gesetzt
      int silben = 9;                                                   // silben werden auf 9 gesetzt
      System.out.println("Sieger: Kind " + abzaehlen(kinder, silben));  // Ausgabe auf Konsole
   }
   
   public static int abzaehlen(int kinderAnzahl, int silben)            // statische Methode abzaehlen vom Typ int
   {
      boolean[] kinder = new boolean[kinderAnzahl];                     // bool`sches Array aus kinder bekommt neues bool`sches Array aus kinderAnzahl(Länge)
      
      int aktuellesKind = -1;                                           // aktuelle Kind wird auf -1 gesetzt

      for(int i = 0; i < kinderAnzahl-1; i++)                           // for-Schleife -- i wird 0 gesetzt -- i kleiner kinderanzahl-1 -- i erhöhen
      {                                                                 // i = Kindervariable
         for(int j = 0; j < silben; j++)                                // j auf 0 setzten -- j kleiner als silben -- j erhöhen
         {                                                              // j = silbenvariable
            if(aktuellesKind + 1 < kinderAnzahl)                        // wenn aktuellesKind + 1 kleiner als kinderanzahl ist
               aktuellesKind++;                                         // dann erhöhe aktuellesKind
            else                                                        // ansonsten
               aktuellesKind = 0;                                       // setze aktuellesKind auf 0
         }
         while(kinder[aktuellesKind])                                   // während das kinder-Array von der Länge aktuellesKind
         {                                                              // tue
            if(aktuellesKind + 1 < kinderAnzahl)                        // wenn aktuellesKind + 1 kleiner kinderAnzahl ist
               aktuellesKind++;                                         // erhöhe das aktuelle Kind
            else                                                        // ansonsten
               aktuellesKind = 0;                                       // setzte es wieder auf 0
         }
         kinder[aktuellesKind] = true;                                  // das bool`sche array kinder ist dann wahr
      }
      for(int i = 0; i < kinderAnzahl; i++)                             // für i=0 -- i kleiner kinderAnzahl -- erhöhe i
      {
         if(kinder[i])                                                  // wenn kinder Array Länge 0 hat
            continue;                                                   // wiederhole
         return i + 1;                                                  // gebe den Wert i + 1 zurück
      }
      return -1;                                                        // gebe -1 zurück
   }
   
}
```


----------



## masta // thomas (26. Nov 2007)

Beim Kommentieren ist es eher sinnvoll, bestimmte Blöcke zu kommentieren. Dabei kurz schildern, was in dem Block passiert - nicht einfach den Quelltext in Deutsch-Schreib-Quelltext portieren. Das macht ist wenig sinnvoll.


```
public class Test  {
	
	public static void main(String[] args) {
		int children = 12;
		int syllables = 9;
		System.out.println("Sieger: Kind " + abzaehlen(children, syllables));
	}
	
	public static int abzaehlen(int childrenAmount, int syllables)
	{
		// Kinder in einem boolean-Array darstellen; 
		// true = bereits draussen; false = noch drin
		boolean[] children = new boolean[childrenAmount];
		
		// aktuelle Position (zeigt noch auf _kein_ Kind)
		int currentChild = -1;
		
		// nur [anzahlDerKinder - 1] mal abzaehlen, 
		// somit bleibt am Ende genau einer uebrig
		for(int i = 0; i < childrenAmount-1; i++)
		{
			// aktuelle Position um anzahlDerSilben erhoehen
			for(int j = 0; j < syllables; j++)
			{
				// ueberpruefen, ob aktuelle Position die anzahlDerKinder
				// nicht ueberschreitet, falls ja, bei Kind 0 weitermachen
				// andernfalls ein Kind weitergehen
				if(currentChild + 1 < childrenAmount)
					currentChild++;
				else
					currentChild = 0;
			}
			// ueberpruefen, ob das Kind an der nun errechneten 
			// Position(letztes Kind + anzahl Silben) bereits draussen ist
			// falls ja, ein Kind weitergehen (dabei wieder ueberpruefen,
			// dass man die anzahlDerKinder nicht ueberschreitet)
			while(children[currentChild])
			{
				if(currentChild + 1 < childrenAmount)
					currentChild++;
				else
					currentChild = 0;
			}
			// Kind markieren => draussen
			children[currentChild] = true;
		}
		// nun genau das eine Kind raussuchen, welches nicht markiert ist
		for(int i = 0; i < childrenAmount; i++)
		{
			if(children[i])
				continue;
			return i + 1;
		}
		return -1;
	}
	
}
```


----------



## blane.de (26. Nov 2007)

arg das mit dem Verständniss sollte jetzt kommen.... 
Hab nur ein Zwischenschritt gemacht, damit ich das schneller verstehe bzw besser....


----------



## blane.de (26. Nov 2007)

```
for (int i = 0; i < childrenAmount; i++) {
    if (!children[i])
        return i + 1;
}
```

Das heißt jetzt hier....

Wenn das Array Kind nicht der Länge i entspricht
gebe i + 1 zurück....


Hier haperts noch....

Also wenn NICHT das Array Kind (Anzahl der Kinder bzw. Arraylänge) ist
dann gebe Kinderanzahl+1 zurück?!?!?


----------



## blane.de (26. Nov 2007)

schon selbst verstanden

for (int i = 0; i < childrenAmount; i++) {
    if (!children_)
        return i + 1;
} 


Er gibt quasi den letzten Wert der nicht drauss ist an
gibt letztes Kind + 1 zurück und dann 
gibt er letztes Kind +1 -1 aus....._


----------



## blane.de (26. Nov 2007)

ok supi habs verstanden.....

Dake euch..... 

Hab mir ne Kladde fertiggemacht an der ich es jetzt komplett verstehe.

Hoffe ich kann das nun auch auf simultane Beispiele anwenden....


----------



## HLX (26. Nov 2007)

blane.de hat gesagt.:
			
		

> Er gibt quasi den letzten Wert der nicht drauss ist an
> gibt letztes Kind + 1 zurück und dann
> gibt er letztes Kind +1 -1 aus.....


  ???:L :bahnhof: 

Also, Wenn die Schleife durchlaufen wird, ist nur noch ein Element auf false gesetzt.


```
// die Abfrage...
if (!children[i]) 
// ...kann man alternativ so schreiben:
if(children[i]==false)
```
Das ist eine überprüfung, ob das i-te Element auf false steht. Sobald das eine Element gefunden wird, erfolgt
die Rückgabe von i+1, da man im Array bei 0 zu zählen beginnt und es kein 0. Kind gibt.


----------

