-
Notifications
You must be signed in to change notification settings - Fork 0
Improve run back #64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MMachmerth
wants to merge
18
commits into
git2025
Choose a base branch
from
improve_run_back
base: git2025
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Improve run back #64
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
6fcb23f
add Problem "linkedAfter"
MMachmerth aea32c1
add linkedInsert
MMachmerth fb98a5c
add linkedFind
MMachmerth 3ff0095
add linkedRemove
MMachmerth 3277d1b
update LinkedAfter
MMachmerth 236fa33
add linkedStack
MMachmerth bb01459
add linkedMerge
MMachmerth bade0eb
update linkedRemove
MMachmerth e1706f4
format with Ruff
MMachmerth 7e1c5a6
Update linkedMerge/html/linkedMerge.html
MMachmerth d652a21
Update linkedMerge/html/params.json
MMachmerth 83c18b4
format with Ruff
MMachmerth 0ba9f90
Update linkedAfter/html/template.html
MMachmerth 7e2612e
update LinkedAfter html
MMachmerth e4adf45
Merge remote-tracking branch 'origin/LinkedLists' into LinkedLists
MMachmerth 640847a
Update linkedAfter/checks/main.py
MMachmerth 1f2c5e7
Merge pull request #63 from HSDDigitalLabor/LinkedLists
MMachmerth f2cceea
change prototype of binary_recursive function including parameters fo…
MMachmerth File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| submit50: | ||
| files: &submit50_files | ||
| - !exclude "*" | ||
| - !include "*.py" | ||
| - !require linkedAfter.py | ||
|
|
||
| check50: | ||
| files: *submit50_files | ||
| checks: checks/main.py | ||
|
|
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| import check50 | ||
| import check50.py | ||
|
|
||
| FILE_NAME = "linkedAfter.py" | ||
|
|
||
|
|
||
| def to_list(ll): | ||
| """LinkedList -> Python-Liste (mit Zyklus-Schutz).""" | ||
| out = [] | ||
| cur = ll.head | ||
| seen = 0 | ||
| while cur is not None: | ||
| out.append(cur.value) | ||
| cur = cur.next | ||
| seen += 1 | ||
| if seen > 10_000: | ||
| msg = f"Linked list appears to have a cycle (more than {seen} nodes)" | ||
| raise check50.Failure(msg) | ||
| return out | ||
|
|
||
|
|
||
| def build_ll(module, values): | ||
| """Erzeugt eine LinkedList über FromPythonlist (wie in der Aufgabe vorgegeben).""" | ||
| ll = module.LinkedList() | ||
| ll.FromPythonlist(values) | ||
| return ll | ||
|
|
||
|
|
||
| def a(self, b): | ||
| c = self.head | ||
| while c is not None: | ||
| if c.value == b: | ||
| return c | ||
| c = c.next | ||
| return None | ||
|
|
||
|
|
||
| @check50.check() | ||
| def exists(): | ||
| """linkedAfter.py exists""" | ||
| check50.exists(FILE_NAME) | ||
|
|
||
|
|
||
| @check50.check(exists) | ||
| def compiles(): | ||
| """linkedAfter.py compiles""" | ||
| check50.py.compile(FILE_NAME) | ||
|
|
||
|
|
||
| @check50.check(compiles) | ||
| def has_classes_and_method(): | ||
| """ListNode, LinkedList and insertAfterNode exist""" | ||
| module = check50.py.import_(FILE_NAME) | ||
|
|
||
| if not hasattr(module, "ListNode"): | ||
| msg = f"Class `ListNode` not found in {FILE_NAME}" | ||
| raise check50.Failure(msg) | ||
|
|
||
| if not hasattr(module, "LinkedList"): | ||
| msg = f"Class `LinkedList` not found in {FILE_NAME}" | ||
| raise check50.Failure(msg) | ||
|
|
||
| if not hasattr(module.LinkedList(), "insertAfterNode"): | ||
| msg = "Method `insertAfterNode` not found in Class `LinkedList`" | ||
| raise check50.Failure(msg) | ||
|
|
||
|
|
||
| @check50.check(has_classes_and_method) | ||
| def test_frompythonlist_order_is_head_insertion(): | ||
| """FromPythonlist: inserts after head (result is reversed input order)""" | ||
| module = check50.py.import_(FILE_NAME) | ||
|
|
||
| ll = build_ll(module, [1, 2, 8, 4]) | ||
| expected = [4, 8, 2, 1] # weil insertAfterHead bei Vorwärtsiteration umdreht | ||
| actual = to_list(ll) | ||
|
|
||
| if actual != expected: | ||
| raise check50.Mismatch(str(expected), str(actual)) | ||
|
|
||
|
|
||
| @check50.check(has_classes_and_method) | ||
| def test_insert_after_middle(): | ||
| """insertAfterNode inserts after a middle node (in reversed-built list)""" | ||
| module = check50.py.import_(FILE_NAME) | ||
|
|
||
| ll = build_ll(module, [1, 2, 8, 4]) # Liste: 4 -> 8 -> 2 -> 1 | ||
| module.LinkedList.searchValue = a | ||
| node = ll.searchValue(8) | ||
| if node is None: | ||
| msg = "searchValue(8) returned None, but 8 should be in the list" | ||
| raise check50.Failure(msg) | ||
|
|
||
| ll.insertAfterNode(node, module.ListNode(3)) | ||
|
|
||
| expected = [4, 8, 3, 2, 1] | ||
| actual = to_list(ll) | ||
| if actual != expected: | ||
| raise check50.Mismatch(str(expected), str(actual)) | ||
|
|
||
|
|
||
| @check50.check(has_classes_and_method) | ||
| def test_insert_after_head(): | ||
| """insertAfterNode inserts after head""" | ||
| module = check50.py.import_(FILE_NAME) | ||
|
|
||
| ll = build_ll(module, [10, 20, 30]) # Liste: 30 -> 20 -> 10 | ||
| module.LinkedList.searchValue = a | ||
| head = ll.head | ||
| if head is None: | ||
| msg = "Linked list head is None after FromPythonlist" | ||
| raise check50.Failure(msg) | ||
|
|
||
| ll.insertAfterNode(head, module.ListNode(25)) | ||
|
|
||
| expected = [30, 25, 20, 10] | ||
| actual = to_list(ll) | ||
| if actual != expected: | ||
| raise check50.Mismatch(str(expected), str(actual)) | ||
|
|
||
|
|
||
| @check50.check(has_classes_and_method) | ||
| def test_insert_after_tail(): | ||
| """insertAfterNode inserts after last node (tail)""" | ||
| module = check50.py.import_(FILE_NAME) | ||
|
|
||
| ll = build_ll(module, [10, 20, 30]) # Liste: 30 -> 20 -> 10 | ||
| module.LinkedList.searchValue = a | ||
| tail = ll.searchValue(10) # 10 ist Tail | ||
| if tail is None: | ||
| msg = "searchValue(10) returned None, but 10 should be in the list" | ||
| raise check50.Failure(msg) | ||
|
|
||
| ll.insertAfterNode(tail, module.ListNode(5)) | ||
|
|
||
| expected = [30, 20, 10, 5] | ||
| actual = to_list(ll) | ||
| if actual != expected: | ||
| raise check50.Mismatch(str(expected), str(actual)) | ||
|
|
||
|
|
||
| @check50.check(has_classes_and_method) | ||
| def test_insert_after_none_prevnode(): | ||
| """insertAfterNode with prevNode=None: | ||
| We expect an exception (ValueError) rather than silently doing nothing.""" | ||
| module = check50.py.import_(FILE_NAME) | ||
|
|
||
| ll = build_ll(module, [1, 2, 3]) | ||
| module.LinkedList.searchValue = a | ||
| prev = ll.searchValue(999) # not in list -> None | ||
| new_node = module.ListNode(4) | ||
|
|
||
| threw = False | ||
| try: | ||
| ll.insertAfterNode(prev, new_node) | ||
| except ValueError: | ||
| threw = True | ||
|
|
||
| if not threw: | ||
| msg = "insertAfterNode should raise a ValueError when prevNode is None" | ||
| raise check50.Failure(msg) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| <h1 id="linkedAfter">Linked List: Insert After Node</h1> | ||
|
|
||
| <p> | ||
| In dieser Übung werden Sie die Datenstruktur <strong>Verkettete Liste (Linked List)</strong> erweitern. | ||
| Gegeben sind bereits die Klassen <code>ListNode</code> und <code>LinkedList</code>, sowie einige | ||
| Hilfsmethoden: <code>FromPythonlist(inputList)</code> zur Erzeugung einer verketteten Liste aus einer Python-Liste | ||
| und <code>printList()</code> zur Ausgabe der Liste. Ebenfalls gegeben ist die Methode | ||
| <code>searchValue(value)</code>, mit deren Hilfe Sie ein Listenelement mit einem bestimmten Wert | ||
| suchen können. Ihre Aufgabe ist es, die Methode <code>insertAfterNode(prevNode, newNode)</code> | ||
| zu implementieren, die ein neues Listenelement <code>newNode</code> direkt nach dem gegebenen | ||
| Element <code>prevNode</code> einfügt. | ||
| </p> | ||
|
|
||
|
|
||
| <h2 id="aufgabe">Aufgabe</h2> | ||
|
|
||
| <p> | ||
| Implementieren Sie die Methode <code>insertAfterNode(self, prevNode, newNode)</code> in der Klasse <code>LinkedList</code>. | ||
| Die Methode erhält das Element <code>prevNode</code> und das neue Element <code>newNode</code> | ||
| und soll das neue Element direkt nach <code>prevNode</code> in die Liste einfügen. Ist <code>prevNode</code> <code>None</code>, | ||
| soll eine <code>ValueError</code>-Exception ausgelöst werden. | ||
| </p> | ||
|
|
||
|
|
||
| <p> | ||
| Erstellen Sie eine Datei mit dem Namen | ||
| <code class="text-danger border border-dark">linkedAfter.py</code> und | ||
| Implementieren Sie die Methode <code>insertAfterNode</code> in Ihrer Datei. Kopieren Sie dazu den | ||
| folgenden Codeblock in die Datei <code class="text-danger border border-dark">linkedAfter.py</code>, | ||
| und ergänzen Sie die Methode <code>insertAfterNode</code>: | ||
| </p> | ||
|
|
||
| <div class="alert alert-dark"> | ||
| <pre><code> | ||
| class ListNode: | ||
| def __init__(self, value: int): | ||
| self.value: int = value | ||
| self.next: ListNode | None = None | ||
|
|
||
|
|
||
| class LinkedList: | ||
| def __init__(self): | ||
| self.head = None | ||
|
|
||
| def FromPythonlist(self, inputList: list[int]): | ||
| for val in inputList: | ||
| newNode = ListNode(value=val) | ||
| self.insertAfterHead(newNode) | ||
|
|
||
| def searchValue(self, value: int) -> ListNode: | ||
| # Siehe Problem 'linkedFind.py' für die Implementierung dieser Methode | ||
| return | ||
|
|
||
| def insertAfterNode(self, prevNode: ListNode | None, newNode: ListNode): | ||
| # TODO: Implementieren Sie diese Methode | ||
| return | ||
|
|
||
| def printList(self): | ||
| current = self.head | ||
| while current is not None: | ||
| print(current.value, end=" -> ") | ||
| current = current.next | ||
| print("None") | ||
|
|
||
| def insertAfterHead(self, newNode: ListNode): | ||
| newNode.next = self.head | ||
| self.head = newNode | ||
| </code></pre> | ||
| </div> | ||
|
|
||
|
|
||
| <!-- <p></p> | ||
| <h2 id="demo">Demo</h2> | ||
| <p> | ||
| <script async="" data-autoplay="1" data-cols="80" data-loop="1" data-rows="12" | ||
| id="asciicast-" | ||
| src="https://asciinema.org/a/.js"> | ||
| </script> | ||
| </p> --> | ||
|
|
||
| <h2 id="before-you-begin">Bevor Sie beginnen</h2> | ||
| <p>Melden Sie sich bei <a href="https://cs50.dev/" target="_blank">cs50.dev</a> an, klicken Sie | ||
| auf Ihr Terminal und führen Sie <code | ||
| class="text-danger border border-dark">cd</code> ohne Parameter aus. Sie | ||
| sollten feststellen, dass der Prompt Ihres Terminals wie unten aussieht:</p> | ||
| <div class="alert alert-primary"><code | ||
| class="text-dark font-weight-bold">$</code></div> | ||
| <p>Als nächstes führen Sie</p> | ||
| <div class="alert alert-primary"><code class="text-dark font-weight-bold">mkdir | ||
| linkedAfter</code></div> | ||
| <p>aus, um einen Ordner namens <code | ||
| class="text-danger border border-dark">linkedAfter</code> in Ihrem Codespace | ||
| zu erstellen.</p> | ||
| <p>Führen Sie anschließend</p> | ||
| <div class="alert alert-primary"><code class="text-dark font-weight-bold">cd | ||
| linkedAfter</code></div> | ||
| <p>aus, um in dieses Verzeichnis zu wechseln. Der Prompt Ihres Terminals sollte | ||
| nun <code class="text-danger border border-dark">linkedAfter/$</code> anzeigen. | ||
| Jetzt können Sie</p> | ||
| <div class="alert alert-primary"><code class="text-dark font-weight-bold">code | ||
| linkedAfter.py</code></div> | ||
| <p>ausführen, um eine Datei namens <code | ||
| class="text-danger">linkedAfter.py</code> zu erstellen, in der Sie Ihr | ||
| Programm schreiben. | ||
| </p> | ||
|
|
||
| <h2 id="how-to-test">So testen Sie Ihr Programm</h2> | ||
| <p>So können Sie Ihr Programm manuell testen:</p> | ||
|
|
||
| <p> | ||
| Testen Sie Ihre Implementierung, indem Sie das Skript ausführen. | ||
| Erstellen Sie dazu eine Instanz der <code>LinkedList</code>, fügen Sie Elemente hinzu und rufen Sie dann Ihre Methode <code>insertAfterNode</code> auf. | ||
| Überprüfen Sie anschließend, ob die Liste die erwartete Struktur hat, indem Sie <code>printList()</code> verwenden. | ||
| </p> | ||
|
|
||
| <div class="alert alert-dark"> | ||
| <pre><code> | ||
| # Erstellen einer verketteten Liste aus einer Python-Liste | ||
| inputList = [4, 8, 2, 1] | ||
| ll = LinkedList() | ||
| ll.FromPythonlist(inputList) | ||
|
|
||
| print("Liste vorher:") | ||
| ll.printList() | ||
|
|
||
| node = ll.searchValue(8) | ||
| newNode = ListNode(3) | ||
| # Einfügen von 3 nach 8 | ||
| ll.insertAfterNode(node, newNode) | ||
|
|
||
| print("Liste nachher:") | ||
| ll.printList() | ||
| # Erwartete Ausgabe: 1 -> 2 -> 8 -> 3 -> 4 -> None | ||
| </code></pre> | ||
| </div> | ||
|
|
||
|
|
||
|
|
||
| <p>Sie können das folgende Kommando ausführen, um Ihren Code mit <code | ||
| class="text-danger">check50</code> zu überprüfen, einem Programm, das bei | ||
| der Abgabe verwendet wird um Ihren Code zu testen. Testen Sie Ihr Programm | ||
| aber auch selbst!</p> | ||
| <div class="alert alert-primary"><code class="text-dark font-weight-bold"> | ||
| check50 HSDDigitalLabor/problems/adg2025/linkedAfter | ||
| </code></div> | ||
| <p> | ||
| Grüne Smileys <span style="font-family: monospace; color: green;">:) </span> | ||
| bedeuten, dass Ihr Programm einen Test bestanden hat! Rote | ||
| traurige Smileys <span style="font-family: monospace; color: red;">:( </span> | ||
| zeigen an, dass Ihr Programm etwas Unerwartetes ausgegeben | ||
| hat. Besuchen Sie die URL, die <code class="text-danger">check50</code> | ||
| ausgibt, um zu sehen, welche Eingabe <code class="text-danger">check50</code> | ||
| an Ihr Programm übergeben hat, welche Ausgabe erwartet wurde und welche | ||
| Ausgabe Ihr Programm tatsächlich geliefert hat. | ||
| </p> | ||
|
|
||
| <h2 id="how-to-submit">Abgabe</h2> | ||
| <p>Führen Sie im Terminal den folgenden Befehl aus, um Ihre Arbeit einzureichen. | ||
| </p> | ||
| <div class="alert alert-primary"><code class="text-dark font-weight-bold"> | ||
| submit50 HSDDigitalLabor/problems/adg2025/linkedAfter | ||
| </code></div> | ||
| <p> | ||
| Führen Sie diesen Befehl vor dem Fälligkeitsdatum aus. Sie können Ihre Lösung | ||
| nach dem ersten Einsenden noch ändern und erneut einreichen. Bewertet wird | ||
| die zuletzt eingereichte Version vor dem Fälligkeitsdatum. Nach Ablauf der | ||
| Frist können Sie technisch zwar noch Abgaben tätigen, Ihre Lösung wird jedoch | ||
| nicht mehr gewertet. Das Ergebnis kann ausschließlich mit obigem Befehl abgegeben | ||
| werden, eine Abgabe in Moodle ist nicht möglich. | ||
| </p> | ||
|
|
||
| <h2 id="how-to-mark">Markierung der Aufgabe als erledigt</h2> | ||
| <p>Nach dem Einreichen der Lösung mit <code class="text-danger">submit50</code>, | ||
| nehmen Sie eine Pseudolösung in Moodle vor, indem Sie auf den Button | ||
| <button type="submit" class="btn btn-primary" id="sample_solution" disabled> | ||
| Aufgabenlösung hinzufügen</button> | ||
| weiter unten auf dieser Seite betätigen und in das sich öffnende Feld unter | ||
| "Texteingabe online" den folgenden Text ein: | ||
| </p> | ||
| <div class="alert alert-primary"> | ||
| <code class="text-dark font-weight-bold">Mit submit50 abgegeben.</code> | ||
| </div> | ||
| <p>Schließen Sie die Eingabe durch Klick auf den Button | ||
| <button type="submit" class="btn btn-primary" id="sample_save" disabled> | ||
| Änderungen speichern</button> unterhalb des Textfeldes ab. | ||
| </p> | ||
| <p> | ||
| Zur besseren Übersicht markieren Sie das Problem linkedAfter.py in Moodle als erledigt, | ||
| indem Sie ganz oben auf dieser Seite den Button | ||
| </p> | ||
| <p> | ||
| <button class="btn btn-outline-secondary btn-sm text-nowrap" title="Problem: linkedAfter.py als erledigt kennzeichnen" | ||
| aria-label="Problem: linkedAfter.py als erledigt kennzeichnen" disabled> | ||
| Als erledigt kennzeichnen | ||
| </button> | ||
| klicken. Daraufhin erscheint der Button | ||
| <button class="btn btn-success btn-sm text-nowrap" | ||
| title="Problem: linkedAfter.py ist als erledigt gekennzeichnet. Zum Rückgängigmachen klicken." | ||
| aria-label="Problem: linkedAfter.py ist als erledigt gekennzeichnet. Zum Rückgängigmachen klicken." disabled> | ||
| <i class="fa fa-check" aria-hidden="true"></i> Erledigt | ||
| </button> | ||
| </p> | ||
|
|
||
| <p class="text-muted text-right text-nowrap" style="font-size: 0.6em;">generated 2025-12-22 12:27:59</p> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "id": "linkedAfter", | ||
| "title": "Linked List: Insert After Node", | ||
| "foldername": "linkedAfter", | ||
| "filename": "linkedAfter.py", | ||
| "asciicast_id": "", | ||
| "check50_path": "HSDDigitalLabor/problems/adg2025/linkedAfter", | ||
| "submit50_path": "HSDDigitalLabor/problems/adg2025/linkedAfter" | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function name
awith parameterband variablecis not descriptive. This appears to be a helper function for searching values in a linked list. Consider using meaningful names likesearch_value_implfor the function,valuefor the parameter, andcurrentfor the variable to improve code readability.