{
"llm" : {
"feedback" : "# Exercise: fractal\n\n### Correctness\n- In `Triangles.drawRec` berechnest du beim zweiten rekursiven Aufruf den dritten Punkt als `((x1 + x2) / 2, y1)`. Das ist nicht der Mittelpunkt der Kante zwischen `(x1,y1)` und `(x2,y2)` (die y-Koordinate müsste auch von `y2` abhängen). Dadurch werden die Teil-Dreiecke geometrisch falsch platziert/verzerrt.\n- In `Triangles.drawRec` verwendest du dieselbe (falsche) y-Koordinate `y1` auch beim dritten Aufruf für den gemeinsamen Punkt `((x1 + x2) / 2, y1)`, was den Fehler weiterzieht und die Rekursion nicht das gewünschte Fraktal-Muster erzeugen lässt.\n\n### Suggestion\n- Überlege dir für das Dreiecks-Fraktal: Du brauchst die Mittelpunkte **aller drei** Seiten des aktuellen Dreiecks. Ein Mittelpunkt entsteht immer aus dem Durchschnitt **beider** Endpunkte der Seite (also x *und* y separat mitteln).\n- Wenn du die drei Mittelpunkte hast, zeichnest du rekursiv die drei „Eck“-Dreiecke (oben, unten links, unten rechts). Prüfe dabei für jeden rekursiven Call, dass seine drei Punkte tatsächlich die Ecken eines der drei kleinen Dreiecke sind (und nicht ein Punkt „auf Höhe y1“ festgenagelt ist).\n\n### Code Style\n- In `Triangles.drawRec` sind die Mittelpunkt-Berechnungen direkt in die Argumente der rekursiven Calls „eingebacken“. Das macht es schwer zu kontrollieren und begünstigt genau solche Koordinatenfehler. Lesbarer wäre es, die Mittelpunkte einmal in Variablen zu berechnen und dann zu verwenden.\n- In `Boxes.drawRec` ist die Reihenfolge der rekursiven Aufrufe gemischt und teils kommentiert (rechts/links). Funktional ok, aber konsistenter (z.B. im Uhrzeigersinn) wäre leichter nachzuvollziehen.\n\n\n# Exercise: knapsack\n\n1. Correctness \n- In `pack(int i)` rufst du innerhalb der `for (int j = 0; j <= maxN; j++)`-Schleife `pack(i + 1)` auf, bevor du (für `j < maxN`) das Item lädst. Dadurch wird der Fall „j-mal genommen“ nicht sauber als „erst j-mal laden, dann rekursiv weiter“ abgebildet, sondern eher „immer weiterrekursieren, und erst danach Zustand verändern“. Das kann dazu führen, dass gewisse Kombinationen nicht oder nicht wie gedacht bewertet werden. \n- Du entlädst am Ende immer genau `maxN`-mal (`for (int j = 0; j < maxN; j++) unloadItem(i);`), unabhängig davon, wie oft du das Item tatsächlich geladen hast. Das macht den Backtracking-Zustand fragil (bei Änderungen im Schleifenablauf oder frühem Abbruch) und ist logisch nicht an die tatsächliche Anzahl `loadItem` gekoppelt.\n\n2. Suggestion \n- Überlege dir für Item `i` eine klare Reihenfolge: „0-mal nehmen → recurse“, „1-mal nehmen → recurse“, … „maxN-mal nehmen → recurse“. Prüfe, ob deine aktuelle Reihenfolge (recurse vor load) genau diese Zustände erzeugt. \n- Koppel das „Aufräumen“ (unload) direkt an die Anzahl, die du wirklich geladen hast. Ein guter Check: Nach dem gesamten Block für ein bestimmtes `i` sollten `currWeight`/`currValue` garantiert wieder exakt den Wert haben wie direkt beim Eintritt in `pack(i)`.\n\n3. Code Style \n- `Logger log` wird nirgends verwendet; das ist unnötiger Ballast und sollte entfernt werden, falls du nicht loggst. \n- In `loadItem`/`unloadItem` kannst du mit `+=`/`-=` arbeiten, das erhöht die Lesbarkeit.\n\n\n# Exercise: queens\n\n### Correctness\n- `QueensSolver.solve()` ist nicht implementiert und liefert immer `false`, damit wird keine Lösung gesucht/platziert.\n- `QueensSolver.count()` ist nicht implementiert und liefert immer `0`, damit wird die Anzahl Lösungen nicht gezählt.\n\n### Suggestion\n- Für `solve()`: Überlege dir eine rekursive Backtracking-Funktion, die zeilenweise vorgeht: in jeder Zeile eine Spalte ausprobieren, mit `checkPlacement` prüfen, Dame setzen, nächste Zeile lösen, und bei Fehlschlag die Dame wieder entfernen (Backtracking).\n- Für `count()`: Ähnlicher Ablauf wie bei `solve()`, aber statt beim ersten Fund abzubrechen, summierst du alle gültigen vollständigen Platzierungen (Basisfall: wenn alle Zeilen belegt sind, zählt das als 1 Lösung), und nach jedem rekursiven Versuch wieder “zurückbauen” (Dame entfernen).\n\n### Code Style\n- In `Queens.java` ist `main()` nicht als Java-Entry-Point definiert (`static void main(String[] args)` fehlt); so wird das Programm typischerweise nicht startbar sein.\n- In `getBoard()` ist `return this.board;` ok, aber im Rest der Vorlage wird meist ohne `this` gearbeitet—einheitlich halten wäre lesbarer.\n\n\n# Exercise: sudoku\n\n### Correctness\n- In `SudokuSolverImpl`, `solved(SudokuModel model, int fieldNr)` ist nicht implementiert und gibt immer `false` zurück; damit wird kein Sudoku gelöst.\n- In `SudokuSolverImpl`, `nofSolutions(SudokuModel model, int fieldNr, int max)` ist nicht implementiert und gibt immer `0` zurück; damit wird die Anzahl Lösungen nie korrekt gezählt.\n- In `Sudoku.java` ist die `main`-Methode nicht als `public static void main(String[] args)` deklariert; so startet das Programm (und damit die GUI) typischerweise nicht.\n\n### Suggestion\n- Für `solved(...)`: Überlege dir eine Backtracking-Rekursion über eine lineare Feldnummer (`fieldNr` von 0 bis `size()*size()-1`) und definiere eine klare Verankerung (wann bist du fertig?). Prüfe für jedes Feld: wenn es schon belegt ist, gehe einfach zum nächsten; wenn es leer ist, probiere Werte `1..size()` und nutze `checker.oneOK(model, i, j)` bevor du tiefer gehst. Wenn kein Wert passt, musst du beim Zurückgehen das Feld wieder leeren.\n- Für `nofSolutions(...)`: Die Struktur ist fast identisch zu `solved`, aber statt beim ersten Erfolg abzubrechen, addierst du die Anzahl gefundener Lösungen. Achte darauf, das `max`-Limit zu berücksichtigen (z.B. indem du beim rekursiven Aufruf nur noch das “Restbudget” weitergibst und Schleifen abbrichst, sobald du genug hast) und dass du beim Backtracking das Feld wieder zurücksetzt.\n- Für `Sudoku.java`: Passe die Signatur von `main` so an, dass die JVM sie als Einstiegspunkt erkennt (public/static/args), sonst wird dein Solver nie über die GUI aufgerufen.\n\n### Code Style\n- Entferne die `// TODO implement`-Kommentare bzw. ersetze sie durch sinnvolle Kommentare, sobald du implementierst, damit klar ist, welche Backtracking-Schritte (Verankerung, Rekursion, Backtracking) wo passieren.\n",
"status" : "SUCCESS"
},
"unitTest" : {
"tests" : [ {
"name" : "allZero()",
"status" : "FAILED",
"message" : "Error occurred in server thread; nested exception is: \n\tjava.lang.NoClassDefFoundError: org/slf4j/LoggerFactory"
}, {
"name" : "uselessStuff()",
"status" : "FAILED",
"message" : "Error occurred in server thread; nested exception is: \n\tjava.lang.NoClassDefFoundError: org/slf4j/LoggerFactory"
}, {
"name" : "random1()",
"status" : "FAILED",
"message" : "Error occurred in server thread; nested exception is: \n\tjava.lang.NoClassDefFoundError: org/slf4j/LoggerFactory"
}, {
"name" : "random2()",
"status" : "FAILED",
"message" : "Error occurred in server thread; nested exception is: \n\tjava.lang.NoClassDefFoundError: org/slf4j/LoggerFactory"
}, {
"name" : "random3()",
"status" : "FAILED",
"message" : "Error occurred in server thread; nested exception is: \n\tjava.lang.NoClassDefFoundError: org/slf4j/LoggerFactory"
}, {
"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
} ]
}
}