{
"llm" : {
"feedback" : "# Exercise: fractal\n\n### Correctness\n- In `Triangles.drawRec` zeichnest du im rekursiven Fall (`n > 0`) nur **ein** Unterdreieck; gefordert ist aber die rekursive Zerlegung in **mehrere** Teildreiecke (das typische Fraktal entsteht sonst nicht).\n- In `Triangles.drawRec` verwendest du im rekursiven Schritt Koordinaten, die nicht konsistent aus den drei Seiten-Mittelpunkten gebildet werden (z.B. mischst du `y1` als festen Wert mit berechneten Mittelpunkten). Dadurch entspricht die Rekursion nicht der beabsichtigten Aufteilung des Ausgangsdreiecks.\n\n### Suggestion\n- Überlege dir für das Dreieck zuerst die **drei Mittelpunkte** der Kanten (zwischen (x0,y0)-(x1,y1), (x0,y0)-(x2,y2), (x1,y1)-(x2,y2)). Wenn du diese drei Punkte hast, kannst du daraus die kleineren Dreiecke zusammensetzen.\n- Prüfe im rekursiven Fall, welche **drei** Dreiecke du weiterzeichnen willst (z.B. oben, unten-links, unten-rechts) und mache dafür pro Teildreieck einen rekursiven Aufruf mit `n-1`.\n- Achte darauf, dass jeder rekursive Aufruf wieder ein korrektes Dreieck (3 Punkte) bekommt, die tatsächlich die Ecken dieses Teildreiecks sind (nicht einzelne alte y-Werte “stehen lassen”).\n\n### Code Style\n- In `Triangles.drawRec` steht noch ein `// TODO implement` Kommentar, obwohl du bereits Code geschrieben hast – entferne/aktualisiere solche TODOs, damit klar ist, was noch fehlt.\n- In `Boxes.drawRec` sind die Kommentare teils hilfreich, aber die Reihenfolge der Aufrufe ist etwas “durcheinander”; eine einheitliche Struktur (z.B. immer TL, TR, BR, BL) macht das leichter lesbar.\n\n\n# Exercise: knapsack\n\n### Correctness\n- `pack(int i)` ist nicht implementiert, damit wird keine Kombination durchsucht und `solve()` liefert immer `0` statt des optimalen Werts.\n- `loadItem(int i)` und `unloadItem(int i)` sind nicht implementiert; ohne korrektes (Ent-)Laden der Gegenstände kann die „n-mal mitnehmen“-Anforderung nicht erfüllt werden.\n- In `KnapsackN` ist `main()` ohne Parameter definiert (`static void main()`); als Java-Startpunkt wird üblicherweise `static void main(String[] args)` erwartet.\n\n### Suggestion\n- Überlege dir für `pack(i)` eine Rekursion/Backtracking-Struktur: an Index `i` entweder den Gegenstand 0-mal nehmen oder 1-mal, 2-mal, … bis `maxN`-mal, und danach jeweils mit `i+1` weitermachen.\n- Achte darauf, wann du `maxValue` aktualisierst: typischerweise dann, wenn du am Ende der Gegenstandsliste angekommen bist (oder keine weitere Entscheidung mehr kommt) und das Gewicht noch innerhalb von `maxWeight` liegt.\n- Plane das „Rückgängig machen“ sauber: Wenn du in einer Schleife bis zu `maxN`-mal lädst, musst du danach auch genau die geladene Anzahl wieder entladen, damit der Zustand (`currWeight`, `currValue`) für den nächsten Ast stimmt.\n- Wenn deine Tests/Umgebung `main` ausführen sollen: passe die Signatur so an, dass sie von der JVM als Einstieg erkannt wird.\n\n### Code Style\n- Die TODO-Methoden sind aktuell leer; solange du sie nicht nutzt, wirken sie wie Platzhalter—entweder implementieren und verwenden oder (falls du anders löst) entfernen, damit die Klasse schlanker bleibt.\n- Benennung ist inkonsistent zum üblichen Paar „pack/unpack“ (du hast `loadItem/unloadItem`), das ist nicht falsch, aber achte darauf, die Begriffe konsequent zu verwenden (auch im `pack`-Algorithmus), damit die Logik leichter nachvollziehbar bleibt.\n\n\n# Exercise: queens\n\n### Correctness\n- `QueensSolver.solve()` ist nicht implementiert und liefert immer `false`, damit wird keine Lösung gesucht/gefunden und das Board bleibt leer.\n- `QueensSolver.count()` ist nicht implementiert und liefert immer `0`, damit wird die Anzahl Lösungen nicht gezählt.\n- In `Queens.java` ist `main()` nicht als Einstiegspunkt lauffähig (nicht `static` und ohne `String[] args`), d.h. das Programm startet so typischerweise nicht über die JVM-Standard-Konvention.\n\n### Suggestion\n- Für `solve()`: Du brauchst eine Backtracking-Strategie, die zeilenweise vorgeht: in einer Zeile eine Spalte ausprobieren, mit `checkPlacement` prüfen, Queen setzen, rekursiv nächste Zeile lösen, und bei Misserfolg wieder entfernen (Backtrack).\n- Für `count()`: Sehr ähnlich wie `solve()`, aber statt beim ersten Fund abzubrechen, sammelst du über alle gültigen Platzierungen die Anzahl Lösungen aus den Rekursionsaufrufen und gibst die Summe zurück; auch hier nach jedem Versuch wieder zurücksetzen.\n- Für `main()`: Orientiere dich an der üblichen Java-Signatur für den Programmeinstieg, damit du dein `solve()`/`count()` überhaupt testen kannst.\n\n### Code Style\n- In `QueensSolver.solve()` und `count()` stehen noch `// TODO implement`-Platzhalter; sobald du implementierst, entferne die TODOs oder ersetze sie durch sinnvolle Kommentare.\n- In `getBoard()` ist `return this.board;` okay, aber innerhalb derselben Klasse ist `this.` nicht nötig, wenn kein Namenskonflikt besteht; konsistente Verwendung hilft der Lesbarkeit.\n\n\n# Exercise: sudoku\n\n### Correctness\n- In `SudokuSolverImpl.solved(SudokuModel model, int fieldNr)` ist noch nichts implementiert und es wird immer `false` zurückgegeben; damit wird nie ein Sudoku gelöst (Anforderung 2 nicht erfüllt).\n- In `SudokuSolverImpl.nofSolutions(SudokuModel model, int fieldNr, int max)` ist noch nichts implementiert und es wird immer `0` zurückgegeben; damit werden Lösungen nie gezählt (Anforderung 4 nicht erfüllt).\n- In `Sudoku.java` ist `main()` nicht `public static void main(String[] args)`; so startet die Applikation in Java nicht wie erwartet (GUI wird nicht geöffnet).\n\n### Suggestion\n- Für `solved(...)`: Überlege dir eine Rekursions-/Backtracking-Struktur mit einer klaren Verankerung (wann bist du “fertig”?), und wie du aus `fieldNr` die Koordinaten `(i, j)` berechnest, um Feld für Feld durchs Grid zu laufen.\n- Für `solved(...)`: Wenn ein Feld bereits belegt ist (vorgegeben), sollte dein Algorithmus dort nichts ändern und direkt zum nächsten Feld gehen.\n- Für `solved(...)`: Wenn ein Feld leer ist, probiere nacheinander Werte `1..model.size()` aus, setze testweise, prüfe mit `checker.oneOK(model, i, j)` und gehe nur dann rekursiv weiter; wenn kein Wert passt, muss das Feld wieder geleert werden (Backtracking).\n- Für `nofSolutions(...)`: Nutze denselben Suchbaum wie beim Lösen, aber statt “beim ersten Treffer stoppen” musst du Treffer zählen; die Verankerung liefert dann typischerweise “eine gefundene Lösung”.\n- Für `nofSolutions(...)`: Achte darauf, dass du bei vielen Lösungen frühzeitig abbrechen kannst, indem du das `max`-Limit (bzw. “Restbudget”) in die Rekursion mitnimmst und nicht weiterzählst, sobald du genug hast.\n- Für `Sudoku.java`: Passe die Signatur von `main` so an, dass sie von der JVM als Einstiegspunkt erkannt wird.\n\n### Code Style\n- Die Datei enthält sehr viel unveränderten Template-/Boilerplate-Code; für die Abgabe wäre es übersichtlicher, nur die relevanten Änderungen (v.a. `SudokuSolverImpl`) anzufassen bzw. hervorzuheben.\n- In `Sudoku.java` fehlt der übliche `public static` Modifizierer bei `main`; auch wenn das primär funktional ist, ist es zugleich ein grundlegender Java-Konventionspunkt für Einstiegsklassen.\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: <0>"
}, {
"name" : "random2()",
"status" : "FAILED",
"message" : "expected: <340> but was: <0>"
}, {
"name" : "random3()",
"status" : "FAILED",
"message" : "expected: <558> but was: <0>"
}, {
"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
} ]
}
}