Skip to forum
Benachrichtigungen
Alles löschen

[Geschlossen] Java: Kinderreim

11 Beiträge
3 Benutzer
0 Reactions
1,557 Ansichten
Dauser
Joined: 19.03.2007

Hi,
Habe folgende Aufgabe, bei der ich nicht weiterkomme.
Das kleingeschriebene sind die genauen Anweisungen, sind aber zum Verständnis nicht unbedingt notwendig.

Aus einer Gruppe von n Kindern soll ein Gewinner ermittelt werden, indem sie sich im Kreis aufstellen und wiederholt mittels eines Reims von m Takten einen Ausscheider abzählen. Jedes ausgezählte Kind verlässt den Kreis, der sich daraufhin wieder schließt. Im neu geschlossenen Kreis beginnt das Abzählen an der Position nach dem ausgeschlossenen Kind.
Gewinner ist das Kind, das als letztes übrig ist.
Beispiel:
Die ersten 4 Auszählschritte für n = 9, m = 5. Die komplette Folge lautet: 5, 1, 7, 4, 3, 6, 9, 2, 8. Der Gewinner steht an
Stelle 8 des ursprünglichen Kreises.
Ziel dieser Aufgabe ist es für gegebenes n und m diejenige Position im ursprünglichen Kreis der Größe n zu bestimmen, an
der das letzte übrigbleibende Kind steht.
Um das Abzählen im Kreis möglichst einfach zu gestalten, benutzen wir eine einfach verkettete zirkuläre Liste. Dies
bedeutet, dass der letzte Knoten nicht auf null, sondern zurück auf den ersten Knoten der Liste zeigt.

Zur Navigation in der Liste benutzen wir einen Zeiger (pointer), der die aktuelle Position in der Liste anzeigt.
Die Liste erlaubt (unter anderem) diese Operationen, die folgendermaßen umzusetzen sind:

· Einfügen: Ein neu einzufügender Knoten wird als Nachfolger des Knotens eingefügt, auf den pointer zeigt.
Nach dem Einfügen des neuen Knotens zeigt pointer auf diesen.
· Abfragen: Liefert das Inhaltselement des aktuellen Knotens. Der Zeiger pointer bleibt unverändert.
· Löschen: Gelöscht wird der Knoten auf den pointer zeigt. Nach dem Löschen eines Elements bewegt sich
pointer auf den Vorgänger des gelöschten Knotens.
· Zeigerbewegung: Der Zeiger pointer wird um eine angegebene Anzahl von Knoten weiterbewegt.

Definieren Sie für den ADT „Zirkuläre Liste“ zunächst ein Java-Interface datenstrukturen. IZirkulaereListe mit folgenden Methoden:
Methode: void addElement(Object element)
Fügt das übergebene Objekt in die Liste an der aktuellen Position ein.
Methode: Object getElement()
Liefert das Inhaltselement des Knotens zurück, auf den pointer verweist.
Methode: Object removeNode()
Entfernt den aktuellen Knoten aus der Liste, und gibt dessen Inhaltselement zurück. Bei einer leeren Liste wird null zurückgeliefert. Methode: void
movePointer(int n)
Bewegt den Zeiger auf das aktuelle Element um n Positionen weiter. Für n < 1 bleibt der Point unverändert.
Methode: int getSize()
Gibt die Anzahl der Elemente in der Liste zurück.
Methode: boolean isEmpty()
Gibt zurück, ob die Liste leer ist.
Erstellen Sie nun eine Klasse datenstrukturen.ZirkulaereListe, die obige Schnittstelle implementiert und folgende Attribute und weiteren Methoden aufweist:
Attribut head: Typ Node
Zeigt auf den ersten Knoten der zirkulären Liste.
Attribut pointer: Typ Node
Zeigt auf den aktuellen Knoten der zirkulären Liste.
Hilfsmethode: Node getPreviousNode(Node node)
Sucht den Vorgänger zu übergebenem Knoten node und gibt diesen zurück.
Überschriebene Methoden: String toString()
Erzeugt eine textuelle Repräsentation der Knoten der Liste, analog zur toString()-Methode der verketteten Liste aus dem Skript. Bei head beginnend wird die Liste durchlaufen, bis jeder Knoten einmal besucht wurde.
Hinweise:
1. Sichtbarkeiten: Attribute und Hilfsmethoden sollen private, Methoden public sein.
2. Benutzen Sie die in der Vorlesung definierte Hilfsklasse Node (Skript 09-38). Kopieren Sie ihn in das gleiche Paket wie die zirkuläre Liste.
3. Eine alternative Behandlung des Head-Knotens (anders als in der verketteten Liste des Skripts) könnte sich einfacher gestalten. Dieser kann in der zirkulären Liste bereits das erste Inhaltselement tragen (sofern vorhanden). Die leere zirkuläre Liste bestünde dann aus 0 Knoten: leere Liste nach Einfügen von Siggi nach Einfügen von Harry Sie können jedoch auch das aus der Vorlesung bekannte Verfahren anwenden. Implementieren Sie abschließend eine Klasse spiele.KinderReim mit folgender Methode: public static int abzaehlen(int kinder, int takte) Gibt die Position des Gewinners bei kinder Kindern und einem Reim der Länge takte zurück. Benutzen Sie obige zirkuläre Liste zur Bestimmung der Gewinnerposition. Liefern Sie für ungültige Werte für kinder oder takte den Rückgabewert -1 zurück.

Das sind meine bisherigen Klassen:

ZirkulaereListe

IZirkulaereListe

Node

Kinderreim

meine Fragen:
1. Was macht dieses Interface? Stehen da nur die Methoden drin oder muss da noch was rein? Ruf ich diese Methoden dann über das interface auf?

2. Wie setze ich den pointer immer an die richtige Stelle? Bei meinem Code ist der ja am Anfang nicht gesetzt, und müsste einen Nullpointer-Fehler erzeugen.

3. Wie kann ich mir Java am Besten selber beibringen? Gibts da irgendwelche empehlenswerte Video2Brain-Folgen oder irgendwelche Bücher?


10 replies
Nazdhun
Joined: 10.03.2008

1.)
In einem Interface definierst du halt die Methoden (samt Übergabe- und Rückgabeparametern) die eine implementierende Klasse zur Verfügung stellen muss. Siehe Kapitel 6.10 Schnittstellen in der JavaInsel.

2.)
Das muss ich mir genauer angucken, bei Interesse könnte ich eine laufende Implementierung posten...

3.)
Da ist die JavaInsel sehr gut: http://openbook.galileocomputing.de/javainsel7/
Ist auf jedenfall ein Bookmark wert, um immer mal was nachzuschlagen, aber ich denke man kann es auch wohl "durcharbeiten" um Java zu lernen.


Dauser
Joined: 19.03.2007

Wenn du Zeit und Lust hast hätte ich nichts dagegen wenn du ne laufende Implementierung erstellst.
Aber es hilft mir ja nur kurzfristig, ich muss es ja irgendwie verstehn. Wobei das mit nem fertigen Code auch leichter geht....

p.s.: auf welcher seite spielst du?


Nazdhun
Joined: 10.03.2008

=> http://rapidshare.de/files/41114361/KinderReim.zip.html

Das ist ein Zip-File meines Eclipse-Projekts. Falls du auch Eclipse nutzt, kannst du das Projekt ja direkt importieren.
Ansonsten öffne das File und hol dir die Java-Dateien aus /src/ selbst raus.

Demo.java startet das ganze mit den Beispiel-Werten 9:5 aus der Aufgabe.
Ausserdem hab ich das ganze mit der Alternativen Lösung implementiert also ohne Head-Element in der Liste, weil das bei einer zirkulären Liste eigentlich keinen Sinn macht.

Ich hab möglichst viel kommentiert, falls du noch Fragen hast meld dich nochmal.
Das beste ist natürlich, wenn du es erst selbst hinbekommst:

- Beim Einfügen/Löschen in die Liste immer die Sonderfälle betrachten:
-- leere Liste
-- Nur ein Element (nextNode zeigt auf sich selbst)
- Beim Einfügen drauf achten, daß man nicht nur den Zeiger auf das nächste Element setzt, sondern auch den nextNode-Zeiger vom vorherigen Element nach dem man einfügt neu setzt.
-- usw...


Dauser
Joined: 19.03.2007

Danke für die Mühe!

Ich kann eigtl alle Schritte nachvollziehen, nur sind mirteilweise die Befehle nicht genau bekannt.
Allerdings meckert der Test, der drüberläuft noch:
Klick
Ich werde da nicht schlau draus.


Aus einer Gruppe von n Kindern soll ein Gewinner ermittelt werden, indem sie sich im Kreis aufstellen und wiederholt mittels eines Reims von m Takten einen Ausscheider abzählen. Jedes ausgezählte Kind verlässt den Kreis, der sich daraufhin wieder schließt. Im neu geschlossenen Kreis beginnt das Abzählen an der Position nach dem ausgeschlossenen Kind. Gewinner ist das Kind, das als letztes übrig ist.

ok, sorry, ich habe 4-5 doppelten whiskey-cola intus, dennoch:

scheiss drauf! warum will man sowas berechnen?!?!

1) das soll ein SPIEL sein! d.h der überraschungseffekt ist das hauptelement!
oder wird schon wieder dieser kleine fette schlaumeier gewinnen, den keiner leiden kann, weil er sich immer so geschickt hindrängelt, dass er gewinnt?

2) wir kämpfen mit rezession, welthunger, diktaturen, krieg, umweltkollaps.
warum beschäftigen sich "kaliber" mit solchen bagatellen???

3) jede blume, jeder sonnenaufgang, jede nackte nachbarin ist mehr wert, als "n-kinder durch auszählreim-quadrat"

mein (vorläufiges, besoffenes) fazit:
vergiss den scheiss! lebe dein leben und liebe aus geanzem herzen, bruder!
statt so eine scheisse zu berechnen, solltest du lieber die hübsche blonde vom gemüseladen gegenüber vreführen!


Dauser
Joined: 19.03.2007

Original von mcadam

Aus einer Gruppe von n Kindern soll ein Gewinner ermittelt werden, indem sie sich im Kreis aufstellen und wiederholt mittels eines Reims von m Takten einen Ausscheider abzählen. Jedes ausgezählte Kind verlässt den Kreis, der sich daraufhin wieder schließt. Im neu geschlossenen Kreis beginnt das Abzählen an der Position nach dem ausgeschlossenen Kind. Gewinner ist das Kind, das als letztes übrig ist.

ok, sorry, ich habe 4-5 doppelten whiskey-cola intus, dennoch:

scheiss drauf! warum will man sowas berechnen?!?!

1) das soll ein SPIEL sein! d.h der überraschungseffekt ist das hauptelement!
oder wird schon wieder dieser kleine fette schlaumeier gewinnen, den keiner leiden kann, weil er sich immer so geschickt hindrängelt, dass er gewinnt?

2) wir kämpfen mit rezession, welthunger, diktaturen, krieg, umweltkollaps.
warum beschäftigen sich "kaliber" mit solchen bagatellen???

3) jede blume, jeder sonnenaufgang, jede nackte nachbarin ist mehr wert, als "n-kinder durch auszählreim-quadrat"

mein (vorläufiges, besoffenes) fazit:
vergiss den scheiss! lebe dein leben und liebe aus geanzem herzen, bruder!
statt so eine scheisse zu berechnen, solltest du lieber die hübsche blonde vom gemüseladen gegenüber vreführen!

hmm, eigtl hast du recht. ich mach mir erstma n Bier auf PROST! :rolleyes:


Nazdhun
Joined: 10.03.2008

Original von Dauser
Danke für die Mühe!

Ich kann eigtl alle Schritte nachvollziehen, nur sind mirteilweise die Befehle nicht genau bekannt.
Allerdings meckert der Test, der drüberläuft noch:
Klick
Ich werde da nicht schlau draus.

Lass deinen Unit-Test nochmal über folgende Version laufen:
http://rapidshare.de/files/41116210/KinderReim.zip.html

Ich habe aus Versehen den neuen Knoten vor den Pointer-Knoten gesetzt und nicht wie gefordert danach...


Dauser
Joined: 19.03.2007

immernoch die gleiche fehlermeldung ;(

Edit: nein halt! die fehlermeldung ist jetzt gerade andersrum:
Teste 'removeElement':
Fuege hinzu: A
Fuege hinzu: B
Fuege hinzu: C
Fuege hinzu: D
Fuege hinzu: E
Fuege hinzu: F
Fuege hinzu: G
Fuege hinzu: H
Fuege hinzu: I
Fuege hinzu: J
Entferne 5 Elemente
Entferne Element: J
Ueberpruefe Status ('Emptiness', Laenge, Inhalt, Pointer):
Expected element: I
Actual element: A


Nazdhun
Joined: 10.03.2008

Hm, dann müsstest du mir mal die JUnit-Testklassen zukommen lassen.

Ich hab grad bei mir nochmal getestet:
Elemente 1-9 hinzugefügt (Pointer nun auf 9)
Dann remove() aufgerufen
9 wurde entfernt, Pointer zeigt nun auf 8, davon der nextNode auf 1

Also so wie es sein sollte...

Aber es ist natürlich wahrscheinlich, daß in meinem Code immer noch irgendwelche Zeiger chaos laufen

Mit den Testklassen könnte ich das eher bugfixen...


Dauser
Joined: 19.03.2007

Die testklassen sind nicht öffentlich.

Wenigstens hab ich mal ne Lösung mit der ich lernen kann.

Vielen Dank nochmal