{
"llm" : {
"feedback" : "# Exercise: fractal\n\n### Correctness\n- **Boxes:** Deine Rekursion terminiert für `n == 0` nicht korrekt (du brichst bei `n == 1` ab). Dadurch passt die Tiefe nicht zur Aufgabenstellung und bei `n == 0` würdest du sogar unendlich weiterrekursieren.\n- **Boxes:** In deinem ersten rekursiven Aufruf verwendest du wieder `(x, y, s)` statt die halbierte Größe zu verwenden. Damit verkleinerst du das Problem nicht in allen Ästen und die Rekursion arbeitet nicht wie beabsichtigt.\n- **Triangles:** Du brichst bei `n == 1` ab, statt bei `n == 0` den Basisfall zu zeichnen. Für `n == 0` würdest du außerdem weiterrekursieren (Problem wie oben).\n- **Triangles:** Du zeichnest die Linien in jedem Rekursionsschritt (auch bei `n > 0`). In der typischen Rekursionsstruktur der Aufgabe wird im Basisfall gezeichnet und sonst nur weiter unterteilt; so wie du es hast, stimmen die resultierenden Muster/Überlagerungen nicht zur geforderten rekursiven Form.\n- **Circles:** Die Aufgabe verlangt nur die Implementierung von `Boxes` und `Triangles`. Deine Änderungen/Implementierung von `Circles` sind dafür nicht erforderlich (und wirken zudem unvollständig).\n\n### Suggestion\n- **Boxes:** Überlege dir einen klaren Basisfall: Welche `n`-Stufe soll wirklich „nur ein Rechteck zeichnen“ bedeuten? Teste explizit `n = 0` und `n = 1` im Kopf und verfolge, ob danach noch rekursive Aufrufe passieren.\n- **Boxes:** Prüfe bei jedem rekursiven Aufruf: Werden `s` und/oder die Koordinaten so angepasst, dass das Teilproblem kleiner ist? Wenn ein Ast wieder mit derselben Größe startet, kommst du dem Abbruch nicht näher.\n- **Triangles:** Lege fest: „Bei welcher Tiefe zeichne ich genau ein Dreieck?“ und „Wann teile ich nur auf?“. Das hilft, das Zeichnen nicht auf allen Ebenen zu machen.\n- **Triangles:** Kontrolliere deine drei rekursiven Aufrufe: Jeder sollte ein echtes Teil-Dreieck definieren, dessen Eckpunkte aus den Mittelpunkten der Kanten (und/oder Originalpunkten) bestehen. Zeichne dir die Punkte (oben, links unten, rechts unten + Mittelpunkte) kurz auf Papier und ordne dann die drei Sub-Dreiecke zu.\n- **Circles:** Wenn du `Circles` drin lässt: Achte darauf, dass `Math.sin/cos` Radiant erwarten (nicht Grad). Rechne Winkel ggf. um, sonst liegen die Kindkreise nicht da, wo du sie erwartest.\n\n### Code Style\n- - In `Boxes`, `Triangles`, `Circles`: Entferne auskommentierte Codeblöcke, sobald du dich entschieden hast – das erschwert das Lesen.\n- - `Point.java` wird nirgends verwendet → entfernen, sonst wirkt es wie „toter Code“.\n- - `Circles`: viele temporäre Variablen (`newr`, `newry`, `newx`, `newy`) sind teils ungenutzt oder irreführend benannt; bessere, konsistente Namen würden die Geometrie nachvollziehbarer machen.\n- - Allgemein: Verwende konsistente Basisfall-Checks (`n == 0` vs. `n == 1`) in allen Shapes, damit das Verhalten von `n` einheitlich bleibt.\n\n\n# Exercise: knapsack\n\n### Correctness\n- Du begrenzt die Rekursion mit `if (i >= maxN) return;` – `i` steht aber für den Index des Gegenstands (0..weights.length-1) und nicht für die Anzahl, wie oft ein Gegenstand genommen werden darf. Damit werden nicht alle Gegenstände betrachtet und das Ergebnis wird falsch.\n- In `pack` fehlt die Prüfung `currWeight <= maxWeight` vor weiteren Rekursionsschritten bzw. bevor du `maxValue` aktualisierst; dadurch können Lösungen mit zu hohem Gewicht als Optimum gezählt werden.\n- Dein Ablauf nimmt jeden Gegenstand höchstens **einmal** (load → pack → unload). Die Anforderung ist aber, dass jeder Gegenstand bis zu **maxN-mal** gewählt werden kann.\n- Die Abbruchbedingung für „keine Gegenstände mehr“ ist bei dir nicht an `weights.length`/`values.length` gekoppelt (du prüfst nur auf leere Arrays). Wenn `i` irgendwann außerhalb der Array-Länge landet, riskierst du einen Zugriff außerhalb des Bereichs (und es gibt auch keinen korrekten „Basisfall“, der dann `maxValue` aktualisiert).\n- `values.length == 0 && weights.length == 0` ist als Abbruchbedingung zu streng: Wenn eins der Arrays leer wäre, würdest du trotzdem weiterlaufen (und dann sicher abstürzen). (Auch wenn Tests das evtl. nicht füttern, ist es logisch inkonsistent.)\n\n### Suggestion\n- Überlege dir, welche Bedeutung `i` in der Rekursion haben soll: typischerweise „welchen Gegenstand betrachte ich gerade?“ → Abbruch, wenn `i` die Anzahl Gegenstände erreicht, nicht wenn `i == maxN`.\n- Baue die Auswahl pro Gegenstand so, dass du **0, 1, 2, …, maxN** Exemplare desselben Gegenstands ausprobieren kannst, bevor du zum nächsten Gegenstand weitergehst.\n- Setze eine Gewichtskontrolle ein: Sobald `currWeight` größer als `maxWeight` ist, solltest du diesen Zweig nicht weiterverfolgen und ihn auch nicht zur `maxValue`-Berechnung zulassen.\n- Definiere einen sauberen Basisfall: „alle Gegenstände behandelt“ → dann (und nur dann) Optimum vergleichen/aktualisieren, sofern das Gewicht passt.\n- Wenn du pro Gegenstand mehrfach lädst, achte darauf, dass das „Zurücksetzen“ beim Backtracking die **gleiche Anzahl** wieder entfernt, die du in diesem Pfad hinzugefügt hast.\n\n### Code Style\n- Die Kommentare `// TODO implement` sind noch vorhanden, obwohl implementiert wurde – entweder entfernen oder durch passende Kommentare ersetzen.\n- Die Prüfung auf leere Arrays in jeder Rekursion ist unnötig teuer und macht die Logik unübersichtlicher; solche Vorbedingungen passen eher in den Konstruktor oder `solve()`.\n- Verwende für Zustandsupdates kürzere Operatoren (`+=`, `-=`), das verbessert Lesbarkeit.\n\n\n# Exercise: sudoku\n\n### Correctness\n- In `Sudoku.java` ist `main()` nicht als `public static void main(String[] args)` deklariert; so startet das Programm in Java nicht über den Standard-Einstiegspunkt.\n- `nofSolutions(...)` erfüllt die Anforderung “zählt die Anzahl Lösungen (bis MAX) und setzt das Modell wieder zurück” nicht: Du setzt `max = 0` direkt am Anfang und nutzt den Parameter damit nicht mehr als Abbruchgrenze.\n- `nofSolutions(...)` ruft rekursiv `solved(...)` statt `nofSolutions(...)` auf; damit wird nicht die Anzahl Lösungen gezählt, sondern (bestenfalls) nur versucht eine Lösung zu finden.\n- In `nofSolutions(...)` wird im Fall `model.get(row,col) != 0` das Ergebnis des rekursiven Aufrufs ignoriert und es fehlt ein `return` (du gibst am Ende `max` zurück, das wegen `max=0` praktisch immer 0 bleibt).\n- In `nofSolutions(...)` ist die Bedingung `if(fieldNr == 81)` innerhalb des Loops unerreichbar, weil du in diesem Block bereits im “sonst”-Zweig bist, in dem `fieldNr` gerade *nicht* 81 ist (die Abbruchbedingung wird oben schon abgefangen).\n- `solved(...)` verwendet fixe Werte (`81`, `9`) statt `model.size()`; falls die Vorlage andere Größen zulässt, ist das nicht korrekt zur Schnittstelle.\n\n### Suggestion\n- Schau dir beim Startproblem die Signatur von `main` an: Java findet den Einstiegspunkt nur, wenn er exakt `public static void main(String[] args)` ist.\n- Für das Zählen von Lösungen brauchst du eine Rekursion, die **nicht** beim ersten Fund abbricht, sondern alle gültigen Fortsetzungen durchgeht und deren Treffer aufsummiert; überlege dir, was deine Rekursion beim “letztes Feld erreicht” zurückgeben soll.\n- Verwende den `max`-Parameter als “Restbudget”: Wenn du schon `n` Lösungen gefunden hast, kannst du an den rekursiven Aufruf ein kleineres Rest-`max` weitergeben und abbrechen, sobald das Budget aufgebraucht ist.\n- Achte darauf, dass du in `nofSolutions` in jedem Pfad einen sinnvollen Rückgabewert lieferst (v.a. beim Fall “Feld ist vorgegeben”).\n- Prüfe deine Abbruchbedingungen: Wenn du ganz am Anfang `fieldNr == size*size` behandelst, brauchst du später keine extra Prüfung auf `fieldNr == 81` mehr in tieferen Blöcken.\n- Falls du allgemein bleiben willst: berechne `row/col` und die Endbedingung mit `model.size()` statt mit 9/81.\n\n### Code Style\n- Entferne die vielen `System.out.println(...)` Debug-Ausgaben aus der Rekursion; das macht die Ausgabe extrem noisy und bremst den Solver stark.\n- Benenne Variablen konsistent (z.B. `row/col` statt einmal `i/j`, einmal `row/col`) und vermeide “Magische Zahlen” wie `9` und `81`.\n- In `nofSolutions` wird der Parameter `max` überschrieben (`max=0`), was sehr verwirrend ist; nutze lieber eine eigene Zählvariable für gefundene Lösungen.\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: <124>"
}, {
"name" : "random2()",
"status" : "FAILED",
"message" : "expected: <340> but was: <174>"
}, {
"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" : "PASSED",
"message" : null
}, {
"name" : "solveReturnsTrueForN4()",
"status" : "PASSED",
"message" : null
}, {
"name" : "solveReturnsTrueForN8()",
"status" : "FAILED",
"message" : "Connection refused to host: 172.25.0.6; nested exception is: \n\tjava.net.ConnectException: Connection refused"
}, {
"name" : "solveReturnsFalseForN2()",
"status" : "FAILED",
"message" : "N=2 has no valid queen placement ==> expected: <false> but was: <true>"
}, {
"name" : "solveReturnsFalseForN3()",
"status" : "FAILED",
"message" : "N=3 has no valid queen placement ==> expected: <false> but was: <true>"
} ]
}
}