AutoFeedback API

Result 83b544cc-e01e-4545-8d52-82ab317796ff

{
  "llm" : {
    "feedback" : "# Exercise: fractal\n\n### Correctness\n- In `Triangles.drawRec` (Base Case `n == 0`) zeichnest du die dritte Kante als `(x0,y0) -> (x2,y2)`. Das ist zwar eine Dreiecksseite, aber du zeichnest damit nicht die Seite `(x2,y2) -> (x0,y0)` wie in der Aufgabenidee „alle drei Kanten“ vorgesehen (funktional identisch, aber prüfe, ob du wirklich die drei Kantenpaare konsistent zeichnest: 01, 12, 20).\n- In `Triangles.drawRec` (Rekursion) verwendest du für den Mittelpunkt der unteren Kante teils `y1` fix (z.B. `(x1 + x2)/2, y1`). Das ist nur korrekt, wenn `y1 == y2` gilt. Deine Methode ist dadurch an die spezielle Start-Geometrie gebunden und berechnet nicht allgemein den Mittelpunkt zwischen `(x1,y1)` und `(x2,y2)`.\n- `Circles` bleibt komplett unimplementiert. (Falls das in eurer Woche wirklich nur „Challenge“ ist, ist das ok — aber wenn es mitabgegeben werden soll, fehlt hier die Rekursion/Zeichnung.)\n\n### Suggestion\n- Für das Dreieck: Überlege dir für jede der drei Kanten im Basisfall ein klares Schema (z.B. immer 0→1, 1→2, 2→0) und bleib dabei, dann vermeidest du Verwechslungen bei den Endpunkten.\n- Bei den rekursiven Dreiecken: Berechne die drei Mittelpunkte jeweils wirklich als Mittelwert der beiden Endpunkte der jeweiligen Kante: einmal zwischen Punkt0–Punkt1, einmal zwischen Punkt0–Punkt2, einmal zwischen Punkt1–Punkt2. Dann kannst du daraus die drei Teil-Dreiecke zusammensetzen, ohne Annahmen über horizontale Kanten (kein „`y1` einfach übernehmen“).\n- Falls `Circles` doch verlangt ist: Starte mit „immer aktuellen Kreis zeichnen“ und entscheide dann über den Rekursionsabbruch über `n`. Danach platzierst du Kind-Kreise relativ zum aktuellen Mittelpunkt (Offsets/Radiusverhältnis).\n\n### Code Style\n- In `Boxes.drawRec` sind die vier Quadranten-Aufrufe gemischt sortiert (erst rechts, dann links). Funktional ok, aber eine konsistente Reihenfolge (z.B. TL, TR, BR, BL) macht die Rekursion leichter nachvollziehbar.\n- In `Triangles.drawRec` wiederholst du viele Ausdrücke wie `(x1 + x0) / 2` mehrfach inline. Das ist fehleranfällig; besser einmal in lokale Variablen (Mittelpunkte) ausrechnen und dann verwenden.\n\n\n# Exercise: knapsack\n\n### Correctness\n*(leer)*\n\n### Suggestion\n*(leer)*\n\n### Code Style\n- In `pack` wirkt `loadeditems` wie ein Workaround, um beim Backtracking wieder “genau so oft” zu entladen; das ist korrekt, aber macht den Kontrollfluss schwerer zu lesen. Überlege, ob du das Entladen an einer einzigen Stelle kapseln kannst (z.B. “alles, was ich von Item i eingeladen habe, in einem Schritt wieder entfernen”), statt mit zwei Schleifen und Zähler zu arbeiten.\n- `loadItem`/`unloadItem` schreiben sehr ausführlich (`currWeight = currWeight + ...`). Kürzer und üblicher wäre der Einsatz von `+=` und `-=`, das erhöht die Lesbarkeit.\n- In `pack` sind die Bedingungen verschachtelt (`if (i == ...) ... else if (currWeight <= ...) ...`). Du könntest mit “early returns”/klarer Struktur arbeiten, damit man die zwei Abbruchfälle (Ende erreicht / Übergewicht) schneller erkennt.\n\n\n# Exercise: queens\n\n### Correctness\n- `QueensSolver.solve()` ist nicht implementiert und liefert immer `false`, damit wird keine Lösung gefunden/gesetzt.\n- `QueensSolver.count()` ist nicht implementiert und liefert immer `0`, damit wird die Anzahl Lösungen nie korrekt gezählt.\n- In `Queens.main()` fehlt die korrekte `static void main(String[] args)` Signatur; so startet das Programm in Java typischerweise nicht (und die geforderte Ausgabe/Tests laufen ggf. nicht).\n\n### Suggestion\n- Für `solve()`: Überlege dir eine rekursive Backtracking-Funktion, die zeilenweise vorgeht: Basisfall „alle Zeilen platziert“, sonst in der aktuellen Zeile jede Spalte ausprobieren, nur setzen wenn `checkPlacement(...)` true ist, und beim Fehlschlag wieder zurücknehmen (Backtracking).\n- Für `count()`: Nutze ein ähnliches Rekursionsschema wie bei `solve()`, aber statt beim ersten Fund abzubrechen summierst du alle vollständigen Platzierungen; achte darauf, dass du nach jedem Rekursionsaufruf das gesetzte Feld wieder auf `false` setzt.\n- Für `main()`: Passe die Methodensignatur so an, dass die JVM sie als Einstiegspunkt erkennt (klassische `main`-Signatur); dann kannst du auch wirklich `solve()`/`count()` ausführen lassen.\n\n### Code Style\n- In `getBoard()` ist `return this.board;` zwar ok, aber inkonsistent zur Vorlage (`return board;`); entscheide dich für einen Stil und bleib dabei.\n- Die `// TODO implement`-Kommentare sind ok während der Entwicklung, sollten aber entfernt/ersetzt werden, sobald du implementiert hast.\n\n\n# Exercise: sudoku\n\n### Correctness\n- `Sudoku.main()` hat nicht die korrekte Signatur als Programmeinstiegspunkt (`public static void main(String[] args)`), dadurch startet die Applikation nicht wie gefordert.\n- `solved(...)` liefert aktuell immer `false`, auch wenn eine Lösung existiert.\n- In `solved(...)` fehlt die Abbruchbedingung für den Fall, dass `fieldNr` das letzte Feld überschreitet (sonst droht ein Zugriff ausserhalb des Boards).\n- In `solved(...)` wird das Resultat des rekursiven Aufrufs ignoriert; damit wird kein „gefunden“ nach oben propagiert und auch nicht frühzeitig beendet.\n- In `solved(...)` fehlt das Backtracking-Aufräumen: wenn ein Wert nicht zum Ziel führt, muss das Feld wieder geleert werden, damit andere Kandidaten korrekt getestet werden.\n- `nofSolutions(...)` ist nicht implementiert und gibt immer `0` zurück (Anforderung: Anzahl Lösungen zählen bis MAX und Model danach wieder im Ausgangszustand).\n\n### Suggestion\n- Schau dir die Methodensignatur von `main` in typischen Java-Programmen an und vergleiche sie mit deiner; die GUI wird nur erstellt, wenn Java die Methode als Einstieg erkennt.\n- Überlege dir eine klare Verankerung (Base Case) für das Backtracking: „Was bedeutet es, wenn ich alle 81 Felder verarbeitet habe?“ und was soll dann zurückgegeben werden?\n- Wenn du rekursiv weitersuchst: speichere das Ergebnis des rekursiven Aufrufs und brich die Schleifen ab, sobald eine gültige Lösung gefunden wurde, statt danach weiterzuprobieren.\n- Für echtes Backtracking: wenn ein Kandidat nicht funktioniert, setze das Feld wieder auf leer, bevor du den nächsten Kandidaten testest (und auch bevor du zurückkehrst).\n- Für `nofSolutions`: denke ähnlich wie bei `solved`, aber statt `boolean` sammelst du Counts; wichtig ist dabei, dass du beim Rekursionsrückweg das Feld wieder leer machst und dass du bei `max`/`MAX` frühzeitig abbrechen kannst, wenn genug Lösungen gezählt wurden.\n\n### Code Style\n- In `solved(...)` wäre es lesbarer, den rekursiven Rückgabewert in einer Variablen zu halten (z.B. `found`) statt ihn komplett zu ignorieren; dadurch wird die Logik nachvollziehbarer.\n- Der `else`-Zweig `} else solved(model,fieldNr+1);` ist ohne Block-Klammern schwer zu lesen; konsistente `{}` helfen, Fehler zu vermeiden.\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" : "PASSED",
      "message" : null
    }, {
      "name" : "random3()",
      "status" : "PASSED",
      "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" : "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
    } ]
  }
}