{
"llm" : {
"feedback" : "# Exercise: fractal\n\n### Correctness\n- In `Boxes.drawRec` zeichnest du bei `n == 0` gar kein Quadrat (weil dein `if (n != 0)` dann nicht ausgeführt wird). Damit fehlt der Basisfall komplett, und bei kleinen Rekursionstiefen kommt ggf. gar nichts raus.\n- In `Boxes.drawRec` fehlt ein rekursiver Aufruf für das unten-links-Quadrat; du zeichnest nur oben-links, oben-rechts und unten-rechts rekursiv.\n- In `Triangles.drawRec` ist der Basisfall ebenfalls vertauscht: Du zeichnest nur, wenn `n > 0`, bei `n == 0` wird nichts gezeichnet. Damit endet die Rekursion zwar, aber ohne das “kleinste” Dreieck zu zeichnen.\n- In `Triangles.drawRec` wirken die berechneten Punkte für die Unterdreiecke teilweise nicht wie die echten Mittelpunkte der Seiten (z.B. verwendest du bei einem Punkt `y2` direkt statt den Mittelpunkt zwischen `y1` und `y2`). Dadurch entsteht sehr wahrscheinlich nicht die geforderte Sierpinski-ähnliche Zerlegung in drei gleichartige Teildreiecke.\n\n### Suggestion\n- Überlege dir bei beiden Formen einen klaren Basisfall: “Wann zeichne ich genau *ein* Element (Quadrat/Dreieck) und wann teile ich weiter auf?” – und setze die Bedingung entsprechend (typischerweise `n == 0` zeichnet, sonst teilt).\n- Prüfe bei den Boxes die vier Teilquadranten systematisch: Wenn du die Seitenlänge halbierst, welche `(x,y)`-Offsets brauchst du für oben-links, oben-rechts, unten-rechts **und** unten-links?\n- Bei den Triangles: Berechne zuerst sauber die drei Seitenmittelpunkte (jeweils Mittelwert der beiden Endpunkte). Verwende dann diese Mittelpunkte, um exakt drei kleinere Dreiecke zu definieren (oben, unten-links, unten-rechts).\n- Kontrolliere bei jedem rekursiven Aufruf, ob die übergebenen drei Punkte wirklich ein Teildreieck des ursprünglichen Dreiecks sind (und nicht z.B. zwei Punkte auf einer falschen Höhe/mit falschem y-Wert).\n\n### Code Style\n- In `Triangles.drawRec` ist der Kommentar `// use g.drawLine(...)...` am Ende irreführend platziert, weil dort keine Zeichenlogik mehr kommt; pack solche Hinweise eher direkt an die relevante Stelle oder entferne sie, wenn du es schon umgesetzt hast.\n- In `Boxes.drawRec` wäre eine explizite `if/else`-Struktur (Basisfall vs. Rekursionsfall) lesbarer als nur `if (n != 0)`, weil man sofort erkennt, was bei `n == 0` passieren soll.\n\n\n# Exercise: knapsack\n\n### Correctness\n- In `pack(...)` benutzt du im `while` fest `n <= 3` statt den übergebenen/konfigurierten Wert `maxN`; damit funktioniert es nur zufällig für `maxN == 3`, aber nicht allgemein für andere Werte.\n- Deine Schleifenlogik zählt effektiv nur die Fälle „0-mal“ und „maxN-mal“ (hier 3-mal) pro Item sauber durch; die Zwischenfälle (z.B. 1x oder 2x) werden nicht als eigene finale Kombinationen bewertet, weil das Update von `maxValue` nur im Basisfall `i == values.length` passiert.\n\n### Suggestion\n- Ersetze die harte Grenze in der `while`-Bedingung durch etwas, das wirklich von `maxN` (dem Feld oder Parameter) abhängt, damit die Implementierung für beliebige `maxN` korrekt skaliert.\n- Überlege dir beim Rekursionsbaum: Für jedes Item solltest du systematisch alle Anzahlen von `0..maxN` ausprobieren und jeweils danach mit `i+1` weitergehen. Prüfe, ob deine aktuelle Reihenfolge aus „erst pack(i+1)“ und dann „mehrfach loadItem + pack(i+1)“ wirklich alle Fälle abdeckt, bevor du am Ende wieder „unloadest“. Eine gute Kontrolle ist: Wird der Zustand für 1x und 2x Mitnehmen jemals im Basisfall (oder an einer Stelle, wo du `maxValue` aktualisierst) betrachtet?\n\n### Code Style\n- Die Parameter `n` und `maxN` in `pack(int i, int n, int maxN)` sind verwirrend, weil es bereits das Feld `maxN` gibt und du den Parameter `maxN` faktisch nicht nutzt; das macht die Methode schwerer verständlich.\n- `while (n <= 3)` ist ein „Magic Number“-Problem und erschwert Wartung/Lesbarkeit; die Grenze sollte aus einer benannten Konstante/Variable kommen.\n- In `KnapsackN` entspricht die `main()`-Signatur nicht dem üblichen `main(String[] args)` (wie in der Vorlage); je nach Test-/Runtime-Setup kann das dazu führen, dass das Programm nicht als Startklasse erkannt wird.\n\n\n# Exercise: sudoku\n\n### Correctness\n- In `nofSolutions`, the `max` parameter (and damit `SudokuSolver.MAX`) is not respected: you never stop counting once `solutions` reaches `max`, so the method can enumerate far more than the bound allows.\n- In `nofSolutions`, the model is not reliably reset to its initial state after counting: when `solutions > 0`, the field you just tried remains filled when returning, which violates the requirement “The model was reset to its initial state.”\n\n### Suggestion\n- Think about how to “spend” the remaining budget `max` during recursion: after you found some solutions in one branch, the next branches should only search for the remaining amount, and you should stop iterating guesses once you hit the limit.\n- Make sure every recursive attempt cleans up after itself: regardless of whether you found 0, 1, or many solutions under a guess, the cell you set should be cleared again before returning to the caller (i.e., backtracking must always undo assignments).\n\n### Code Style\n- Avoid hardcoding `9` and `80`; use `model.size()` and `model.size() * model.size()` so the solver works for other Sudoku sizes too and is self-explanatory.\n- The condition `if (solutions == 0) model.clear(i, j);` is a bit misleading because clearing should conceptually happen independent of the number of solutions found; restructuring to “set → recurse → clear” as a consistent pattern improves readability and reduces mistakes.\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" : "PASSED",
"message" : null
}, {
"name" : "random2()",
"status" : "FAILED",
"message" : "expected: <340> but was: <334>"
}, {
"name" : "random3()",
"status" : "FAILED",
"message" : "expected: <558> but was: <541>"
}, {
"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
} ]
}
}