AutoFeedback API

Result 65b7fa80-c02c-4d4c-ac8f-cea71212648f

{
  "llm" : {
    "feedback" : "# Exercise: fractal\n\n### Correctness\n- In `Triangles.drawRec` (Basisfall `n == 0`) zeichnest du die dritte Kante mit `g.drawLine(x0, y0, x2, y2)`; gefordert ist aber das vollständige Dreieck, also auch die Kante zwischen `(x2,y2)` und `(x0,y0)` in der richtigen Richtung (bei dir fehlt die Linie von `(x2,y2)` nach `(x0,y0)` und stattdessen zeichnest du nochmals von `x0` aus).\n- In `Triangles.drawRec` (rekursiver Fall) ist beim mittleren Teil-Dreieck ein Punkt nicht korrekt berechnet: du verwendest für den dritten Punkt `( (x1 + x2)/2, y1 )` statt den Mittelpunkt der Strecke zwischen `(x1,y1)` und `(x2,y2)` (also mit passendem `y`-Mittelwert). Dadurch wird das untere „Mittelpunkt“-Vertex falsch platziert und die Teil-Dreiecke werden geometrisch verzerrt.\n- In `Triangles.drawRec` (rekursiver Fall) verwendest du in zwei rekursiven Aufrufen `y1` direkt für einen Mittelpunkt-Punkt; wenn `y1` und `y2` unterschiedlich wären (allgemeiner Fall), wäre das falsch. Auch wenn es hier zufällig funktioniert, weil `y1 == y2 == 790`, ist die Implementierung damit nicht allgemein korrekt für die übergebenen Punkte.\n\n### Suggestion\n- Schau dir im Basisfall an, welche drei Kanten ein Dreieck wirklich hat: Du brauchst genau die Verbindungen `0-1`, `1-2` und `2-0`. Vergleiche das mit deinen drei `drawLine`-Aufrufen.\n- Berechne im rekursiven Fall die drei Mittelpunkte sauber als Mittelwerte der jeweiligen Endpunkte (für **x und y**). Wenn du dir die drei Seiten `(0-1)`, `(0-2)`, `(1-2)` einzeln notierst und jeweils den Mittelpunkt berechnest, wird klar, welche Koordinaten in die drei rekursiven Aufrufe gehören.\n- Prüfe deine rekursiven Aufrufe, indem du für jedes Teil-Dreieck explizit notierst, aus welchen drei Eckpunkten es bestehen soll (z.B. „oberes Dreieck: Spitze + zwei angrenzende Mittelpunkte“). Dann siehst du schnell, wo du aus Versehen `y1` statt eines berechneten Mittelpunkt-`y` verwendest.\n\n### Code Style\n- In `Triangles.drawRec` wiederholst du sehr oft Ausdrücke wie `(x1 + x0) / 2` und `(y0 + y1) / 2`; das wird deutlich lesbarer und weniger fehleranfällig, wenn du diese Mittelpunkte einmal in Variablen speicherst (wie `mid01x`, `mid01y`, …).\n- In `Boxes.drawRec` mischst du rekursives Zeichnen und direktes `g.drawRect` im Else-Zweig; das ist okay, aber für Konsistenz/Lesbarkeit könntest du entweder alles rekursiv oder alles direkt im Basisfall machen (und im rekursiven Fall nur rekursiv aufrufen).\n\n\n# Exercise: knapsack\n\n### Correctness\n- Du berücksichtigst `maxN` nicht: In `pack` kannst du jeden Gegenstand aktuell nur 0- oder 1-mal einpacken, nicht bis zu `n`-mal wie in der Aufgabenstellung gefordert.\n- Dadurch liefert deine Lösung für Fälle mit `maxN > 1` nicht das geforderte Optimum (Tests, die Mehrfachmitnahme prüfen, werden so typischerweise fehlschlagen).\n\n### Suggestion\n- Überlege dir in `pack(i)`, welche Möglichkeiten es pro Item geben muss: nicht nur „weglassen“ oder „einmal nehmen“, sondern „0, 1, 2, …, maxN-mal nehmen“. Das lässt sich gut als Schleife über die Anzahl Mitnahmen ausdrücken.\n- Achte darauf, dass dein Zurücksetzen (dein `unloadItem`) danach wieder exakt den Zustand vor dem Durchprobieren dieses Items herstellt. Wenn du ein Item mehrfach lädst, muss das Entladen entsprechend „alles, was du geladen hast“ wieder entfernen (nicht nur einmal).\n\n### Code Style\n- In `pack` steht noch der Kommentar `// TODO implement`, obwohl die Methode bereits implementiert ist; den kannst du entfernen, damit es nicht wie unvollständig wirkt.\n- In `loadItem`/`unloadItem` sind Ausdrücke wie `currWeight = currWeight + ...` korrekt, aber unnötig lang; kürzere Operatoren (`+=`, `-=`) verbessern 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/gefunden und das Board bleibt leer.\n- `QueensSolver.count()` ist nicht implementiert und liefert immer `0`, damit wird die Anzahl möglicher Lösungen nicht gezählt.\n- In `Queens.java` ist `main()` nicht als Einstiegspunkt nutzbar (nicht `static` und ohne `String[] args`), dadurch startet das Programm in der üblichen Java-Umgebung nicht wie erwartet.\n\n### Suggestion\n- Für `solve()`: Überlege dir eine rekursive Backtracking-Funktion, die zeilenweise (oder spaltenweise) vorgeht, pro Zeile eine Spalte ausprobiert, mit `checkPlacement(...)` prüft, die Dame setzt, rekursiv weitergeht und beim Fehlschlag wieder entfernt (Backtracking).\n- Für `count()`: Nutze eine sehr ähnliche Rekursion wie bei `solve()`, aber statt beim ersten Fund aufzuhören summierst du alle erfolgreichen vollständigen Platzierungen (Basisfall: „alle Zeilen gefüllt“ → 1 Lösung).\n- Für `main()`: Passe die Signatur so an, dass sie als Java-Startmethode erkannt wird; orientiere dich an der üblichen `public static void main(String[] args)`-Form.\n\n### Code Style\n- In `getBoard()` ist `return this.board;` zwar ok, aber im restlichen Code wird `board` ohne `this` verwendet—einheitlicher Stil wäre empfehlenswert.\n- Die `// TODO implement`-Kommentare sind ok während der Bearbeitung, sollten aber nach der Implementierung entfernt/ersetzt werden.\n\n\n# Exercise: sudoku\n\n### Correctness\n- `SudokuSolverImpl.solved(SudokuModel)` ist nicht implementiert (delegiert zwar an die private Methode, diese gibt aber immer `false` zurück), damit wird nie ein Sudoku gelöst.\n- `SudokuSolverImpl.nofSolutions(SudokuModel)` ist nicht implementiert (private Methode gibt immer `0` zurück), damit wird die Anzahl Lösungen immer als 0 gemeldet.\n- `Sudoku.main()` hat nicht die korrekte Java-Signatur als Einstiegspunkt (`public static void main(String[] args)`), dadurch startet die Applikation typischerweise nicht.\n\n### Suggestion\n- Für `solved(...)`: Überlege dir eine Rekursion über alle 81 Felder (z.B. über einen linearen Index `fieldNr`). Du brauchst eine Abbruchbedingung „alle Felder verarbeitet“ und ansonsten je Feld: wenn vorgegeben → weiter; wenn leer → Werte 1..size() probieren, nach jedem Setzen mit `checker.oneOK(...)` prüfen und bei Misserfolg wieder zurücksetzen (Backtracking).\n- Für `nofSolutions(...)`: Nutze dieselbe Traversierungslogik wie beim Lösen, aber statt beim ersten Fund zu stoppen, zählst du jede vollständige Belegung als „+1“. Denk daran, dass du bei vielen Lösungen früh abbrechen sollst: verwalte ein `max`-Budget (z.B. `max - n` beim rekursiven Aufruf), damit du bei `MAX` nicht weiter suchst.\n- Für `main(...)`: Vergleiche die erwartete Signatur mit einer Standard-Java-`main`-Methode. Achte darauf, dass sie `public` und `static` ist und ein `String[] args` entgegennimmt.\n\n### Code Style\n- Die `// TODO implement`-Stellen sind noch offen; solange die Methoden nur konstante Rückgabewerte liefern, ist das schwer testbar und verschleiert, ob die Rekursion korrekt aufgesetzt ist.\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: <279>"
    }, {
      "name" : "random3()",
      "status" : "FAILED",
      "message" : "expected: <558> but was: <357>"
    }, {
      "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
    } ]
  }
}