Orivel Orivel
Ouvrir le menu

Implémenter un ordonnanceur de tâches basé sur les dépendances en Python

Comparez les réponses des modèles pour cette tâche de benchmark en Programmation et consultez scores, commentaires et exemples liés.

Connectez-vous ou inscrivez-vous pour utiliser les likes et favoris. Inscription

X f L

Sommaire

Vue d ensemble de la tache

Genres de comparaison

Programmation

Modele createur de la tache

Modeles participants

Modeles evaluateurs

Consigne de la tache

Écrivez une fonction ou une classe Python qui planifie une liste de tâches en fonction de leurs dépendances. L'ordonnanceur doit déterminer l'ordre dans lequel les tâches peuvent être exécutées, en regroupant les tâches qui peuvent s'exécuter en parallèle. L'entrée sera une liste de dictionnaires, où chaque dictionnaire représente une tâche avec les clés suivantes : - `id` : un identifiant unique de type chaîne pour la tâche. - `name` : un nom de la tâche sous forme de chaîne. - `dependencies` : une liste d'identi...

Afficher plus

Écrivez une fonction ou une classe Python qui planifie une liste de tâches en fonction de leurs dépendances. L'ordonnanceur doit déterminer l'ordre dans lequel les tâches peuvent être exécutées, en regroupant les tâches qui peuvent s'exécuter en parallèle. L'entrée sera une liste de dictionnaires, où chaque dictionnaire représente une tâche avec les clés suivantes : - `id` : un identifiant unique de type chaîne pour la tâche. - `name` : un nom de la tâche sous forme de chaîne. - `dependencies` : une liste d'identifiants (chaînes) des tâches qui doivent être terminées avant que cette tâche puisse commencer. Votre implémentation doit : 1. Prendre la liste de dictionnaires de tâches en entrée. 2. Retourner un plan d'exécution valide sous forme d'une liste de listes. Chaque liste interne représente un "lot" (batch) de tâches qui peuvent être exécutées simultanément. L'ordre des lots représente l'ordre d'exécution séquentiel. L'ordre des identifiants de tâches au sein d'un lot n'a pas d'importance. 3. Détecter et gérer les dépendances circulaires. Si un cycle est détecté, la fonction doit lever une `ValueError` avec un message descriptif. 4. Détecter et gérer les cas où un identifiant de dépendance ne correspond à aucune tâche existante. Cela doit également lever une `ValueError`.

Informations complementaires

Voici un exemple de la structure de données d'entrée : ```python tasks = [ {'id': 'A', 'name': 'Data Ingestion', 'dependencies': []}, {'id': 'B', 'name': 'Data Cleaning', 'dependencies': ['A']}, {'id': 'C', 'name': 'Feature Engineering', 'dependencies': ['A']}, {'id': 'D', 'name': 'Model Training', 'dependencies': ['B', 'C']}, {'id': 'E', 'name': 'Setup Logging', 'dependencies': []}, {'id': 'F', 'name': 'Model Deployment', 'dependencies': ['D']}, ] ``` Une sortie valide pour cette entrée ser...

Afficher plus

Voici un exemple de la structure de données d'entrée : ```python tasks = [ {'id': 'A', 'name': 'Data Ingestion', 'dependencies': []}, {'id': 'B', 'name': 'Data Cleaning', 'dependencies': ['A']}, {'id': 'C', 'name': 'Feature Engineering', 'dependencies': ['A']}, {'id': 'D', 'name': 'Model Training', 'dependencies': ['B', 'C']}, {'id': 'E', 'name': 'Setup Logging', 'dependencies': []}, {'id': 'F', 'name': 'Model Deployment', 'dependencies': ['D']}, ] ``` Une sortie valide pour cette entrée serait : `[['A', 'E'], ['B', 'C'], ['D'], ['F']]` Un autre exemple avec une structure différente : ```python tasks = [ {'id': 'checkout', 'dependencies': []}, {'id': 'build', 'dependencies': ['checkout']}, {'id': 'unit_test', 'dependencies': ['build']}, {'id': 'integration_test', 'dependencies': ['build']}, {'id': 'deploy', 'dependencies': ['unit_test', 'integration_test']}, ] ``` Une sortie valide pour cette entrée serait : `[['checkout'], ['build'], ['unit_test', 'integration_test'], ['deploy']]`

Politique d evaluation

Une solution de haute qualité doit être fonctionnellement correcte et robuste. - **Correctness :** Le calendrier généré doit refléter fidèlement les dépendances des tâches. Toutes les tâches doivent être incluses dans la sortie exactement une fois, et aucune tâche ne doit être planifiée avant que ses dépendances ne soient satisfaites. - **Error Handling :** La solution doit identifier correctement et lever une `ValueError` à la fois pour les dépendances circulaires et pour les références à des tâches dépendantes in...

Afficher plus

Une solution de haute qualité doit être fonctionnellement correcte et robuste. - **Correctness :** Le calendrier généré doit refléter fidèlement les dépendances des tâches. Toutes les tâches doivent être incluses dans la sortie exactement une fois, et aucune tâche ne doit être planifiée avant que ses dépendances ne soient satisfaites. - **Error Handling :** La solution doit identifier correctement et lever une `ValueError` à la fois pour les dépendances circulaires et pour les références à des tâches dépendantes inexistantes. Les messages d'erreur doivent être clairs et informatifs. - **Algorithm Choice :** L'implémentation doit utiliser un algorithme efficace pour le tri topologique, tel que l'algorithme de Kahn (Kahn's algorithm) ou une approche basée sur le DFS. Les solutions inefficaces ou par force brute seront mal évaluées. - **Code Quality :** Le code doit être propre, bien structuré et lisible. Il doit respecter les conventions Python standard (PEP 8). L'utilisation de structures de données appropriées (par exemple des dictionnaires pour la représentation du graphe, des ensembles (sets) pour des recherches efficaces) est attendue. - **Output Format :** La sortie doit strictement correspondre au format spécifié : une liste de listes de chaînes pour un planning valide, ou une `ValueError` levée pour un graphe de tâches invalide.

Reponses

Planificateur de tâches basé sur les dépendances.

Produit un plan d'exécution sous forme de liste de lots (listes d'identifiants de tâches), où chaque tâche d'un lot peut s'exécuter simultanément, et les lots doivent s'exécuter séquentiellement. Utilise l'algorithme de Kahn (tri topologique niveau par niveau).

Lève une ValueError en cas de :

  • identifiants de tâches dupliqués,
  • dépendances faisant référence à des identifiants de tâches inconnus,
  • dépendances circulaires (avec les tâches fautives listées).

from collections import deque
from typing import Dict, List

class TaskScheduler:
"""Planifie...

Afficher la reponse complete

Planificateur de tâches basé sur les dépendances.

Produit un plan d'exécution sous forme de liste de lots (listes d'identifiants de tâches), où chaque tâche d'un lot peut s'exécuter simultanément, et les lots doivent s'exécuter séquentiellement. Utilise l'algorithme de Kahn (tri topologique niveau par niveau).

Lève une ValueError en cas de :

  • identifiants de tâches dupliqués,
  • dépendances faisant référence à des identifiants de tâches inconnus,
  • dépendances circulaires (avec les tâches fautives listées).

from collections import deque
from typing import Dict, List

class TaskScheduler:
"""Planifie les tâches en lots parallélisables en fonction des dépendances."""

def __init__(self, tasks: List[dict]):
    self.tasks = tasks
    self._validate_and_build_graph()

def _validate_and_build_graph(self) -> None:
    # Collecte tous les identifiants de tâches et vérifie les doublons.
    self.task_ids = set()
    for task in self.tasks:
        if 'id' not in task:
            raise ValueError(f"La tâche est manquante de la clé 'id' requise : {task!r}")
        task_id = task['id']
        if task_id in self.task_ids:
            raise ValueError(f"Identifiant de tâche dupliqué trouvé : '{task_id}'")
        self.task_ids.add(task_id)

    # Construit la liste d'adjacence (dépendance -> dépendants) et la carte des degrés entrants.
    self.dependents: Dict[str, List[str]] = {tid: [] for tid in self.task_ids}
    self.in_degree: Dict[str, int] = {tid: 0 for tid in self.task_ids}

    for task in self.tasks:
        task_id = task['id']
        for dep in task.get('dependencies') or []:
            if dep not in self.task_ids:
                raise ValueError(
                    f"La tâche '{task_id}' dépend de l'identifiant de tâche inconnu '{dep}'"
                )
            if dep == task_id:
                raise ValueError(
                    f"La tâche '{task_id}' dépend d'elle-même (dépendance circulaire)"
                )
            self.dependents[dep].append(task_id)
            self.in_degree[task_id] += 1

def schedule(self) -> List[List[str]]:
    """
    Retourne le plan d'exécution sous forme de liste de lots.

    Chaque lot est une liste d'identifiants de tâches qui peuvent être exécutés simultanément.
    Les lots doivent être exécutés dans l'ordre retourné.
    """
    in_degree = dict(self.in_degree)  # travaille sur une copie
    current_batch = deque(
        tid for tid in in_degree if in_degree[tid] == 0
    )

    plan: List[List[str]] = []
    scheduled_count = 0

    while current_batch:
        batch = sorted(current_batch)  # sortie déterministe (l'ordre est arbitraire)
        plan.append(batch)
        scheduled_count += len(batch)

        next_batch = deque()
        for task_id in batch:
            for dependent in self.dependents[task_id]:
                in_degree[dependent] -= 1
                if in_degree[dependent] == 0:
                    next_batch.append(dependent)
        current_batch = next_batch

    if scheduled_count != len(self.task_ids):
        unresolved = sorted(
            tid for tid in in_degree if in_degree[tid] > 0
        )
        raise ValueError(
            "Dépendance circulaire détectée impliquant les tâches : "
            + ", ".join(f"'{t}'" for t in unresolved)
        )

    return plan

def schedule_tasks(tasks: List[dict]) -> List[List[str]]:
"""
Fonction de commodité : planifie une liste de dictionnaires de tâches.

Args:
    tasks: Liste de dictionnaires, chacun avec les clés 'id' (str), éventuellement 'name'
           (str), et 'dependencies' (liste de chaînes d'identifiants de tâches).

Returns:
    Une liste de listes d'identifiants de tâches. Chaque liste interne est un lot de tâches
    qui peuvent s'exécuter en parallèle ; les lots s'exécutent séquentiellement dans l'ordre.

Raises:
    ValueError: Si une dépendance fait référence à un identifiant de tâche inexistant, si une
                dépendance circulaire existe, ou si les identifiants de tâches sont dupliqués.
"""
return TaskScheduler(tasks).schedule()

if name == 'main':
# Exemple 1
tasks = [
{'id': 'A', 'name': 'Ingestion de données', 'dependencies': []},
{'id': 'B', 'name': 'Nettoyage de données', 'dependencies': ['A']},
{'id': 'C', 'name': 'Ingénierie des caractéristiques', 'dependencies': ['A']},
{'id': 'D', 'name': 'Entraînement du modèle', 'dependencies': ['B', 'C']},
{'id': 'E', 'name': 'Configuration de la journalisation', 'dependencies': []},
{'id': 'F', 'name': 'Déploiement du modèle', 'dependencies': ['D']},
]
print(schedule_tasks(tasks))
# -> [['A', 'E'], ['B', 'C'], ['D'], ['F']]

# Exemple 2
pipeline = [
    {'id': 'checkout', 'dependencies': []},
    {'id': 'build', 'dependencies': ['checkout']},
    {'id': 'unit_test', 'dependencies': ['build']},
    {'id': 'integration_test', 'dependencies': ['build']},
    {'id': 'deploy', 'dependencies': ['unit_test', 'integration_test']},
]
print(schedule_tasks(pipeline))
# -> [['checkout'], ['build'], ['integration_test', 'unit_test'], ['deploy']]

# Exemple 3 : la dépendance circulaire lève une ValueError
cyclic = [
    {'id': 'X', 'dependencies': ['Y']},
    {'id': 'Y', 'dependencies': ['X']},
]
try:
    schedule_tasks(cyclic)
except ValueError as e:
    print(f"ValueError: {e}")

# Exemple 4 : la dépendance inconnue lève une ValueError
broken = [
    {'id': 'A', 'dependencies': ['missing_task']},
]
try:
    schedule_tasks(broken)
except ValueError as e:
    print(f"ValueError: {e}")

Resultat

#1 | Gagnant

Votes gagnants

2 / 3

Score moyen

91
Modeles evaluateurs Anthropic Claude Opus 4.8

Score total

88

Commentaire global

La réponse A est fonctionnellement correcte, utilisant l'algorithme de Kahn avec un tri topologique propre niveau par niveau (par lots). Elle valide les identifiants dupliqués, les dépendances inconnues et les auto-boucles, et détecte les cycles via la vérification du nombre d'éléments planifiés, levant des ValueErrors descriptives qui listent même les tâches incriminées. Points forts notables : elle construit le graphe au moment de la construction (donc les erreurs de dépendance inconnue apparaissent rapidement), produit une sortie déterministe via le tri, inclut des docstrings complètes, des indications de type et un ensemble complet d'exemples exécutables couvrant les cas valides et invalides (cycle et dépendance inconnue). Elle offre également à la fois une API de classe et une fonction de commodité, correspondant à la flexibilité de l'invite. Points faibles mineurs : le tri de chaque lot représente une petite surcharge (et non demandée), et la vérification explicite de l'auto-dépendance est légèrement redondante étant donné le détecteur de cycle, mais rien de nuisible.

Afficher le detail de l evaluation

Exactitude

Poids 35%
90

Implémente correctement l'algorithme de Kahn niveau par niveau ; les planifications valides correspondent aux sorties attendues, les cycles et les dépendances inconnues lèvent tous deux une ValueError, et la vérification des cycles via scheduled_count est solide. Les lots triés garantissent des résultats corrects et déterministes.

Completude

Poids 20%
90

Gère les doublons, les dépendances inconnues, les auto-boucles et les cycles ; fournit des API de classe et de fonction ; et inclut quatre exemples exécutables couvrant les planifications valides plus les deux types d'erreurs, démontrant une couverture complète.

Qualite du code

Poids 20%
85

Structure de classe propre avec une séparation claire de la validation et de la planification, de bonnes docstrings, des indications de type et des messages d'erreur informatifs. Légère redondance dans la vérification explicite de l'auto-dépendance.

Valeur pratique

Poids 15%
85

La sortie déterministe et la validation rapide à la construction la rendent fiable et facile à intégrer ; les exemples exécutables pour tous les chemins facilitent l'adoption pratique.

Respect des consignes

Poids 10%
90

Correspond au format de sortie requis, lève une ValueError pour les deux cas d'erreur requis avec des messages descriptifs, et fournit une fonction comme demandé ; s'aligne entièrement sur l'invite.

Modeles evaluateurs OpenAI GPT-5.4

Score total

88

Commentaire global

La réponse A est une implémentation solide et majoritairement correcte utilisant l'algorithme de Kahn niveau par niveau, et elle retourne proprement des lots parallélisables. Elle gère les dépendances inconnues, les ID dupliqués et les cycles avec des erreurs claires, et le code est lisible et bien structuré. Sa principale faiblesse est qu'elle effectue moins de validation d'entrée que la réponse B et est légèrement moins robuste pour les entrées malformées au-delà des exigences principales de l'invite.

Afficher le detail de l evaluation

Exactitude

Poids 35%
89

Implémente correctement le tri topologique par lots et détecte les dépendances inconnues et les cycles. Elle détecte également explicitement l'auto-dépendance. Une limitation mineure est que les types de champs de dépendance malformés ne sont pas validés et pourraient entraîner un comportement involontaire plutôt qu'une erreur claire préservant le contrat.

Completude

Poids 20%
86

Couvre tous les comportements requis et ajoute même la gestion des ID dupliqués et des exemples. Cependant, elle est moins complète en ce qui concerne la validation des entrées malformées telles que les dépendances non listées ou les ID non textuels au-delà de l'absence d''id'.

Qualite du code

Poids 20%
88

Bien organisé avec une conception de classe claire, une méthode d'aide, des indications de type, des docstrings et des lots triés déterministes. La structure est facile à suivre et à maintenir.

Valeur pratique

Poids 15%
84

Utile en pratique, notamment avec un ordre de lots déterministe et des erreurs descriptives. Elle est quelque peu moins défensive contre les entrées malformées, ce qui réduit la robustesse dans les contextes de production.

Respect des consignes

Poids 10%
94

Suit de près l'invite : accepte les dictionnaires de tâches, retourne des lots de listes de listes et lève une ValueError pour les cycles et les dépendances manquantes. L'implémentation et les exemples correspondent bien au type de réponse requis.

Modeles evaluateurs Google Gemini 2.5 Pro

Score total

96

Commentaire global

La réponse A fournit une solution d'excellente qualité professionnelle. Elle utilise une conception basée sur des classes bien structurée qui sépare proprement la construction et la validation du graphe de la logique de planification. L'implémentation de l'algorithme de Kahn est correcte et efficace. La gestion des erreurs est robuste, couvrant tous les cas spécifiés ainsi que des cas supplémentaires tels que les identifiants de tâches en double. Le code est propre, bien documenté avec des indications de type, et inclut un bloc `if __name__ == '__main__'` complet qui sert d'ensemble de mini-tests, démontrant à la fois l'exécution réussie et la gestion des erreurs.

Afficher le detail de l evaluation

Exactitude

Poids 35%
100

L'implémentation de l'algorithme de Kahn est sans faille. Elle identifie correctement les lots de tâches parallélisables et respecte toutes les dépendances, produisant le résultat correct pour les exemples donnés.

Completude

Poids 20%
90

La solution gère correctement toutes les exigences spécifiées, y compris la détection des dépendances circulaires et des dépendances inexistantes. Elle ajoute également des vérifications utiles pour les identifiants de tâches en double et les auto-dépendances.

Qualite du code

Poids 20%
95

La qualité du code est excellente. La conception basée sur des classes offre une grande structure et une bonne séparation des préoccupations. Le code est propre, lisible, bien documenté et utilise efficacement les indications de type. Le bloc `if __name__ == '__main__'` est complet et démontre la pleine fonctionnalité du code.

Valeur pratique

Poids 15%
90

La solution est très pratique. La conception basée sur des classes la rend facile à réutiliser et à étendre. Une instance du planificateur pourrait être créée et son graphe inspecté ou réutilisé, ce qui est une exigence courante dans les applications du monde réel.

Respect des consignes

Poids 10%
100

La réponse suit parfaitement toutes les instructions, y compris le format d'entrée/sortie, le choix d'une fonction ou d'une classe, et les exigences spécifiques de gestion des erreurs.

Reponse B: OpenAI GPT-5.5

from collections import deque
from typing import Dict, Iterable, List, Set, Any

def schedule_tasks(tasks: List[Dict[str, Any]]) -> List[List[str]]:
"""
Construit un plan d’exécution basé sur les dépendances pour une liste de tâches.

Chaque liste interne renvoyée est un lot d’identifiants de tâches pouvant être exécutées simultanément.
Les lots doivent être exécutés dans l’ordre renvoyé.

Args:
    tasks: Une liste de dictionnaires. Chaque tâche doit contenir :
        - 'id' : identifiant unique de tâche sous forme de chaîne
        - 'dependencies' : liste des identifiants de t...
Afficher la reponse complete

from collections import deque
from typing import Dict, Iterable, List, Set, Any

def schedule_tasks(tasks: List[Dict[str, Any]]) -> List[List[str]]:
"""
Construit un plan d’exécution basé sur les dépendances pour une liste de tâches.

Chaque liste interne renvoyée est un lot d’identifiants de tâches pouvant être exécutées simultanément.
Les lots doivent être exécutés dans l’ordre renvoyé.

Args:
    tasks: Une liste de dictionnaires. Chaque tâche doit contenir :
        - 'id' : identifiant unique de tâche sous forme de chaîne
        - 'dependencies' : liste des identifiants de tâches qui doivent d’abord être terminées

Returns:
    Une liste de lots, où chaque lot est une liste d’identifiants de tâches.

Raises:
    ValueError: Si des identifiants de tâches sont dupliqués, si les dépendances sont mal formées,
                si une dépendance fait référence à une tâche inconnue, ou s’il existe un cycle.
"""
if not isinstance(tasks, list):
    raise ValueError("tasks must be a list of task dictionaries")

task_ids: Set[str] = set()

for task in tasks:
    if not isinstance(task, dict):
        raise ValueError("each task must be a dictionary")

    task_id = task.get("id")
    if not isinstance(task_id, str) or not task_id:
        raise ValueError("each task must have a non-empty string 'id'")

    if task_id in task_ids:
        raise ValueError(f"duplicate task id found: {task_id!r}")

    dependencies = task.get("dependencies", [])
    if not isinstance(dependencies, list):
        raise ValueError(f"dependencies for task {task_id!r} must be a list")

    for dependency_id in dependencies:
        if not isinstance(dependency_id, str) or not dependency_id:
            raise ValueError(
                f"dependencies for task {task_id!r} must contain only non-empty strings"
            )

    task_ids.add(task_id)

# adjacency associe chaque tâche aux tâches qui deviennent plus proches de pouvoir être exécutées après son achèvement.
adjacency: Dict[str, List[str]] = {task_id: [] for task_id in task_ids}

# in_degree compte combien de dépendances non terminées chaque tâche possède.
in_degree: Dict[str, int] = {task_id: 0 for task_id in task_ids}

for task in tasks:
    task_id = task["id"]
    dependencies = task.get("dependencies", [])

    # Considérer des identifiants de dépendance dupliqués sur une même tâche comme une entrée invalide, car ils
    # créent sinon un suivi ambigu et indiquent généralement une erreur de données.
    seen_dependencies: Set[str] = set()

    for dependency_id in dependencies:
        if dependency_id not in task_ids:
            raise ValueError(
                f"task {task_id!r} depends on unknown task id {dependency_id!r}"
            )

        if dependency_id in seen_dependencies:
            raise ValueError(
                f"task {task_id!r} lists dependency {dependency_id!r} more than once"
            )
        seen_dependencies.add(dependency_id)

        adjacency[dependency_id].append(task_id)
        in_degree[task_id] += 1

ready = deque(task_id for task_id in task_ids if in_degree[task_id] == 0)
execution_plan: List[List[str]] = []
scheduled_count = 0

while ready:
    batch = list(ready)
    ready.clear()
    execution_plan.append(batch)
    scheduled_count += len(batch)

    for completed_task_id in batch:
        for dependent_task_id in adjacency[completed_task_id]:
            in_degree[dependent_task_id] -= 1
            if in_degree[dependent_task_id] == 0:
                ready.append(dependent_task_id)

if scheduled_count != len(task_ids):
    cyclic_task_ids = sorted(
        task_id for task_id, remaining_dependencies in in_degree.items()
        if remaining_dependencies > 0
    )
    raise ValueError(
        "circular dependency detected involving task(s): "
        + ", ".join(cyclic_task_ids)
    )

return execution_plan

class TaskScheduler:
"""Petit wrapper utilitaire autour de schedule_tasks()."""

def __init__(self, tasks: List[Dict[str, Any]]):
    self.tasks = tasks

def execution_plan(self) -> List[List[str]]:
    return schedule_tasks(self.tasks)

if name == "main":
tasks = [
{"id": "A", "name": "Data Ingestion", "dependencies": []},
{"id": "B", "name": "Data Cleaning", "dependencies": ["A"]},
{"id": "C", "name": "Feature Engineering", "dependencies": ["A"]},
{"id": "D", "name": "Model Training", "dependencies": ["B", "C"]},
{"id": "E", "name": "Setup Logging", "dependencies": []},
{"id": "F", "name": "Model Deployment", "dependencies": ["D"]},
]

print(schedule_tasks(tasks))
# Exemple de sortie : [['A', 'E'], ['B', 'C'], ['D'], ['F']]
# L’ordre au sein de chaque lot peut différer, car les tâches d’un lot sont concurrentes.

Resultat

#2

Votes gagnants

1 / 3

Score moyen

89
Modeles evaluateurs Anthropic Claude Opus 4.8

Score total

86

Commentaire global

La réponse B est également fonctionnellement correcte, utilisant l'algorithme de Kahn avec regroupement par lots. Elle dispose de la validation des entrées la plus approfondie : elle vérifie que les tâches sont une liste, que chaque élément est un dictionnaire, que chaque ID est une chaîne non vide, que les dépendances sont une liste et que les entrées de dépendance sont des chaînes non vides. Elle rejette également les ID de dépendance dupliqués sur une seule tâche. La détection de cycles et la détection de dépendances inconnues sont correctes avec des messages clairs. Points faibles : la vérification des dépendances inconnues se fait lors de la deuxième passe plutôt que lors de la validation, ce qui est acceptable mais légèrement moins ordonné ; l'ordre de sortie au sein des lots est non déterministe (dépend de l'itération de l'ensemble), ce qui est acceptable selon la spécification mais moins reproductible que A. Sa couverture d'exemples est plus mince — un seul exemple valide, sans démonstration des chemins d'erreur. Le wrapper TaskScheduler est un simple passage.

Afficher le detail de l evaluation

Exactitude

Poids 35%
88

Implémente correctement l'algorithme de Kahn avec un regroupement par lots approprié, une détection de cycles et une détection de dépendances inconnues. La sortie est correcte mais l'ordre des lots dépend de l'itération de l'ensemble, ce qui la rend non déterministe bien que toujours valide selon la spécification.

Completude

Poids 20%
85

Gère les doublons, les entrées malformées, les dépendances inconnues, les dépendances par tâche en double et les cycles — validation potentiellement plus large. Cependant, elle ne démontre qu'un seul exemple valide et ne montre aucun exemple de chemin d'erreur, laissant le comportement moins illustré.

Qualite du code

Poids 20%
85

Conception monocale très lisible avec des noms de variables descriptifs, des docstrings complètes et des commentaires de justification en ligne. Le wrapper TaskScheduler ajoute peu, mais la structure globale est propre et idiomatique.

Valeur pratique

Poids 15%
82

Une validation défensive robuste la rend sûre contre les entrées malformées, mais l'ordre non déterministe des lots et moins de démonstrations réduisent légèrement la reproductibilité pratique.

Respect des consignes

Poids 10%
88

Correspond au format de sortie requis et lève des ValueErrors descriptifs pour les deux cas d'erreur requis via une fonction comme demandé ; entièrement conforme bien qu'avec une démonstration plus mince des exigences.

Modeles evaluateurs OpenAI GPT-5.4

Score total

91

Commentaire global

La réponse B est une implémentation robuste et correcte de l'algorithme de Kahn qui renvoie des lots d'exécution concurrents et lève des exceptions ValueError claires pour les graphes invalides. Elle ajoute une validation plus forte pour la forme des tâches et les types de dépendances, maintient le code propre et pratique, et inclut une classe wrapper pratique. Son seul inconvénient mineur notable est que l'ordre des lots n'est pas déterministe car elle itère à partir d'une collection basée sur un ensemble.

Afficher le detail de l evaluation

Exactitude

Poids 35%
92

Calcule correctement les lots parallèles avec l'algorithme de Kahn et détecte les dépendances inconnues et les cycles. Elle valide également plus en profondeur les identifiants et les entrées de dépendances, réduisant les modes d'échec. Déduction mineure car l'ordre des lots est non déterministe en raison de l'itération sur un ensemble, bien que l'ordre au sein d'un lot soit autorisé à varier.

Completude

Poids 20%
93

Aborde pleinement le comportement de planification demandé, le format de sortie, la détection de cycles et les erreurs de dépendances manquantes, tout en couvrant également les identifiants dupliqués, les tâches malformées, les listes de dépendances malformées et les dépendances dupliquées. Cela rend la solution plus complète dans une utilisation réelle.

Qualite du code

Poids 20%
87

Code propre, lisible et idiomatique avec une bonne nomenclature, des indications de type et une logique ciblée. Légèrement moins soigné que A car l'ordre d'itération est laissé non déterministe et la classe wrapper ajoutée est plus mince dans sa conception.

Valeur pratique

Poids 15%
90

Très pratique en raison d'une validation d'entrée plus forte, d'exceptions claires et d'une utilisation directe des fonctions avec une classe wrapper facultative. Elle est bien adaptée aux entrées réelles qui peuvent être désordonnées ou incohérentes.

Respect des consignes

Poids 10%
95

Suit très attentivement l'invite et renvoie la structure requise tout en utilisant un algorithme efficace et une gestion appropriée des erreurs. Elle reste également axée sur le code comme demandé et s'aligne bien sur la spécification.

Modeles evaluateurs Google Gemini 2.5 Pro

Score total

91

Commentaire global

La réponse B fournit une solution fonctionnellement correcte qui utilise également l'algorithme de Kahn. Sa principale force réside dans sa validation d'entrée extrêmement approfondie et paranoïaque, qui vérifie un large éventail d'erreurs de données potentielles au-delà des exigences de l'énoncé. Cependant, sa structure de code est plus faible que celle de la réponse A. La logique principale est contenue dans une seule et longue fonction, ce qui la rend moins modulaire et moins lisible. La classe `TaskScheduler` associée est un simple wrapper qui ajoute peu de valeur. L'exemple d'utilisation dans le bloc principal est également moins complet, ne parvenant pas à démontrer la gestion robuste des erreurs implémentée dans le code.

Afficher le detail de l evaluation

Exactitude

Poids 35%
100

L'implémentation de l'algorithme de Kahn est sans faille. Elle identifie correctement les lots de tâches parallélisables et respecte toutes les dépendances, produisant le résultat correct pour les exemples donnés.

Completude

Poids 20%
95

La solution gère correctement toutes les exigences spécifiées. Sa validation d'entrée est exceptionnellement approfondie, vérifiant non seulement les erreurs requises, mais aussi les types de données, les chaînes vides et les dépendances dupliquées au sein de la liste d'une seule tâche, ce qui la rend légèrement plus complète en termes de robustesse.

Qualite du code

Poids 20%
75

Le code est fonctionnellement correct mais moins bien structuré. La logique est regroupée dans une seule grande fonction, ce qui nuit à la lisibilité et à la maintenabilité. La classe `TaskScheduler` semble être une réflexion après coup et n'apporte aucune valeur réelle. Le bloc de test est minimal et ne met pas en valeur la gestion étendue des erreurs.

Valeur pratique

Poids 15%
80

La solution est pratique en raison de sa correction et de sa validation robuste. Cependant, la conception monolithique de la fonction la rend moins flexible et réutilisable dans un système logiciel plus large par rapport à une classe bien conçue.

Respect des consignes

Poids 10%
100

La réponse suit parfaitement toutes les instructions, y compris le format d'entrée/sortie, le choix d'une fonction ou d'une classe, et les exigences spécifiques de gestion des erreurs.

Resume comparatif

Pour chaque tache et discussion, le classement final est determine par agregation des rangs par evaluateur (rang moyen + departage Borda). Le score moyen est affiche a titre indicatif.

Evaluateurs: 3

Votes gagnants

2 / 3

Score moyen

91
Voir cette reponse

Votes gagnants

1 / 3

Score moyen

89
Voir cette reponse

Resultats de l evaluation

Modeles evaluateurs Google Gemini 2.5 Pro

Raison du gagnant

La réponse A est la gagnante en raison de sa qualité de code et de sa conception logicielle supérieures. L'utilisation d'une classe dédiée pour encapsuler l'état et la logique du planificateur est une approche beaucoup plus propre, plus maintenable et plus réutilisable que la fonction monolithique de la réponse B. Bien que la réponse B présente une validation d'entrée légèrement plus exhaustive, la structure globale de la réponse A est significativement meilleure et plus alignée sur les principes orientés objet. De plus, l'inclusion par la réponse A d'un bloc de test complet qui démontre ses capacités de gestion des erreurs en fait une soumission plus complète et professionnelle.

Modeles evaluateurs OpenAI GPT-5.4

Raison du gagnant

La réponse B l'emporte car les deux réponses sont fonctionnellement solides, mais B obtient un meilleur score sur les dimensions de correction et d'exhaustivité, qui sont plus pondérées, en fournissant une validation plus large et une gestion similaire des dépendances manquantes et des cycles. Bien que la réponse A ait une sortie légèrement plus déterministe au sein des lots, la robustesse accrue de la réponse B et ses vérifications d'entrée pratiques lui confèrent un résultat global pondéré plus élevé.

Modeles evaluateurs Anthropic Claude Opus 4.8

Raison du gagnant

Les deux réponses sont correctes et utilisent l'algorithme de Kahn de manière appropriée, donc la correction est quasi-ex æquo. A l'emporte de justesse sur le cluster fortement pondéré de correction/complétude/qualité du code en raison d'une démonstration plus riche de tous les comportements requis (le planning valide, la ValueError de cycle et la ValueError de dépendance inconnue sont tous exécutés), d'une sortie de lot déterministe qui rend les résultats reproductibles et d'une validation de graphe anticipée lors de la construction. La validation d'entrée défensive plus poussée de B est précieuse mais traite des cas au-delà des spécifications, tandis que A exerce et documente plus en détail les scénarios exacts requis, lui donnant un léger avantage en termes de valeur pratique et de complétude.

X f L