Orivel Orivel
Menue oeffnen

Implementieren Sie einen Abhängigkeitsauflöser mit semantischer Versionierung

Vergleiche Modellantworten fuer diese Programmierung-Benchmark-Aufgabe und pruefe Scores, Kommentare und verwandte Beispiele.

Bitte einloggen oder registrieren, um Likes und Favoriten zu nutzen. Registrieren

X f L

Inhalt

Aufgabenubersicht

Vergleichsgenres

Programmierung

Aufgaben-Erstellermodell

Antwortende Modelle

Bewertungsmodelle

Aufgabenstellung

Ihre Aufgabe ist es, eine Funktion zu schreiben, die den Abhängigkeitsauflöser eines Paketmanagers simuliert. Die Funktion soll eine Liste aller verfügbaren Pakete, ein Zielpaket zur Installation und dessen Versionsanforderung entgegennehmen. Sie muss eine flache Liste von Paketen (Name und spezifische Version) zurückgeben, die installiert werden müssen, in einer gültigen topologischen Reihenfolge (Abhängigkeiten vor Abhängigen). Der Resolver muss SemVer (semantische Versionierung) Einschränkungen verarbeiten. Für...

Mehr anzeigen

Ihre Aufgabe ist es, eine Funktion zu schreiben, die den Abhängigkeitsauflöser eines Paketmanagers simuliert. Die Funktion soll eine Liste aller verfügbaren Pakete, ein Zielpaket zur Installation und dessen Versionsanforderung entgegennehmen. Sie muss eine flache Liste von Paketen (Name und spezifische Version) zurückgeben, die installiert werden müssen, in einer gültigen topologischen Reihenfolge (Abhängigkeiten vor Abhängigen). Der Resolver muss SemVer (semantische Versionierung) Einschränkungen verarbeiten. Für diese Aufgabe müssen Sie nur exakte Versionen, Caret (`^`) und Tilde (`~`) Spezifizierer unterstützen. - `1.2.3`: Muss genau Version 1.2.3 sein. - `^1.2.3`: Erlaubt Versionen von 1.2.3 bis, aber nicht einschließlich, 2.0.0 (d.h. `>=1.2.3 <2.0.0`). - `~1.2.3`: Erlaubt Versionen von 1.2.3 bis, aber nicht einschließlich, 1.3.0 (d.h. `>=1.2.3 <1.3.0`). Ihre Implementierung muss: 1. Für jedes Paket die höchstmögliche Version auswählen, die alle von anderen Paketen im Abhängigkeitsbaum auferlegten Einschränkungen erfüllt. 2. Eine topologisch sortierte Liste von Paketen für die Installation erzeugen. 3. Fehlerfälle elegant behandeln und melden für: - Nicht auflösbare Versionskonflikte (z. B. wenn eine Abhängigkeit `^1.0.0` und eine andere `^2.0.0` desselben Pakets verlangt). - Zirkuläre Abhängigkeiten (z. B. Paket A hängt von B ab und B hängt von A ab). - Ein benötigtes Paket oder eine benötigte Version nicht verfügbar ist. Sie können jede Programmiersprache für Ihre Implementierung wählen. Definieren Sie die Funktionssignatur und Datenstrukturen nach eigenem Ermessen, machen Sie diese aber klar.

Erganzende Informationen

Gehen Sie davon aus, dass die Liste der verfügbaren Pakete in einer Struktur wie dem folgenden JSON-Objekt bereitgestellt wird. Die Schlüssel sind Paketnamen. Die Werte sind Arrays verfügbarer Versionen, wobei jedes Versionsobjekt einen Versionsstring und ein Objekt auflistet, das seine Abhängigkeiten enthält. Ein Beispiel für diese Datenstruktur ist: {"pkg-A": [{"version": "1.0.0", "dependencies": {"pkg-B": "~1.0.0"}}, {"version": "1.1.0", "dependencies": {"pkg-B": "^1.1.0"}}], "pkg-B": [{"version": "1.0.0", "depe...

Mehr anzeigen

Gehen Sie davon aus, dass die Liste der verfügbaren Pakete in einer Struktur wie dem folgenden JSON-Objekt bereitgestellt wird. Die Schlüssel sind Paketnamen. Die Werte sind Arrays verfügbarer Versionen, wobei jedes Versionsobjekt einen Versionsstring und ein Objekt auflistet, das seine Abhängigkeiten enthält. Ein Beispiel für diese Datenstruktur ist: {"pkg-A": [{"version": "1.0.0", "dependencies": {"pkg-B": "~1.0.0"}}, {"version": "1.1.0", "dependencies": {"pkg-B": "^1.1.0"}}], "pkg-B": [{"version": "1.0.0", "dependencies": {}}, {"version": "1.0.5", "dependencies": {}}, {"version": "1.1.0", "dependencies": {}}, {"version": "2.0.0", "dependencies": {}}], "pkg-C": [{"version": "1.0.0", "dependencies": {"pkg-A": "^1.0.0", "pkg-B": "^1.0.0"}}], "pkg-D": [{"version": "1.0.0", "dependencies": {"pkg-D": "^1.0.0"}}], "pkg-E": [{"version": "1.0.0", "dependencies": {"pkg-F": "^1.0.0"}}], "pkg-F": [{"version": "1.0.0", "dependencies": {"pkg-E": "^1.0.0"}}]}. Zum Beispiel, wenn Sie aufgefordert würden, `pkg-C` mit der Versionsanforderung `^1.0.0` aufzulösen, könnte eine korrekte Ausgabe eine Liste wie `[{"name": "pkg-B", "version": "1.1.0"}, {"name": "pkg-A", "version": "1.1.0"}, {"name": "pkg-C", "version": "1.0.0"}]` sein (die Reihenfolge von pkg-B und pkg-A kann vertauscht werden). Dies liegt daran, dass `pkg-C@1.0.0` `pkg-A@^1.0.0` und `pkg-B@^1.0.0` benötigt. Die beste Version für `pkg-A` ist `1.1.0`, die wiederum `pkg-B@^1.1.0` benötigt. Die Schnittmenge der Einschränkungen `^1.0.0` und `^1.1.0` für `pkg-B` ergibt `^1.1.0`, daher wird `pkg-B@1.1.0` gewählt. Wenn Sie aufgefordert werden, `pkg-D` oder `pkg-E` aufzulösen, sollte die Funktion eine zirkuläre Abhängigkeit melden.

Bewertungsrichtlinie

Eine qualitativ hochwertige Lösung muss ein korrektes, robustes und gut geschriebenes Programm sein. - **Korrektheit:** Das primäre Kriterium ist Korrektheit. Die endgültige Paketliste muss alle Abhängigkeitsbeschränkungen erfüllen, die höchstmöglichen gültigen Versionen verwenden und in einer korrekten topologischen Reihenfolge stehen. Die Logik zum Parsen von SemVer-Bereichen (`^`, `~`) muss genau sein. - **Robustheit und Fehlerbehandlung:** Der Code darf bei komplexen oder ungültigen Eingaben nicht abstürzen. Er...

Mehr anzeigen

Eine qualitativ hochwertige Lösung muss ein korrektes, robustes und gut geschriebenes Programm sein. - **Korrektheit:** Das primäre Kriterium ist Korrektheit. Die endgültige Paketliste muss alle Abhängigkeitsbeschränkungen erfüllen, die höchstmöglichen gültigen Versionen verwenden und in einer korrekten topologischen Reihenfolge stehen. Die Logik zum Parsen von SemVer-Bereichen (`^`, `~`) muss genau sein. - **Robustheit und Fehlerbehandlung:** Der Code darf bei komplexen oder ungültigen Eingaben nicht abstürzen. Er sollte klar verständliche Fehlermeldungen für alle Fehlerfälle korrekt identifizieren und melden, einschließlich Versionskonflikten, zirkulären Abhängigkeiten und fehlenden Paketen/Versionen. - **Codequalität und Design:** Die Lösung sollte gut strukturiert und lesbar sein. Die Logik sollte in handhabbare Funktionen aufgeteilt sein (z. B. für Versionsparsing, Graphaufbau und Auflösung). Die Wahl der Algorithmen und Datenstrukturen sollte der Komplexität des Problems angemessen sein. - **Vollständigkeit:** Die Lösung sollte eine vollständige, ausführbare Funktion oder ein Programm sein, das zeigt, wie es mit den Beispieldaten verwendet wird.

Antworten

Abhängigkeitsauflöser mit SemVer-Unterstützung (exakt, ^, ~). Implementiert Backtracking, um die höchstmögliche Version pro Paket auszuwählen, die mit allen Einschränkungen konsistent ist, erkennt zirkuläre Abhängigkeiten, fehlende Pakete/Versionen und Konflikte. API: resolve_dependencies(available_packages, target_name, target_spec) - available_packages: dict, das Paketnamen -> Liste von Versionen abbildet, wobei jede Version ein dict ist {"version": "1.2.3", "dependencies": {"pkg-B": "^1.0.0", ...}} - target_name: Paketname als String - target_spec: Versionsspezifikation als String (exakt...

Vollstandige Antwort anzeigen

Abhängigkeitsauflöser mit SemVer-Unterstützung (exakt, ^, ~). Implementiert Backtracking, um die höchstmögliche Version pro Paket auszuwählen, die mit allen Einschränkungen konsistent ist, erkennt zirkuläre Abhängigkeiten, fehlende Pakete/Versionen und Konflikte. API: resolve_dependencies(available_packages, target_name, target_spec) - available_packages: dict, das Paketnamen -> Liste von Versionen abbildet, wobei jede Version ein dict ist {"version": "1.2.3", "dependencies": {"pkg-B": "^1.0.0", ...}} - target_name: Paketname als String - target_spec: Versionsspezifikation als String (exakt wie "1.2.3" oder "^1.2.3" oder "~1.2.3") Gibt zurück: Liste von {"name": pkg, "version": ver} in topologischer Reihenfolge (Abhängigkeiten vor Abhängigen) Löst Ausnahmen aus: NotFoundError, ConflictError, CircularDependencyError mit beschreibenden Meldungen. Beispielverwendung mit den Beispieldaten in der Eingabeaufforderung finden Sie unten unter `if __name__ == '__main__' `. from copy import deepcopy class ResolverError(Exception): pass class NotFoundError(ResolverError): pass class ConflictError(ResolverError): pass class CircularDependencyError(ResolverError): pass def parse_version(v): parts = v.split('.') if len(parts) != 3: raise ValueError(f"Unsupported version format: {v}") try: return tuple(int(p) for p in parts) except Exception: raise ValueError(f"Unsupported version number in: {v}") def cmp_version(a, b): return (a > b) - (a < b) def satisfies_spec(version_str, spec): v = parse_version(version_str) if spec.startswith('^'): base = parse_version(spec[1:]) # ^1.2.3 => >=1.2.3 <2.0.0 min_v = base max_v = (base[0] + 1, 0, 0) return v >= min_v and v < max_v elif spec.startswith('~'): base = parse_version(spec[1:]) # ~1.2.3 => >=1.2.3 <1.3.0 min_v = base max_v = (base[0], base[1] + 1, 0) return v >= min_v and v < max_v else: # exact base = parse_version(spec) return v == base def filter_versions(available_version_list, specs): # available_version_list: list of version strings (e.g. ["1.1.0","1.0.5"]) or list of version dicts # specs: list of spec strings # Return list of version dicts that satisfy all specs result = [] for verobj in available_version_list: ver_str = verobj['version'] ok = True for s in specs: if not satisfies_spec(ver_str, s): ok = False break if ok: result.append(verobj) # sort descending highest first result.sort(key=lambda vd: parse_version(vd['version']), reverse=True) return result def build_versions_index(available_packages): # Normalize and sort available versions descending idx = {} for pkg, versions in available_packages.items(): # ensure each item has 'version' and 'dependencies' vlist = [] for v in versions: deps = v.get('dependencies', {}) if isinstance(v, dict) else {} vlist.append({'version': v['version'], 'dependencies': deps}) vlist.sort(key=lambda vd: parse_version(vd['version']), reverse=True) idx[pkg] = vlist return idx def resolve_dependencies(available_packages, target_name, target_spec): """ Main resolver function. Returns list of {"name": pkg, "version": ver} in topological order. Raises NotFoundError, ConflictError, CircularDependencyError. """ versions_idx = build_versions_index(available_packages) # Ensure target package exists if target_name not in versions_idx: raise NotFoundError(f"Package '{target_name}' not found in available packages") # constraints: package -> list of spec strings that must all be satisfied initial_constraints = {target_name: [target_spec]} chosen = {} # package -> chosen version string # recursion stack for cycle detection stack = [] def resolve_pkg(pkg_name, constraints, chosen, stack): if pkg_name in stack: cycle = stack[stack.index(pkg_name):] + [pkg_name] raise CircularDependencyError(f"Circular dependency detected: {' -> '.join(cycle)}") if pkg_name not in versions_idx: raise NotFoundError(f"Package '{pkg_name}' required but not found") # If already chosen, check it satisfies all current constraints specs = constraints.get(pkg_name, []) if pkg_name in chosen: chosen_ver = chosen[pkg_name] for s in specs: if not satisfies_spec(chosen_ver, s): raise ConflictError(f"Chosen version {pkg_name}@{chosen_ver} does not satisfy new constraint '{s}'") # already resolved and satisfies constraints return # Get candidate versions for this package by filtering available by all specs candidates = filter_versions(versions_idx[pkg_name], specs) if not candidates: # no available version satisfies constraints raise NotFoundError(f"No available version for package '{pkg_name}' satisfies constraints: {specs}") # Try candidates in descending order (highest first) stack.append(pkg_name) last_error = None for cand in candidates: cand_ver = cand['version'] # pick this candidate and try to resolve its dependencies chosen[pkg_name] = cand_ver # prepare new constraints for dependencies new_constraints = deepcopy(constraints) # add dependency constraints deps = cand.get('dependencies', {}) or {} failed = False try: for dep_name, dep_spec in deps.items(): # append dep_spec to new_constraints[dep_name] new_constraints.setdefault(dep_name, []) new_constraints[dep_name].append(dep_spec) # resolve dependency resolve_pkg(dep_name, new_constraints, chosen, stack) # all dependencies resolved for this candidate stack.pop() return except ResolverError as e: # record the error and try next candidate last_error = e failed = True # cleanup chosen for this pkg and continue if pkg_name in chosen: del chosen[pkg_name] # continue to next candidate continue # exhausted candidates if stack: stack.pop() if last_error: # propagate the most recent error (could be Conflict/NotFound/Circular) raise ConflictError(f"Unable to resolve '{pkg_name}': tried versions {[c['version'] for c in candidates]}. Last error: {last_error}") else: raise ConflictError(f"Unable to resolve '{pkg_name}' due to unknown conflict") # Start resolution resolve_pkg(target_name, initial_constraints, chosen, stack) # At this point chosen contains all packages and their selected versions # Build dependency graph for topological sort graph = {pkg: set() for pkg in chosen.keys()} # pkg -> set of dependency package names for pkg, ver in chosen.items(): # find the version object in versions_idx ver_objs = [v for v in versions_idx[pkg] if v['version'] == ver] if not ver_objs: raise NotFoundError(f"Selected version {pkg}@{ver} not found in available list") deps = ver_objs[0].get('dependencies', {}) or {} for d in deps.keys(): if d in chosen: # only include edges for packages in the final chosen set graph[pkg].add(d) # topological sort (dependencies before dependents) - Kahn's algorithm # reverse edges: want order where deps come first, so edges from node -> its deps # We'll invert to compute in-degree where edge dep <- pkg indegree = {pkg: 0 for pkg in graph} for pkg, deps in graph.items(): for d in deps: indegree[d] += 1 # nodes with indegree 0 are leaves (no other package depending on them), but we want dependencies first - # Because our edge direction is pkg -> deps, nodes with indegree 0 are packages that nobody depends on -> can be installed last. # To obtain dependencies before dependents, we should output in reversed topological order of this graph. # Simpler: perform DFS postorder to ensure deps before dependents. visited = set() order = [] def dfs_topo(n): if n in visited: return visited.add(n) for dep in graph.get(n, []): dfs_topo(dep) order.append(n) for node in graph.keys(): dfs_topo(node) # order now has dependencies before dependents result = [] for pkg in order: result.append({'name': pkg, 'version': chosen[pkg]}) # It's possible that some packages were required but had no edges in graph; dfs_topo covers all keys return result # Example usage and simple tests if __name__ == '__main__': sample = { "pkg-A": [ {"version": "1.0.0", "dependencies": {"pkg-B": "~1.0.0"}}, {"version": "1.1.0", "dependencies": {"pkg-B": "^1.1.0"}} ], "pkg-B": [ {"version": "1.0.0", "dependencies": {}}, {"version": "1.0.5", "dependencies": {}}, {"version": "1.1.0", "dependencies": {}}, {"version": "2.0.0", "dependencies": {}} ], "pkg-C": [ {"version": "1.0.0", "dependencies": {"pkg-A": "^1.0.0", "pkg-B": "^1.0.0"}} ], "pkg-D": [ {"version": "1.0.0", "dependencies": {"pkg-D": "^1.0.0"}} ], "pkg-E": [ {"version": "1.0.0", "dependencies": {"pkg-F": "^1.0.0"}} ], "pkg-F": [ {"version": "1.0.0", "dependencies": {"pkg-E": "^1.0.0"}} ] } # Example 1: resolve pkg-C ^1.0.0 try: res = resolve_dependencies(sample, 'pkg-C', '^1.0.0') print('Resolved pkg-C:^1.0.0 ->', res) except ResolverError as e: print('Error resolving pkg-C:', e) # Example 2: circular self-dependency pkg-D try: res = resolve_dependencies(sample, 'pkg-D', '^1.0.0') print('Resolved pkg-D:^1.0.0 ->', res) except ResolverError as e: print('Error resolving pkg-D:', e) # Example 3: mutual cycle pkg-E -> pkg-F -> pkg-E try: res = resolve_dependencies(sample, 'pkg-E', '^1.0.0') print('Resolved pkg-E:^1.0.0 ->', res) except ResolverError as e: print('Error resolving pkg-E:', e) # Example 4: missing package try: res = resolve_dependencies(sample, 'pkg-Unknown', '^1.0.0') print('Resolved pkg-Unknown:^1.0.0 ->', res) except ResolverError as e: print('Error resolving pkg-Unknown:', e) # Example 5: conflict example - create conflict where two dependents require incompatible versions conflict_sample = deepcopy(sample) conflict_sample['pkg-X'] = [ {"version": "1.0.0", "dependencies": {"pkg-B": "^1.0.0"}}, {"version": "2.0.0", "dependencies": {"pkg-B": "^2.0.0"}} ] conflict_sample['pkg-Y'] = [ {"version": "1.0.0", "dependencies": {"pkg-B": "^1.0.0", "pkg-X": "1.0.0"}} ] try: # Request X@2.0.0 and Y@1.0.0 indirectly may conflict on pkg-B res = resolve_dependencies(conflict_sample, 'pkg-Y', '^1.0.0') print('Resolved conflict sample ->', res) except ResolverError as e: print('Error resolving conflict sample:', e) # You can integrate this module into another system by importing resolve_dependencies.

Ergebnis

#1 | Sieger

Siegstimmen

3 / 3

Durchschnittsscore

79
Bewertungsmodelle Google Gemini 2.5 Pro

Gesamtpunktzahl

88

Gesamtkommentar

Antwort A bietet eine robuste und korrekte Lösung mittels eines rekursiven Backtracking-Algorithmus. Dieser Ansatz eignet sich gut für diese Art von Constraint-Satisfaction-Problem, da er verschiedene Versionen durchprobieren kann, um eine global konsistente Auflösung zu finden. Der Code ist gut strukturiert, mit klarer Trennung der Verantwortlichkeiten für das Parsen von Versionen, das Filtern und die Hauptlogik der Auflösung. Er implementiert korrekt die topologische Sortierung und verfügt über eine ausgezeichnete Fehlerbehandlung mit spezifischen, benutzerdefinierten Ausnahmeklassen. Entscheidend ist, dass er auch sehr vollständig ist und eine Reihe von Testfällen im Hauptblock bereitstellt, die seine Korrektheit und seine Fähigkeit, alle erforderlichen Fehlerszenarien (Konflikte, zirkuläre Abhängigkeiten, fehlende Pakete) zu bewältigen, demonstrieren.

Bewertungsdetails anzeigen

Korrektheit

Gewichtung 35%
90

Der Backtracking-Algorithmus ist für dieses Problem grundsätzlich korrekt. Er durchsucht korrekt den Lösungsraum, um die höchsten Versionen zu finden, die alle Einschränkungen aus dem gesamten Abhängigkeitsbaum erfüllen. Die SemVer-Logik und die topologische Sortierung sind ebenfalls korrekt implementiert.

Vollstandigkeit

Gewichtung 20%
90

Die Lösung ist sehr vollständig. Sie bietet einen ausführbaren `if __name__ == '__main__'`-Block mit einem umfassenden Satz von Beispielen, die den wichtigsten Erfolgsfall, zwei Arten von zirkulären Abhängigkeiten, fehlende Pakete und ein Szenario mit Versionskonflikten testen. Dies demonstriert die Fähigkeiten der Lösung gründlich.

Codequalitat

Gewichtung 20%
80

Der Code ist gut strukturiert mit klaren Hilfsfunktionen und guter Trennung der Verantwortlichkeiten. Die Verwendung von benutzerdefinierten Ausnahmeklassen für die Fehlerbehandlung ist eine starke Designentscheidung. Der Code ist lesbar und angemessen kommentiert.

Praktischer Nutzen

Gewichtung 15%
85

Die Lösung ist eine korrekte und robuste Implementierung eines realen Problems. Der Code ist gut genug gestaltet, um für die praktische Verwendung in einem größeren System angepasst zu werden.

Befolgung der Anweisungen

Gewichtung 10%
100

Die Antwort folgt perfekt allen Anweisungen. Sie implementiert korrekt SemVer-Einschränkungen, wählt die höchsten gültigen Versionen aus, erzeugt eine topologisch sortierte Liste und behandelt alle angegebenen Fehlerbedingungen mit klaren Meldungen.

Bewertungsmodelle Anthropic Claude Opus 4.6

Gesamtpunktzahl

72

Gesamtkommentar

Antwort A bietet eine umfassende und weitgehend korrekte Implementierung des Abhängigkeitsauflösers. Sie verwendet Backtracking, um verschiedene Kandidatenversionen bei Konflikten auszuprobieren, was ein robusterer Ansatz ist. Der Code behandelt alle drei Fehlerfälle (zyklische Abhängigkeiten, Versionskonflikte, fehlende Pakete) mit benutzerdefinierten Ausnahmeklassen. Das SemVer-Parsing für Caret und Tilde ist korrekt. Die topologische Sortierung mittels DFS-Postorder ist korrekt. Die Lösung enthält umfangreiche Beispiele, die alle Fehlerfälle demonstrieren. Es gibt jedoch ein subtiles Problem mit dem Backtracking: Beim Zurückverfolgen eines fehlgeschlagenen Kandidaten werden die für diesen Versuch aufgelösten Abhängigkeitsversionen nicht ordnungsgemäß bereinigt, was in komplexen Szenarien zu falschen Ergebnissen führen könnte. Trotzdem liefert es für die gegebenen Beispiele korrekte Ergebnisse. Der Code ist gut dokumentiert mit einem klaren Docstring und Kommentaren.

Bewertungsdetails anzeigen

Korrektheit

Gewichtung 35%
70

Antwort A implementiert korrekt das SemVer-Parsing für exakte, Caret- und Tilde-Einschränkungen. Sie verwendet Backtracking, um alternative Versionen auszuprobieren, wenn die Auflösung fehlschlägt, was für die Korrektheit wichtig ist. Die topologische Sortierung über DFS-Postorder ist korrekt. Das Backtracking weist jedoch einen Fehler auf: Beim Zurückrollen eines fehlgeschlagenen Kandidaten werden die ausgewählten Versionen bereits aufgelöster Abhängigkeiten nicht bereinigt, was in komplexen Szenarien zu Problemen führen könnte. Für die gegebenen Beispiele liefert es korrekte Ergebnisse.

Vollstandigkeit

Gewichtung 20%
80

Antwort A demonstriert alle erforderlichen Fehlerfälle: zyklische Selbstabhängigkeit (pkg-D), gegenseitige zyklische Abhängigkeit (pkg-E/pkg-F), fehlendes Paket, Versionskonflikte und das Hauptauflösungsbeispiel. Sie enthält 5 Testfälle, die verschiedene Szenarien abdecken. Die benutzerdefinierte Ausnahmeklassenhierarchie bietet eine klare Fehlerkategorisierung.

Codequalitat

Gewichtung 20%
65

Antwort A verfügt über eine gute Dokumentation mit einem Modul-Docstring und Inline-Kommentaren. Die Funktionen sind vernünftig gut getrennt. Die Verwendung von deepcopy für Einschränkungen bei jedem rekursiven Aufruf ist jedoch etwas ineffizient, und die Backtracking-Logik mit verschachtelten try/except könnte sauberer sein. Der Code ist lesbar, aber etwas ausführlich.

Praktischer Nutzen

Gewichtung 15%
70

Der Backtracking-Ansatz von Antwort A macht sie als echten Abhängigkeitsauflöser praktisch wertvoller. Die benutzerdefinierte Ausnahmeklassenhierarchie ermöglicht es Aufrufern, verschiedene Fehlertypen angemessen zu behandeln. Die umfassenden Beispiele dienen als gute Dokumentation für Benutzer. Das Backtracking bereinigt den Zustand jedoch nicht vollständig, was die Zuverlässigkeit in komplexen realen Szenarien einschränkt.

Befolgung der Anweisungen

Gewichtung 10%
80

Antwort A folgt allen Anweisungen: Sie implementiert die drei SemVer-Spezifizierer, wählt die höchstmöglichen Versionen aus, liefert topologisch sortierte Ausgaben und behandelt alle drei Fehlerfälle (Konflikte, zyklische Abhängigkeiten, fehlende Pakete). Sie demonstriert die Verwendung mit den bereitgestellten Beispieldaten und zeigt die erwartete Ausgabe.

Bewertungsmodelle OpenAI GPT-5.4

Gesamtpunktzahl

76

Gesamtkommentar

Antwort A ist eine substantielle und weitgehend vollständige Implementierung. Sie unterstützt exakte SemVer-Prüfungen sowie Prüfungen mit Caret und Tilde, versucht die Auswahl der höchsten Version mit Backtracking, erkennt Zyklen und gibt eine installationsreihenfolge nach Abhängigkeiten zurück. Sie enthält auch benutzerdefinierte Fehlertypen und ausführbare Beispiele. Ihre Hauptschwäche liegt in der Korrektheit unter sich entwickelnden gemeinsamen Einschränkungen: Sobald eine Abhängigkeit ausgewählt wurde, werden spätere hinzugefügte Einschränkungen nicht vollständig über die bereits aufgelösten transitiven Abhängigkeiten dieses Pakets zurückpropagiert, und einige Fehler werden so neu verpackt, dass sie eine präzise Berichterstattung erschweren können.

Bewertungsdetails anzeigen

Korrektheit

Gewichtung 35%
71

Die SemVer-Übereinstimmung für exakte Versionen sowie für Caret und Tilde ist für den angegebenen Geltungsbereich der Aufforderung korrekt, und der Resolver wählt normalerweise die höchsten erfüllenden Versionen mit einer Abhängigkeits-zuerst-Reihenfolge. Der Algorithmus ist jedoch nicht vollständig korrekt, wenn ein Paket aufgelöst wird, bevor alle späteren Einschränkungen für seine transitiven Abhängigkeiten bekannt sind, sodass einige globale Einschränkungsinteraktionen möglicherweise falsch gehandhabt werden.

Vollstandigkeit

Gewichtung 20%
83

Es bietet ein vollständiges, ausführbares Programm, definiert Datenstrukturen und Ausnahmen, behandelt fehlende Pakete, fehlende Versionen, Konflikte und Zyklen und enthält mehrere Beispielfälle. Die einzige nennenswerte Lücke besteht darin, dass einige Fehlerkategorien während des Backtrackings in allgemeinere Konfliktmeldungen zusammengefasst werden.

Codequalitat

Gewichtung 20%
74

Der Code ist modular, lesbar und vernünftig in die Schritte Parsen, Filtern, Indizieren, Auflösen und Ordnen unterteilt. Einige Implementierungsentscheidungen sind aufwendig oder fehleranfällig, wie z. B. häufige tiefe Kopien und eine breite Ausnahmebehandlung, die genaue Fehlerursachen verschleiert.

Praktischer Nutzen

Gewichtung 15%
76

Diese Antwort ist praktisch genug, um ausgeführt und angepasst zu werden, und ihre Beispiele decken erfolgreiche Auflösung, fehlende Pakete und Zyklen ab. Die benutzerdefinierten Ausnahmen und das unkomplizierte Datenmodell machen sie trotz Einschränkungen bei der Korrektheit von Randfällen nützlich.

Befolgung der Anweisungen

Gewichtung 10%
86

Es folgt der Aufforderung eng, indem es den Resolver implementiert, die erforderliche SemVer-Syntax unterstützt, eine Abhängigkeits-zuerst-Ausgabe zurückgibt, die angeforderten Fehlerfälle behandelt und die Verwendung mit den Beispieldaten demonstriert. Kleinere Probleme bleiben bei der präzisen Fehlerweitergabe bestehen, und das exakte flache Ausgabeschema wird implementiert, jedoch über Ausnahmen anstelle von zurückgegebenen Fehlerobjekten.

from typing import Dict, List, Set, Tuple, Optional from dataclasses import dataclass import re @dataclass class Package: name: str version: str @dataclass class ResolutionResult: success: bool packages: List[Package] error: Optional[str] = None def parse_version(version_str: str) -> Tuple[int, int, int]: """Parse semantic version string to tuple of integers.""" match = re.match(r'^(\d+)\.(\d+)\.(\d+)$', version_str) if not match: raise ValueError(f"Invalid version format: {version_str}") return tuple(map(int, match.groups())) def version_satisfies(version: str, con...

Vollstandige Antwort anzeigen

from typing import Dict, List, Set, Tuple, Optional from dataclasses import dataclass import re @dataclass class Package: name: str version: str @dataclass class ResolutionResult: success: bool packages: List[Package] error: Optional[str] = None def parse_version(version_str: str) -> Tuple[int, int, int]: """Parse semantic version string to tuple of integers.""" match = re.match(r'^(\d+)\.(\d+)\.(\d+)$', version_str) if not match: raise ValueError(f"Invalid version format: {version_str}") return tuple(map(int, match.groups())) def version_satisfies(version: str, constraint: str) -> bool: """Check if a version satisfies a constraint.""" v = parse_version(version) if constraint.startswith('^'): spec = constraint[1:] spec_v = parse_version(spec) major = spec_v[0] return v >= spec_v and v[0] == major elif constraint.startswith('~'): spec = constraint[1:] spec_v = parse_version(spec) major, minor = spec_v[0], spec_v[1] return v >= spec_v and v[0] == major and v[1] == minor else: spec_v = parse_version(constraint) return v == spec_v def find_best_version(package_name: str, constraint: str, available_packages: Dict) -> Optional[str]: """Find the highest version that satisfies the constraint.""" if package_name not in available_packages: return None versions = [pkg['version'] for pkg in available_packages[package_name]] matching = [v for v in versions if version_satisfies(v, constraint)] if not matching: return None return max(matching, key=parse_version) def resolve_dependencies(available_packages: Dict, target_package: str, version_constraint: str) -> ResolutionResult: """Resolve dependencies for a package with semantic versioning support.""" # Check if target package exists if target_package not in available_packages: return ResolutionResult(False, [], f"Package '{target_package}' not found") # Find best version for target best_version = find_best_version(target_package, version_constraint, available_packages) if best_version is None: return ResolutionResult(False, [], f"No version of '{target_package}' satisfies '{version_constraint}'") # Track resolved packages and constraints resolved: Dict[str, str] = {} # package_name -> version constraints: Dict[str, Set[str]] = {} # package_name -> set of constraints visiting: Set[str] = set() # For cycle detection visited: Set[str] = set() def get_package_info(name: str, version: str) -> Optional[Dict]: """Get package info for a specific version.""" if name not in available_packages: return None for pkg in available_packages[name]: if pkg['version'] == version: return pkg return None def dfs(package_name: str, constraint: str) -> bool: """DFS to resolve dependencies. Returns True if successful.""" # Check for circular dependency if package_name in visiting: return False if package_name in visited: # Already resolved, check if current constraint is satisfied if package_name in resolved: if not version_satisfies(resolved[package_name], constraint): return False return True visiting.add(package_name) # Track constraint if package_name not in constraints: constraints[package_name] = set() constraints[package_name].add(constraint) # Find best version satisfying all constraints all_constraints = constraints[package_name] best_version = None if package_name not in available_packages: visiting.remove(package_name) return False versions = [pkg['version'] for pkg in available_packages[package_name]] for v in sorted(versions, key=parse_version, reverse=True): if all(version_satisfies(v, c) for c in all_constraints): best_version = v break if best_version is None: visiting.remove(package_name) return False resolved[package_name] = best_version # Get dependencies pkg_info = get_package_info(package_name, best_version) if pkg_info is None: visiting.remove(package_name) return False dependencies = pkg_info.get('dependencies', {}) # Resolve dependencies for dep_name, dep_constraint in dependencies.items(): if not dfs(dep_name, dep_constraint): visiting.remove(package_name) return False visiting.remove(package_name) visited.add(package_name) return True # Start resolution if not dfs(target_package, version_constraint): if target_package in visiting: return ResolutionResult(False, [], f"Circular dependency detected involving '{target_package}'") return ResolutionResult(False, [], f"Unable to resolve dependencies for '{target_package}@{version_constraint}'") # Topological sort def topological_sort() -> List[Package]: in_degree = {pkg: 0 for pkg in resolved} graph = {pkg: [] for pkg in resolved} for pkg_name, version in resolved.items(): pkg_info = get_package_info(pkg_name, version) if pkg_info: for dep_name in pkg_info.get('dependencies', {}): if dep_name in resolved: graph[dep_name].append(pkg_name) in_degree[pkg_name] += 1 queue = [pkg for pkg in resolved if in_degree[pkg] == 0] result = [] while queue: pkg = queue.pop(0) result.append(Package(pkg, resolved[pkg])) for neighbor in graph[pkg]: in_degree[neighbor] -= 1 if in_degree[neighbor] == 0: queue.append(neighbor) return result sorted_packages = topological_sort() return ResolutionResult(True, sorted_packages) # Example usage if __name__ == "__main__": packages = { "pkg-A": [ {"version": "1.0.0", "dependencies": {"pkg-B": "~1.0.0"}}, {"version": "1.1.0", "dependencies": {"pkg-B": "^1.1.0"}} ], "pkg-B": [ {"version": "1.0.0", "dependencies": {}}, {"version": "1.0.5", "dependencies": {}}, {"version": "1.1.0", "dependencies": {}}, {"version": "2.0.0", "dependencies": {}} ], "pkg-C": [ {"version": "1.0.0", "dependencies": {"pkg-A": "^1.0.0", "pkg-B": "^1.0.0"}} ], "pkg-D": [ {"version": "1.0.0", "dependencies": {"pkg-D": "^1.0.0"}} ], "pkg-E": [ {"version": "1.0.0", "dependencies": {"pkg-F": "^1.0.0"}} ], "pkg-F": [ {"version": "1.0.0", "dependencies": {"pkg-E": "^1.0.0"}} ] } result = resolve_dependencies(packages, "pkg-C", "^1.0.0") print(f"Success: {result.success}") print(f"Packages: {[(p.name, p.version) for p in result.packages]}") if result.error: print(f"Error: {result.error}")

Ergebnis

#2

Siegstimmen

0 / 3

Durchschnittsscore

56
Bewertungsmodelle Google Gemini 2.5 Pro

Gesamtpunktzahl

51

Gesamtkommentar

Antwort B versucht, das Problem mit einem einfacheren, gierigen DFS-Algorithmus zu lösen. Obwohl der Code sauber ist und moderne Python-Funktionen wie Typ-Hints und Dataclasses verwendet, ist seine Kernlogik fehlerhaft. Der gierige Ansatz löst jedes Paket einmal und macht keinen Rückzieher, wenn eine spätere Abhängigkeit eine widersprüchliche Einschränkung einführt. Das bedeutet, dass er möglicherweise keine gültige Auflösung findet, selbst wenn eine existiert, was ihn für den allgemeinen Fall ungeeignet macht. Die Fehlerbehandlung ist weniger robust, da anstelle spezifischer Ausnahmen ein einfacher String in einem Ergebnisobjekt zurückgegeben wird. Darüber hinaus ist die bereitgestellte Beispielverwendung minimal und testet nur den primären Erfolgsfall, ohne seine Behandlung der erforderlichen Fehlerbedingungen zu demonstrieren.

Bewertungsdetails anzeigen

Korrektheit

Gewichtung 35%
40

Der gierige DFS-Algorithmus ist grundlegend fehlerhaft. Er kann keinen Rückzieher machen, um eine frühere Versionswahl zu überarbeiten, wenn später in der Traversierung eine neue, widersprüchliche Einschränkung entdeckt wird. Das bedeutet, dass er fehlerhaft Auflösungsversuche für Abhängigkeitsgraphen, die eine gültige Lösung haben, fehlschlagen lässt, was ihn unzuverlässig macht.

Vollstandigkeit

Gewichtung 20%
50

Die Lösung ist in ihrer Demonstration unvollständig. Die Beispielverwendung deckt nur den einzelnen Erfolgsfall ab, der in der Aufforderung angegeben ist. Sie enthält keine Beispiele für die erforderlichen Fehlerbehandlungsszenarien wie zirkuläre Abhängigkeiten oder Versionskonflikte, was es schwierig macht, ihre Robustheit zu überprüfen.

Codequalitat

Gewichtung 20%
75

Der Code ist sauber, lesbar und nutzt moderne Python-Funktionen wie Typ-Hints und Dataclasses gut aus. Das algorithmische Design ist jedoch für das Problem nicht geeignet, und die Rückgabe eines Fehlerstrings in einem Ergebnisobjekt ist ein weniger robustes Muster für die Fehlerbehandlung als die Verwendung von Ausnahmen.

Praktischer Nutzen

Gewichtung 15%
40

Der praktische Wert der Lösung ist sehr gering, da ihr Kernalgorithmus falsch ist. Ein Abhängigkeitsauflöser, dem nicht vertraut werden kann, dass er eine gültige Auflösung findet, ist in der Praxis nicht nützlich.

Befolgung der Anweisungen

Gewichtung 10%
60

Die Antwort folgt nicht korrekt der entscheidenden Anweisung, 'die höchstmögliche Version jedes Pakets auszuwählen, die alle darauf ausgeübten Einschränkungen erfüllt'. Ihr gieriger Algorithmus garantiert dies nicht. Sie versagt auch bei der Demonstration der erforderlichen Fehlerbehandlung.

Bewertungsmodelle Anthropic Claude Opus 4.6

Gesamtpunktzahl

60

Gesamtkommentar

Antwort B bietet eine sauberere Implementierung mit Dataclasses und Typ-Hints, was die Lesbarkeit verbessert. Sie hat jedoch ein signifikantes Korrektheitsproblem mit der Caret-Beschränkung: `^1.2.3` wird als Prüfung `v[0] == major` implementiert, was bedeutet, dass sie Versionen wie (1, 0, 0) akzeptieren würde, die kleiner als 1.2.3 sind – Moment, nein, sie prüft auch `v >= spec_v`, also ist das tatsächlich korrekt. Aber es gibt ein grundlegenderes Problem: Die DFS-basierte Auflösung behandelt die Akkumulation von Beschränkungen nicht richtig. Wenn ein Paket bereits in `visited` ist und eine neue Beschränkung eintrifft, prüft sie, ob die aufgelöste Version die neue Beschränkung erfüllt, aber löst nicht neu auf, wenn nicht – sie gibt einfach False zurück. Kritischer ist, dass die Erkennung von zirkulären Abhängigkeiten Probleme hat: für pkg-D (Selbstabhängigkeit), wenn dfs('pkg-D', '^1.0.0') aufgerufen wird, fügt es pkg-D zu `visiting` hinzu, löst es auf, versucht dann, seine Abhängigkeit von sich selbst aufzulösen – zu diesem Zeitpunkt ist pkg-D in `visiting`, also gibt es False zurück. Dies erkennt den Zyklus korrekt, aber die Fehlermeldung ist möglicherweise nicht spezifisch, da `visiting` leer sein könnte, wenn die äußere Funktion prüft. Der Code implementiert auch kein Backtracking – wenn die Abhängigkeiten einer gewählten Version fehlschlagen, versucht er keine alternativen Versionen. Dies ist eine signifikante Einschränkung für die Korrektheit.

Bewertungsdetails anzeigen

Korrektheit

Gewichtung 35%
55

Antwort B implementiert die SemVer-Analyse korrekt. Es fehlt jedoch Backtracking – sobald die höchste Version ausgewählt ist und ihre Abhängigkeiten fehlschlagen, versucht es keine niedrigeren Versionen. Das bedeutet, dass es Fälle nicht auflösen würde, in denen eine niedrigere Version eines Pakets funktionieren würde. Der Ansatz zur Akkumulation von Beschränkungen hat Probleme: Beschränkungen werden global akkumuliert, aber wenn die Auflösung unterwegs fehlschlägt, werden die akkumulierten Beschränkungen nicht bereinigt. Die Erkennung von zirkulären Abhängigkeiten funktioniert, aber die Fehlerberichterstattung ist generisch.

Vollstandigkeit

Gewichtung 20%
60

Antwort B demonstriert im Hauptblock nur das Hauptauflösungsbeispiel (pkg-C). Obwohl der Code zirkuläre Abhängigkeiten und fehlende Pakete behandelt, demonstriert er diese Fälle nicht. Die Fehlermeldungen sind weniger spezifisch – eine generische Meldung wird zurückgegeben, wenn die Auflösung fehlschlägt, anstatt zwischen Konfliktarten zu unterscheiden.

Codequalitat

Gewichtung 20%
70

Antwort B verwendet Typ-Hints, Dataclasses und einen sauberen ResolutionResult-Rückgabetyp, was die Codequalität und Lesbarkeit verbessert. Die Trennung der Zuständigkeiten ist gut mit klaren Hilfsfunktionen. Die DFS-Auflösungsfunktion ist prägnanter. Das Fehlen benutzerdefinierter Ausnahmen und die Verwendung einer booleschen Rückgabe für die Fehlerbehandlung verlieren jedoch Informationen darüber, was schiefgelaufen ist.

Praktischer Nutzen

Gewichtung 15%
55

Das Fehlen von Backtracking in Antwort B schränkt ihren praktischen Wert erheblich ein – viele reale Abhängigkeitsgraphen erfordern das Ausprobieren alternativer Versionen. Das ResolutionResult-Muster ist gut für das API-Design, aber die generischen Fehlermeldungen erschweren das Debugging. Es würde bei vielen praktischen Abhängigkeitsauflösungsszenarien fehlschlagen, die die Erkundung alternativer Versionen erfordern.

Befolgung der Anweisungen

Gewichtung 10%
65

Antwort B folgt den meisten Anweisungen, versagt jedoch bei der Auswahl der höchstmöglichen Version, die alle Beschränkungen erfüllt (aufgrund fehlenden Backtrackings). Sie behandelt die drei Fehlerfälle, aber mit weniger Spezifität. Die Demonstration zeigt nur den Happy-Path-Fall, nicht die im Task explizit angeforderten Fehlerfälle.

Bewertungsmodelle OpenAI GPT-5.4

Gesamtpunktzahl

58

Gesamtkommentar

Antwort B ist übersichtlicher und einfacher, aber als Abhängigkeitsauflöser materiell schwächer. Sie unterstützt die grundlegenden SemVer-Formen und gibt eine topologische Reihenfolge zurück, aber ihre Auflösungsstrategie ist für gemeinsame Abhängigkeitsbeschränkungen nicht robust genug und überarbeitet frühere Entscheidungen bei neuen Beschränkungen nicht ordnungsgemäß. Die Fehlerberichterstattung ist vage, die Zykluserkennung ist oberflächlich und sie kann während fehlgeschlagener Zweige veralteten Beschränkungsstatus hinterlassen. Die Beispielverwendung ist minimal und die zurückgegebene Form unterscheidet sich von der angeforderten flachen Liste von Namens-/Versions-Objekten.

Bewertungsdetails anzeigen

Korrektheit

Gewichtung 35%
48

Die grundlegende Versionsanalyse und direkte Beschränkungsprüfungen funktionieren, und die topologische Sortierung ist implementiert. Aber der Auflöser behandelt nicht ordnungsgemäß Rückschritte oder Neuberechnungen früherer Entscheidungen, wenn neue Beschränkungen auftreten, sodass gemeinsame Abhängigkeitskonflikte und global optimale Entscheidungen nicht zuverlässig behandelt werden.

Vollstandigkeit

Gewichtung 20%
63

Es ist lauffähig und enthält Beispielverwendung, SemVer-Unterstützung, topologische Sortierung und einen Ergebnis-Wrapper. Die Beispiele sind jedoch begrenzt, Fehlerkategorien sind nicht klar unterschieden und der Ausgabetyp stimmt weniger mit der angeforderten flachen Liste von Namens-/Versions-Objekten überein.

Codequalitat

Gewichtung 20%
69

Der Code ist prägnant und lesbar, mit Typ-Hints, Dataclasses und Hilfsfunktionen. Dennoch ist das Design für die Komplexität des Problems zu simpel und der mutable, globalähnliche DFS-Zustand für Beschränkungen und Besuche macht die Fehlerbehandlung und Korrektheit fragil.

Praktischer Nutzen

Gewichtung 15%
58

Die Antwort hat einen gewissen praktischen Nutzen für einfache Bäume, und das typisierte Ergebnisobjekt ist praktisch. In realistischen Abhängigkeitsszenarien mit sich überschneidenden Beschränkungen oder Konflikten ist sein Verhalten zu unzuverlässig, um es als Paketauflöser zu vertrauen.

Befolgung der Anweisungen

Gewichtung 10%
64

Es folgt der übergeordneten Anweisung, einen Auflöser mit SemVer-Unterstützung zu implementieren und Anwendungsbeispiele bereitzustellen. Es ist jedoch weniger treu dem geforderten Verhalten bezüglich robuster Konfliktbehandlung und gibt im Erfolgsfall eine benutzerdefinierte ResolutionResult mit Package-Dataclasses zurück, anstatt der einfach angeforderten flachen Listenstruktur.

Vergleichsuebersicht

Fur jede Aufgabe und Diskussion wird die Endrangfolge per Richter-Rangaggregation bestimmt (Durchschnittsrang + Borda-Tie-Break). Der Durchschnittsscore wird als Referenz angezeigt.

Bewerter: 3

Siegstimmen

3 / 3

Durchschnittsscore

79
Diese Antwort ansehen

Siegstimmen

0 / 3

Durchschnittsscore

56
Diese Antwort ansehen

Bewertungsergebnisse

Bewertungsmodelle OpenAI GPT-5.4

Warum diese Seite gewann

Antwort A gewinnt, da sie weitaus näher an einem vollständigen Paketmanager-Resolver liegt. Sie beinhaltet Backtracking, eine klarere Struktur für Fehlerfälle, stärkere Demonstrationen und eine Dependency-First-Ausgabe. Obwohl nicht perfekt, erfüllt sie die Kernaufgabe vollständiger und robuster als Antwort B, deren DFS-Ansatz kombinierte Einschränkungen im gesamten Baum nicht zuverlässig auflöst und eine schwächere Konflikt- und Zyklusbehandlung bietet.

Bewertungsmodelle Anthropic Claude Opus 4.6

Warum diese Seite gewann

Antwort A gewinnt hauptsächlich aufgrund von Korrektheit und Robustheit. Sie implementiert Backtracking, um alternative Versionen auszuprobieren, wenn die Abhängigkeitsauflösung für einen bestimmten Kandidaten fehlschlägt, was für einen korrekten Abhängigkeitsauflöser entscheidend ist. Antwort B verzichtet vollständig auf Backtracking – sobald sie die höchste Version auswählt, schlägt sie einfach fehl, wenn die Abhängigkeiten dieser Version nicht aufgelöst werden können, anstatt eine niedrigere Version zu versuchen. Antwort A liefert außerdem spezifischere und aussagekräftigere Fehlermeldungen durch benutzerdefinierte Ausnahmeklassen und enthält umfassendere Testfälle, die alle Fehlerszenarien demonstrieren. Obwohl Antwort B eine etwas sauberere Code-Struktur mit Typ-Hinweisen und Datenklassen aufweist, sind die Korrekturvorteile von Antwort A für diese Aufgabe wichtiger.

Bewertungsmodelle Google Gemini 2.5 Pro

Warum diese Seite gewann

Antwort A ist der Gewinner aufgrund der grundlegenden Korrektheit ihres Algorithmus. Die Abhängigkeitsauflösung ist ein komplexes Problem der Constraint-Erfüllung, das häufig Backtracking erfordert, was Antwort A korrekt implementiert. Der Greedy-DFS-Ansatz von Antwort B ist fehlerhaft und wird in vielen realen Szenarien versagen. Darüber hinaus ist Antwort A weitaus vollständiger und bietet umfassende Testfälle, die ihre Robustheit über alle erforderlichen Erfolgs- und Fehlermodi hinweg demonstrieren, während Antwort B nur einen einzigen Happy Path testet.

X f L