Zu erst habe ich die Tests in IntelliJ ausgeführt. Da haben sortEmpty
,generic
und create23
gefailed.
In sortEmpty
und generic
gab es ArrayIndexOutOfBoundsException
, von den beiden hörte sich der empty-test einfacher an.
Also habe ich in emptySort()
einen Breakpoint vor dem a.sort()
(also auf die gleiche Zeile) gesetzt und habe den Test dann debuged (Name rechts-anklicken "Debug sortEmpty()" oder mit Tastatur-shortcut).
Am Breakpoint angekommen bin ich in a.sort()
rein-gesteppt (F7), dann nochmal in recursiveSort(numbers.length)
bis ich in deiner eigentlichen Sortierfunktion war. Dort dann Zeile für Zeile durch gesteppt (F8) bis es gecrashed ist, als es im else
Teil das maximum lesen wollte (array index 0 war natürlich im empty array out of bounds).
Da ja laut Aufgabenblatt bei else
Geschichte entfernt. Danach habe ich wieder alle tests laufen lassen: emptySort
passt jetzt, aber generic
und create23
failen weiter.
Weil exceptions finden einfacher ist als "logische" Fehler (falsch sortiert) habe ich mir als nächstes generic
angeschaut. Hier musste ich natürlich immer in den Rekursiven Fall "rein"steppen (F7) und nicht "drüber"steppen (F8).
Bis "ganz runter" (until = 0) ging alles gut, also wusste ich das der Fehler beim "hochgehen" passieren musste. Also habe ich den Code in der if
Klausel angeschaut und sofort gemerkt das until < this.numbers.length()
und int max = this.numbers[until+1]
ein Problem ist denn ein Array von Länge
Wenn man das nicht direkt sieht kann man aber auch einfach wieder weiter mit F8 steppen bis es crashed und dann weiss man wo es crashed.
Als erstes habe ich die crashende Zeile auf int max = this.numbers[until]
geändert, denn wir wollen ja den Bereich [until,numbers.length) durchsuchen - siehe Beschreibung. Alle Positionen von 0 bis und mit until-1 wurden ja durch Rekursion schon sortiert. Jetzt also müssen wir den grössten Wert aus until bis ende finden. Der Aufruf auf numbers[until]
ist auch sicher wegen dem if
und weil kein +1
mehr drin ist.
Dann habe ich direkt gesehen, dass am Ende das this.numbers[until+1] = max
natürlich auch crashen wird. Aber das könnte man auch durch neues debuggen rausfinden. Zum Glück ist auch das "doppelt" falsch: Einmal crashed es, und einmal ist es die falsche Stelle. Laut Aufgabe soll recursiveSort das Maximum ja mit der Zahl an Stelle until-1
vertauschen.
Daraus merken wir direkt, dass wir nicht nur das maximum brauchen sondern auch die Position vom maximum, damit wir die andere Zahl da hin packen können. Also fügen wir eine Variable dafür hinzu und updaten es wenn wir max upadten.
Jetzt können wir am Ende die Zahlen vertauschen (brauchen dafür natürlich eine hilfsvariable damit wir keine "verlieren)
Wieder alle tests laufen lassen: Juhu, nichts neues! Aber leider failed generic
immer noch und create23
auch. Aber zum Glück crashed generic
nicht mehr. Stattdessen ist der "String nicht well formed"...Mhh, also ein Problem mit toString()
. Mh, das Test Pattern enthält delim
und wenn wir das anschauen (rechtsclick Go To -> Go To oder Cmd/Ctrl+B) dann sehen wir das es als ", "
, d.h. mit Leerzeichen definiert ist und in deinem toString()
kein Leerzeichen nach dem Komma ist. Easy fix!
Ok, generic
failed immer noch aber wengistens create23
ist wohl dadurch schon magisch gefixed. Yay! Neuer Fehler bei generic: Wrong order at position .. of array.
Also stimmt die Sortier Logik irgendwo nicht...
Die Stelle ist erst irgendwo im Array, d.h. vermutlich hat es was mit dem maximum finden und swappen zu tun (sonst würde es schon direkt an Stelle 1 oder so fehlschlagen)...
Beim durchsteppen setze ich einen Breakpoint auf die if(until < numbers.length()
Zeile und benutze Resume Program (Cmd+Option+R oder Ctrl+Alt+R) um bis zum nächsten Breakpoint (also wieder der gleiche, nur ein level "höher" zu gehen.
Dabei achte ich einfach nur im Variablen Fenster auf this
und schaue zu wie es die Sachen sortiert. Irgendwann macht es einen Fehler und ich sehe: Aha, da war das Element was da stand grösser als das was es da hin geswappt hat. Also schaue ich auf den code und denke "Klar, int max = numbers[until]
kann ein Problem sein wenn numbers[until-1]
grösser ist, weil wir dann das "kleinere" max dahin swappen würden. Also wird es auf int max = numbers[until-1]
geändert.