AutoFeedback API

Result 0e61e181-e14d-465c-b423-3ebb50ad7044

{
  "llm" : {
    "feedback" : "# Exercise: fractal\n\n### Correctness\n- In `Boxes.drawRec`: Im Basisfall (`n == 0`) zeichnest du kein Rechteck, sondern kehrst sofort zurück. Damit wird bei `n == 0` gar nichts gezeichnet.\n- In `Boxes.drawRec`: Einer deiner rekursiven Aufrufe ist `drawRec(g, x, y, s, n-1)` (also gleiche Koordinaten und gleiche Seitenlänge). Das führt dazu, dass die gleiche Box immer wieder rekursiv aufgerufen wird (kein echtes “Verkleinern/Unterteilen”) und das Ergebnis nicht dem geforderten rekursiven Muster entspricht.\n- In `Triangles.drawRec`: Im Basisfall (`n == 0`) zeichnest du kein Dreieck, sondern kehrst sofort zurück. Damit wird bei `n == 0` gar nichts gezeichnet.\n- In `Triangles.drawRec`: Du zeichnest die Dreieckslinien in jedem Rekursionsschritt (auch wenn `n > 0`). Die Aufgabe ist so gedacht, dass beim Basisfall gezeichnet wird und sonst nur weiter unterteilt wird; so wie du es hast, werden auch “große” Dreiecke immer wieder gezeichnet und überdecken/vermischen das Fraktalmuster.\n\n### Suggestion\n- Überlege bei beiden Formen: Was ist das “kleinste” Objekt, das gezeichnet werden soll? Genau dieses sollte im `n == 0`-Fall gezeichnet werden (statt `return`).\n- Bei den Boxen: Prüfe, ob in jedem rekursiven Schritt die Parameter wirklich “kleiner” werden (vor allem `s`). Wenn ein rekursiver Call die gleichen `x,y,s` wie der aktuelle hat, entsteht kein Fortschritt in Richtung Basisfall-Muster.\n- Bei den Boxen: Überlege, welche Teilquadrate du im Rekursionsschritt erzeugen willst (Positionen relativ zu `x,y` und `s/2`) und ob wirklich alle rekursiven Aufrufe die halbe Größe verwenden.\n- Bei den Dreiecken: Entscheide dich für eine klare Trennung: **entweder** du zeichnest nur im Basisfall, **oder** du zeichnest auch in höheren Ebenen bewusst (dann aber entspricht es meist nicht dem erwarteten Fraktal). Für das typische Sierpinski-Muster: im Rekursionsfall nur Mittelpunkte berechnen und die 3 kleineren Dreiecke rekursiv aufrufen.\n- Bei den Dreiecken: Kontrolliere, ob deine drei rekursiven Dreiecke wirklich die “Eckdreiecke” sind (jeweils mit einer Original-Ecke und zwei passenden Mittelpunkten) – das hilft, wenn du die Parameter-Reihenfolge pro Call nochmal auf Papier skizzierst.\n\n### Code Style\n- Entferne auskommentierten Code (die auskommentierten `g.drawRect(...)`-Blöcke und alte Debug-Kommentare), damit der Kern der Lösung klar bleibt.\n- In `Triangles.drawRec`: Vermeide “Rechenkommentare” mit falschen/irreführenden Beispielen (z.B. `400+10/2` ohne Klammern). Wenn du kommentierst, dann eher “midpoint between (x0,y0) and (x1,y1)”.\n- Benenne Variablen konsistenter: statt `newmx`, `mx`, `mx2` lieber klarere Namen wie `m01`, `m12`, `m20` (oder `mid01X/mid01Y` usw.).\n\n\n# Exercise: knapsack\n\n### Correctness\n- In `pack(int i)` verwendest du `for(; i <= maxN; i++)` und veränderst dabei den Parameter `i`: `i` steht aber für den **Index des Gegenstands** (0..weights.length-1) und nicht für die Anzahl Kopien; damit überspringst du Gegenstände bzw. brichst die Rekursion falsch ab.\n- Durch `loadItem(i)` innerhalb dieser Schleife wird mit `i` teilweise auf `weights[i]`/`values[i]` zugegriffen, obwohl `i` dort Werte bis `maxN` annehmen kann; sobald `maxN >= weights.length` (oder auch einfach, wenn `i` nicht mehr ein gültiger Item-Index ist), führt das zu einem **ArrayIndexOutOfBounds** bzw. falschen Berechnungen.\n- Du prüfst die Gewichtsgrenze (`currWeight <= maxWeight`) nur im Basisfall `i == weights.length`. Dadurch werden auch Zustände weiter erkundet, die das Maximalgewicht schon längst überschreiten, und das kann die Logik verfälschen (und macht es sehr ineffizient).\n- Mit deinem `unloadItem(i)` machst du pro Rekursionsschritt nur **ein** Item rückgängig. Wenn du ein Item mehrmals lädst (für „n-mal mitnehmen“), muss beim Backtracking auch wieder der passende Zustand hergestellt werden (sonst bleibt Gewicht/Wert „hängen“ oder wird zu wenig zurückgenommen).\n\n### Suggestion\n- Trenne gedanklich zwei Dinge: **welcher Gegenstand** ist dran (Index `i`) und **wie viele Kopien** dieses Gegenstands du einpackst (eine eigene Zählvariable, z.B. `n`), und vermische diese Rollen nicht in derselben Schleifenvariable.\n- Baue die Rekursion so auf, dass du für einen festen Gegenstand `i` alle erlaubten Anzahlen (0 bis `maxN`) ausprobierst und **danach** zu `i+1` weitergehst.\n- Füge eine Abbruch-/Pruning-Bedingung ein: Sobald `currWeight > maxWeight`, solltest du diesen Pfad nicht weiter verfolgen.\n- Achte beim Backtracking darauf, dass der Zustand nach dem Ausprobieren wieder exakt so ist wie davor (wenn du etwas mehrfach „lädst“, musst du es auch mehrfach oder entsprechend zusammengefasst wieder „entladen“).\n\n### Code Style\n- Entferne die vielen `System.out.println(...)` Debug-Ausgaben (oder ersetze sie durch sauberes Logging, falls erlaubt), sonst werden Tests unnötig „zugemüllt“.\n- In `pack(int i)` ist die Schleife `for(; i <= maxN; i++)` schwer lesbar und fehleranfällig, weil sie den Methodenparameter verändert; nutze dafür eine eigene Schleifenvariable.\n- Benenne Methoden konsistent (z.B. `packItem/unpackItem` statt `loadItem/unloadItem`), damit klarer ist, dass es um den Knapsack-Zustand geht.\n\n\n# Exercise: sudoku\n\n### Correctness\n- In `SudokuSolverImpl.solved(SudokuModel model, int fieldNr)` ist noch keine Backtracking-Logik implementiert und die Methode liefert immer `false`, dadurch kann das Sudoku nie als gelöst zurückgegeben werden.\n- In `SudokuSolverImpl.nofSolutions(SudokuModel model, int fieldNr, int max)` ist noch keine Zähl-Logik implementiert und die Methode liefert immer `0`, dadurch werden nie Lösungen gezählt.\n- In `Sudoku.java` ist die `main`-Methode nicht als Java-Startpunkt definiert (`public static void main(String[] args)` fehlt), dadurch startet die Applikation nicht wie erwartet.\n\n### Suggestion\n- Für `solved(..., fieldNr)`: Überlege dir eine klare Rekursions-Verankerung (wann bist du “fertig”?), und wie du aus `fieldNr` die Koordinaten `(i,j)` berechnest, um Feld für Feld durchzugehen. Für leere Felder probierst du Werte 1..size und prüfst nach jedem Setzen mit dem `checker`, ob der aktuelle Teilzustand noch gültig ist; falls nicht oder falls die Rekursion scheitert, musst du das Feld wieder zurücksetzen (Backtracking).\n- Für `nofSolutions(..., fieldNr, max)`: Nutze dieselbe Feld-Iteration wie beim Lösen, aber statt beim ersten Fund aufzuhören, summierst du die Ergebnisse der rekursiven Aufrufe. Achte darauf, dass du den `max`-Grenzwert wirklich als Abbruchkriterium benutzt (z.B. sobald du genug Lösungen gefunden hast) und dass du nach dem Durchprobieren eines Feldes das Feld wieder leer machst.\n- Für `Sudoku.java`: Prüfe die exakte Methodensignatur, die die JVM als Einstiegspunkt erkennt. Sobald die stimmt, sollte die GUI überhaupt erst starten.\n\n### Code Style\n- Die `// TODO implement`-Platzhalter sind ok während der Arbeit, aber sobald du die Methoden implementierst, entferne sie (oder ersetze sie durch kurze, aussagekräftige Kommentare zur Rekursionsidee/Verankerung).\n- In `Sudoku.java` fehlt der `public static`-Teil der `main`-Methode; auch wenn das primär “Correctness” ist, ist es in Java-Konventionen sehr stark standardisiert und sollte exakt so geschrieben werden.\n\n\n# Exercise: queens\n\nLlm Evaluation ist für diese Aufgabe deaktiviert. Entferne die .llmignore Datei vom Package der Aufgabe.\n",
    "status" : "SUCCESS"
  },
  "unitTest" : {
    "tests" : [ {
      "name" : "allZero()",
      "status" : "PASSED",
      "message" : null
    }, {
      "name" : "uselessStuff()",
      "status" : "PASSED",
      "message" : null
    }, {
      "name" : "random1()",
      "status" : "FAILED",
      "message" : "expected: <190> but was: <174>"
    }, {
      "name" : "random2()",
      "status" : "FAILED",
      "message" : "expected: <340> but was: <0>"
    }, {
      "name" : "random3()",
      "status" : "FAILED",
      "message" : null
    }, {
      "name" : "boardIsValidAfterSolveN4()",
      "status" : "FAILED",
      "message" : "Board must contain exactly N queens ==> expected: <4> but was: <0>"
    }, {
      "name" : "boardIsValidAfterSolveN5()",
      "status" : "FAILED",
      "message" : "Board must contain exactly N queens ==> expected: <5> but was: <0>"
    }, {
      "name" : "boardIsValidAfterSolveN8()",
      "status" : "FAILED",
      "message" : "Board must contain exactly N queens ==> expected: <8> but was: <0>"
    }, {
      "name" : "boardSizeIsCorrectForN4()",
      "status" : "PASSED",
      "message" : null
    }, {
      "name" : "boardSizeIsCorrectForN8()",
      "status" : "PASSED",
      "message" : null
    }, {
      "name" : "countN1()",
      "status" : "FAILED",
      "message" : "N=1 has exactly 1 solution ==> expected: <1> but was: <0>"
    }, {
      "name" : "countN2()",
      "status" : "PASSED",
      "message" : null
    }, {
      "name" : "countN3()",
      "status" : "PASSED",
      "message" : null
    }, {
      "name" : "countN4()",
      "status" : "FAILED",
      "message" : "N=4 has exactly 2 solutions ==> expected: <2> but was: <0>"
    }, {
      "name" : "countN5()",
      "status" : "FAILED",
      "message" : "N=5 has exactly 10 solutions ==> expected: <10> but was: <0>"
    }, {
      "name" : "countN6()",
      "status" : "FAILED",
      "message" : "N=6 has exactly 4 solutions ==> expected: <4> but was: <0>"
    }, {
      "name" : "countN8()",
      "status" : "FAILED",
      "message" : "N=8 has exactly 92 solutions ==> expected: <92> but was: <0>"
    }, {
      "name" : "solveReturnsTrueForN1()",
      "status" : "FAILED",
      "message" : "N=1 has exactly one solution ==> expected: <true> but was: <false>"
    }, {
      "name" : "solveReturnsTrueForN4()",
      "status" : "FAILED",
      "message" : "N=4 has valid queen placements ==> expected: <true> but was: <false>"
    }, {
      "name" : "solveReturnsTrueForN8()",
      "status" : "FAILED",
      "message" : "N=8 has valid queen placements ==> expected: <true> but was: <false>"
    }, {
      "name" : "solveReturnsFalseForN2()",
      "status" : "PASSED",
      "message" : null
    }, {
      "name" : "solveReturnsFalseForN3()",
      "status" : "PASSED",
      "message" : null
    } ]
  }
}