AutoFeedback API

Result 23b4c685-e183-49f1-aecc-0208a903f156

{
  "llm" : {
    "feedback" : "# Exercise: fractal\n\n### Correctness\n- In `Triangles.drawRec` zeichnest du im Basisfall die dritte Kante mit `g.drawLine(x0, y0, x2, y2)`; das ist zwar eine Kante, aber du schliesst das Dreieck nicht mit der Kante zwischen Punkt 2 und Punkt 0 im gleichen “Rundlauf” wie die anderen Linien (in der Vorlage/üblichen Form wäre das die Kante `x2,y2` nach `x0,y0`). Je nach Erwartung/Tests kann das als falsches Zeichnen des Dreiecks gewertet werden.\n- In `Triangles.drawRec` verwendest du in einem rekursiven Teil-Dreieck für den y-Wert eines Mittelpunkts schlicht `y1` (z.B. `(x1+x2)/2, y1`). Das ist nur dann korrekt, wenn die beiden Punkte wirklich exakt dieselbe y-Koordinate haben. Die Rekursion sollte aber allgemein mit den Mittelpunkten der jeweiligen Kanten arbeiten, sonst verschieben sich bei anderen Koordinaten die Teil-Dreiecke bzw. es entstehen “verzogene” Formen.\n\n### Suggestion\n- Prüfe im Basisfall, ob du wirklich alle drei Kanten so zeichnest, dass die Punkte zyklisch verbunden werden (P0→P1, P1→P2, P2→P0), statt “quer” zu verbinden.\n- Berechne für jede der drei Kanten jeweils den Mittelpunkt aus beiden Endpunkten (sowohl x als auch y als Durchschnitt der jeweiligen Endpunkte) und verwende genau diese drei Mittelpunkte, um die drei rekursiven Teil-Dreiecke zusammenzusetzen. Wenn du irgendwo `y1` “hart” einsetzt, überleg dir, ob das wirklich der Mittelpunkt-y der betreffenden Kante ist.\n\n### Code Style\n- In `Boxes.drawRec` mischst du rekursive Aufrufe und ein direktes `g.drawRect(...)` für das unten-links-Quadrat. Das ist nicht falsch, aber uneinheitlich; entweder alles rekursiv (z.B. mit passender Abbruchstufe) oder alles direkt nach demselben Muster macht den Code leichter zu lesen.\n- In `Triangles.drawRec` sind die vielen Ausdrücke wie `(x1 + x0) / 2` mehrfach wiederholt; speichere Mittelpunkte in gut benannten lokalen Variablen (wie “leftMid”, “rightMid”, “bottomMid”), das reduziert Fehler und macht die Geometrie nachvollziehbarer.\n- Kommentare sind teils knapp/uneinheitlich (z.B. “rechts oben”, “recht unten”); wenn du kommentierst, dann am besten konsistent und mit klarer Benennung (oben links/rechts, unten links/rechts).\n\n\n# Exercise: knapsack\n\n### Correctness\n- `pack(int i)` ist nicht implementiert; damit wird nie eine Kombination ausprobiert und `maxValue` bleibt immer `0`.\n- `loadItem(int i)` und `unloadItem(int i)` sind nicht implementiert; selbst wenn `pack` rekursiv aufgerufen würde, könnte das Gewicht/der Wert nie korrekt verändert und zurückgesetzt werden.\n- `KnapsackN.main()` hat keine `String[] args`-Signatur; je nach Test-/Run-Setup wird die Main-Methode so nicht als Programmeinstieg erkannt.\n\n### Suggestion\n- Überlege dir für `pack(i)` eine Rekursions-/Backtracking-Struktur: Was passiert, wenn `i` noch innerhalb der Item-Liste liegt, und was ist der Abbruchfall bei `i == weights.length`?\n- Um „n gleiche Gegenstände“ zu ermöglichen: Für jedes Item `i` musst du nicht nur „nehmen/nehmen nicht“ betrachten, sondern „0 bis maxN-mal nehmen“. Eine Schleife über die mögliche Anzahl ist dafür ein typischer Ansatz.\n- Achte darauf, dass du nach dem Ausprobieren mehrerer „load“-Schritte den Zustand wieder korrekt zurücksetzt (Backtracking): `unloadItem` muss genau das rückgängig machen, was du zuvor an `currWeight`/`currValue` addiert hast.\n- Für `main`: Prüfe, welche Methodensignatur in euren Übungen/Tests erwartet wird und passe sie entsprechend an (häufig `static void main(String[] args)`).\n\n### Code Style\n- Die `// TODO implement`-Stellen sind noch offen; solange sie leer sind, ist die Klasse funktional unvollständig.\n- Benennungen sind uneinheitlich zur Aufgabenlogik: Du verwendest `loadItem/unloadItem`, im Kontext wird aber meist „pack/unpack“ verwendet—wichtig ist v.a., dass klar ist, dass es symmetrische Gegenoperationen sind.\n- `KnapsackN.main()` ohne Parameter ist ungewöhnlich für Java und kann beim automatischen Ausführen verwirren; auch wenn es lokal geht, ist die Standard-Signatur wartungsfreundlicher.\n\n\n# Exercise: queens\n\n### Correctness\n- `QueensSolver.solve()` ist nicht implementiert und liefert immer `false`, damit wird keine Lösung gefunden und das Board nie korrekt befüllt.\n- `QueensSolver.count()` ist nicht implementiert und liefert immer `0`, damit wird die Anzahl der Lösungen nicht gezählt.\n- In `Queens.main()` fehlt die korrekte Java-`main`-Signatur (`static void main(String[] args)`), dadurch startet das Programm so nicht wie erwartet.\n\n### Suggestion\n- Für `solve()`: Überlege dir eine rekursive Backtracking-Struktur, die zeilenweise (oder spaltenweise) eine Dame setzt, und bei einem Fehlschlag die gesetzte Dame wieder entfernt (Undo-Schritt), bevor die nächste Position probiert wird.\n- Für `count()`: Nutze eine sehr ähnliche Rekursion wie bei `solve()`, aber statt beim ersten Fund abzubrechen, sammelst du alle möglichen vollständigen Platzierungen (Basisfall liefert dann einen Zählwert zurück).\n- Für `main()`: Prüfe, welche Methodensignatur die JVM als Einstiegspunkt erwartet und passe die `main`-Methode entsprechend an (Stichwort: `static`, Parameterliste).\n\n### Code Style\n- In `getBoard()` ist `return this.board;` ok, aber das `this` ist hier nicht nötig und kann weggelassen werden, um es konsistent mit dem Rest zu halten.\n\n\n# Exercise: sudoku\n\n### Correctness\n- In `SudokuSolverImpl`, die Methoden `solved(SudokuModel model, int fieldNr)` und `nofSolutions(SudokuModel model, int fieldNr, int max)` sind nicht implementiert (geben immer `false` bzw. `0` zurück) und erfüllen damit die Aufgabenanforderungen nicht.\n- In `Sudoku.java` ist `main` nicht als `public static void main(String[] args)` deklariert; so startet das Programm/GUI typischerweise nicht über den normalen Java-Entry-Point.\n\n### Suggestion\n- Für `solved(...)`: Überlege dir eine Backtracking-Rekursion über alle Felder (z.B. per `fieldNr` von 0 bis `size*size`). Du brauchst eine Abbruchbedingung, wann du “fertig” bist, und pro Feld die Unterscheidung “vorgegeben” (≠ 0) vs. “leer” (== 0). Bei leeren Feldern probierst du Werte 1..`size()` und prüfst nach dem Setzen mit dem `checker` die Gültigkeit, bevor du rekursiv weitergehst. Wenn kein Wert passt, musst du das Feld wieder zurücksetzen.\n- Für `nofSolutions(...)`: Das ist sehr ähnlich wie `solved`, aber statt “bei erster Lösung stoppen” zählst du alle Lösungen. Achte darauf, dass du das `max`-Limit tatsächlich zum frühzeitigen Abbrechen nutzt (sonst kann es extrem lange dauern). Außerdem muss das Modell nach dem Zählen wieder im Ausgangszustand sein (d.h. Felder, die du testweise gesetzt hast, wieder leeren), auch wenn du wegen `max` abbrichst.\n- Für `Sudoku.java`: Passe die Signatur von `main` so an, dass sie von der JVM als Einstiegspunkt erkannt wird (inkl. `public`, `static`, Rückgabetyp und Parameterliste).\n\n### Code Style\n- Die `// TODO implement`-Platzhalter sind ok während der Arbeit, sollten aber verschwinden, sobald du fertig bist, damit klar ist, dass die Abgabe vollständig ist.\n- Einheitliche Sichtbarkeit/Signatur: In `Sudoku.java` wirkt `void main()` wie ein Versehen (fehlendes `public static`, fehlende `String[] args`); das ist weniger “Style” als auch Wartbarkeit/Erwartungskonvention in Java.\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
    } ]
  }
}