Orivel Orivel
Ouvrir le menu

Implémenter un Cache LRU (Least Recently Used)

Comparez les reponses des modeles pour cette tache benchmark en Programmation et consultez scores, commentaires et exemples lies.

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

Implémentez une classe de Cache LRU (Least Recently Used) en Python qui prend en charge les opérations suivantes : 1. `LRUCache(capacity)` — Initialisez le cache avec une capacité d'entier positif. 2. `get(key)` — Retourne la valeur associée à la clé si elle existe dans le cache, sinon retourne -1. L'accès à une clé la marque comme récemment utilisée. 3. `put(key, value)` — Insérez ou mettez à jour la paire clé-valeur. Si le cache dépasse sa capacité après insertion, évincez la clé la moins récemment utilisée. Le...

Afficher plus

Implémentez une classe de Cache LRU (Least Recently Used) en Python qui prend en charge les opérations suivantes : 1. `LRUCache(capacity)` — Initialisez le cache avec une capacité d'entier positif. 2. `get(key)` — Retourne la valeur associée à la clé si elle existe dans le cache, sinon retourne -1. L'accès à une clé la marque comme récemment utilisée. 3. `put(key, value)` — Insérez ou mettez à jour la paire clé-valeur. Si le cache dépasse sa capacité après insertion, évincez la clé la moins récemment utilisée. Les opérations `get` et `put` doivent s'exécuter en complexité temporelle moyenne O(1). Fournissez une implémentation Python complète et autonome. N'utilisez pas `functools.lru_cache` ni `collections.OrderedDict`. Vous devez implémenter la structure de données sous-jacente vous-même (par exemple, en utilisant une liste doublement chaînée et une table de hachage). Après votre définition de classe, incluez une courte démonstration qui crée un LRUCache avec une capacité de 2 et effectue les opérations suivantes, en imprimant le résultat de chaque `get` : ``` cache = LRUCache(2) cache.put(1, 10) cache.put(2, 20) print(cache.get(1)) # Attendu : 10 cache.put(3, 30) # Évince la clé 2 print(cache.get(2)) # Attendu : -1 cache.put(4, 40) # Évince la clé 1 print(cache.get(1)) # Attendu : -1 print(cache.get(3)) # Attendu : 30 print(cache.get(4)) # Attendu : 40 ```

Politique d evaluation

Une bonne réponse doit fournir une implémentation Python complète et exécutable d'un cache LRU qui répond à tous les critères suivants : (1) Il n'utilise ni OrderedDict ni functools.lru_cache. (2) Il atteint une complexité temporelle moyenne de O(1) pour get et put, généralement via une table de hachage combinée à une liste doublement chaînée. (3) La classe gère correctement les limites de capacité et évince l'entrée la moins récemment utilisée. (4) Le code de démonstration est inclus et produirait la sortie attend...

Afficher plus

Une bonne réponse doit fournir une implémentation Python complète et exécutable d'un cache LRU qui répond à tous les critères suivants : (1) Il n'utilise ni OrderedDict ni functools.lru_cache. (2) Il atteint une complexité temporelle moyenne de O(1) pour get et put, généralement via une table de hachage combinée à une liste doublement chaînée. (3) La classe gère correctement les limites de capacité et évince l'entrée la moins récemment utilisée. (4) Le code de démonstration est inclus et produirait la sortie attendue (10, -1, -1, 30, 40). (5) Le code est propre, bien structuré et raisonnablement commenté ou auto-explicatif. Un crédit partiel peut être accordé pour des solutions largement correctes mais présentant des problèmes mineurs. Les solutions utilisant OrderedDict ou ne parvenant pas à atteindre une complexité O(1) devraient être moins bien notées. Les solutions présentant des bugs produisant une sortie incorrecte pour la démonstration devraient être significativement moins bien notées.

Reponses

Reponse A: OpenAI GPT-5.2

class _Node: __slots__ = ("key", "value", "prev", "next") def __init__(self, key=None, value=None): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): if not isinstance(capacity, int) or capacity <= 0: raise ValueError("capacity must be a positive integer") self.capacity = capacity self.map = {} # key -> _Node # Dummy head/tail to avoid edge cases. # Most-recent is right after head. Least-recent is right before tail. self.head = _Node()...

Afficher la reponse complete

class _Node: __slots__ = ("key", "value", "prev", "next") def __init__(self, key=None, value=None): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): if not isinstance(capacity, int) or capacity <= 0: raise ValueError("capacity must be a positive integer") self.capacity = capacity self.map = {} # key -> _Node # Dummy head/tail to avoid edge cases. # Most-recent is right after head. Least-recent is right before tail. self.head = _Node() self.tail = _Node() self.head.next = self.tail self.tail.prev = self.head def _add_to_front(self, node: _Node) -> None: node.prev = self.head node.next = self.head.next self.head.next.prev = node self.head.next = node def _remove(self, node: _Node) -> None: node.prev.next = node.next node.next.prev = node.prev node.prev = None node.next = None def _move_to_front(self, node: _Node) -> None: self._remove(node) self._add_to_front(node) def _evict_lru(self) -> None: lru = self.tail.prev if lru is self.head: return self._remove(lru) del self.map[lru.key] def get(self, key: int) -> int: node = self.map.get(key) if node is None: return -1 self._move_to_front(node) return node.value def put(self, key: int, value: int) -> None: node = self.map.get(key) if node is not None: node.value = value self._move_to_front(node) return new_node = _Node(key, value) self.map[key] = new_node self._add_to_front(new_node) if len(self.map) > self.capacity: self._evict_lru() # Demonstration cache = LRUCache(2) cache.put(1, 10) cache.put(2, 20) print(cache.get(1)) # Expected: 10 cache.put(3, 30) # Evicts key 2 print(cache.get(2)) # Expected: -1 cache.put(4, 40) # Evicts key 1 print(cache.get(1)) # Expected: -1 print(cache.get(3)) # Expected: 30 print(cache.get(4)) # Expected: 40

Resultat

#1 | Gagnant

Votes gagnants

3 / 3

Score moyen

99
Modeles evaluateurs Google Gemini 2.5 Pro

Score total

100

Commentaire global

La soumission est exceptionnelle. Elle fournit une implémentation correcte, efficace et de haute qualité d'un cache LRU à partir de zéro. Le code utilise l'approche classique et optimale d'une table de hachage combinée à une liste doublement chaînée. L'implémentation est robuste, comportant des nœuds sentinelles de tête/queue pour simplifier les cas limites, et démontre d'excellentes pratiques de codage comme des méthodes auxiliaires et des indications de type. Elle respecte pleinement toutes les exigences et contraintes de la tâche.

Afficher le detail de l evaluation

Exactitude

Poids 35%
100

L'implémentation est parfaitement correcte. Elle utilise avec succès une table de hachage pour des recherches en O(1) et une liste doublement chaînée pour maintenir l'ordre d'utilisation. La logique pour `get`, `put`, et l'éviction fonctionne sans faille, et le code de démonstration fourni produit le résultat attendu exact.

Completude

Poids 20%
100

La solution est entièrement complète. Elle fournit une classe `LRUCache` autonome, une classe auxiliaire privée `_Node`, et le code de démonstration exact demandé dans l'énoncé. Toutes les fonctionnalités requises sont implémentées.

Qualite du code

Poids 20%
100

La qualité du code est excellente. Il est bien structuré avec des méthodes auxiliaires claires, à responsabilité unique (_add_to_front, _remove, etc.) qui améliorent la lisibilité. L'utilisation de nœuds sentinelles de tête/queue est une technique sophistiquée qui simplifie la logique de la liste chaînée. L'inclusion d'indications de type, de `__slots__`, et de validation d'entrée pour la capacité démontre des pratiques de codage solides et professionnelles.

Valeur pratique

Poids 15%
100

La solution a une grande valeur pratique. Elle fournit une implémentation efficace, typique d'un manuel, d'une structure de données fondamentale et largement utilisée. Ce code pourrait être utilisé dans des applications réelles et sert d'excellente référence sur la façon de construire un cache LRU à partir de zéro.

Respect des consignes

Poids 10%
100

La solution respecte parfaitement toutes les instructions. Elle implémente correctement le cache LRU à partir de zéro sans utiliser de bibliothèques interdites comme `collections.OrderedDict`. Elle atteint la complexité temporelle moyenne requise en O(1) pour ses opérations principales et inclut la démonstration obligatoire.

Modeles evaluateurs Anthropic Claude Sonnet 4.6

Score total

99

Commentaire global

Excellente implémentation d'un Cache LRU. La solution utilise correctement une liste doublement chaînée combinée à une table de hachage pour atteindre une complexité temporelle moyenne de O(1) pour les opérations get et put. Le code évite les constructions interdites (OrderedDict, functools.lru_cache), gère correctement tous les cas limites et produit exactement la sortie attendue. L'utilisation de nœuds sentinelles de tête/queue factices est une approche propre qui élimine les cas limites. Le code est bien structuré, utilise __slots__ pour l'efficacité mémoire, inclut la validation des entrées et est clairement commenté. La démonstration correspond exactement à la sortie requise.

Afficher le detail de l evaluation

Exactitude

Poids 35%
100

L'implémentation est entièrement correcte. La liste doublement chaînée avec des sentinelles factices suit correctement la récence, get déplace les nœuds accédés vers le début, put gère les cas d'insertion et de mise à jour, l'éviction supprime le nœud tail.prev (LRU), et toutes les sorties de démonstration correspondent aux valeurs attendues (10, -1, -1, 30, 40).

Completude

Poids 20%
100

La solution est entièrement complète : elle inclut la classe LRUCache avec toutes les méthodes requises (constructeur, get, put), les méthodes privées auxiliaires, la classe _Node, la validation des entrées et le code de démonstration complet tel que spécifié dans la tâche.

Qualite du code

Poids 20%
100

La qualité du code est excellente. L'utilisation de __slots__ sur _Node témoigne d'une attention à l'efficacité mémoire. Les méthodes d'aide privées (_add_to_front, _remove, _move_to_front, _evict_lru) sont bien nommées et n'ont qu'un seul objectif. Des indications de type sont utilisées. Les commentaires expliquent la conception du nœud sentinelle. Le code est propre et lisible.

Valeur pratique

Poids 15%
95

L'implémentation est très pratique. Elle inclut la validation des entrées avec un message d'erreur significatif, utilise __slots__ pour la performance, et la conception est extensible. Le seul petit défaut est qu'elle ne gère pas la sécurité des threads, mais cela n'était pas requis par la tâche.

Respect des consignes

Poids 10%
100

Toutes les instructions sont suivies à la lettre : aucune utilisation d'OrderedDict ou de functools.lru_cache, complexité O(1) atteinte via table de hachage + liste doublement chaînée, la structure de données sous-jacente est implémentée manuellement, et le code de démonstration exact de la tâche est inclus avec des commentaires de sortie attendue corrects.

Modeles evaluateurs OpenAI GPT-5 mini

Score total

97

Commentaire global

Cette réponse fournit une implémentation Python correcte, efficace et autonome d'un cache LRU utilisant une table de hachage et une liste doublement chaînée. Elle respecte les opérations O(1) requises, gère correctement la capacité et l'éviction, et inclut la démonstration demandée qui afficherait les sorties attendues. Le code est propre et lisible ; les problèmes mineurs se limitent à de petits points de style (par exemple, le nom 'map' masque un élément intégré et il n'y a pas de docstrings), mais ceux-ci n'affectent pas la correction ou les performances.

Afficher le detail de l evaluation

Exactitude

Poids 35%
100

Implémente correctement LRU en utilisant une table de hachage + une liste doublement chaînée. get et put fonctionnent en temps moyen O(1), la logique d'éviction est correcte et la démonstration fournie produira les sorties attendues.

Completude

Poids 20%
100

Toutes les fonctionnalités requises sont présentes : constructeur avec validation de capacité, sémantiques get et put, éviction LRU lorsque la capacité est dépassée, aucune utilisation de OrderedDict ou functools.lru_cache, et la démonstration demandée est incluse.

Qualite du code

Poids 20%
90

Le code est bien structuré, clair et utilise des têtes/queues factices pour simplifier les opérations de liste. Les méthodes sont petites et ciblées. Petits détails de style : le nom d'attribut 'map' masque un élément intégré et il n'y a pas de docstrings, mais cela n'affecte pas la correction.

Valeur pratique

Poids 15%
90

L'implémentation est pratique et prête à être utilisée dans du code réel : efficace, sûre (valide la capacité) et économe en mémoire (utilise __slots__). Elle bénéficierait de petits ajouts comme des docstrings ou des tests unitaires, mais elle est fonctionnellement complète.

Respect des consignes

Poids 10%
100

Suit les instructions à la lettre : n'utilise pas de bibliothèques interdites, implémente manuellement les structures de données requises, garantit les opérations O(1) et inclut la démonstration exacte avec les résultats imprimés attendus.

class Node: def __init__(self, key=0, value=0): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): self.capacity = capacity self.cache = {} # Sentinelles de tête et de queue pour la liste doublement chaînée self.head = Node() self.tail = Node() self.head.next = self.tail self.tail.prev = self.head def _add_node(self, node): # Ajoute un nœud juste après la tête (le rendant le plus récemment utilisé) node.prev = self.head no...

Afficher la reponse complete

class Node: def __init__(self, key=0, value=0): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): self.capacity = capacity self.cache = {} # Sentinelles de tête et de queue pour la liste doublement chaînée self.head = Node() self.tail = Node() self.head.next = self.tail self.tail.prev = self.head def _add_node(self, node): # Ajoute un nœud juste après la tête (le rendant le plus récemment utilisé) node.prev = self.head node.next = self.head.next self.head.next.prev = node self.head.next = node def _remove_node(self, node): # Supprime un nœud de la liste chaînée prev_node = node.prev next_node = node.next prev_node.next = next_node next_node.prev = prev_node def _move_to_front(self, node): # Supprime un nœud et le rajoute au début (le plus récemment utilisé) self._remove_node(node) self._add_node(node) def _pop_tail(self): # Supprime et retourne le nœud le moins récemment utilisé (celui juste avant la sentinelle de queue) if self.tail.prev == self.head: return None # La liste est vide lru_node = self.tail.prev self._remove_node(lru_node) return lru_node def get(self, key: int) -> int: if key not in self.cache: return -1 node = self.cache[key] self._move_to_front(node) # Marquer comme récemment utilisé return node.value def put(self, key: int, value: int) -> None: if key in self.cache: node = self.cache[key] node.value = value # Mettre à jour la valeur self._move_to_front(node) # Marquer comme récemment utilisé else: new_node = Node(key, value) self.cache[key] = new_node self._add_node(new_node) # Ajouter le nouveau nœud au début if len(self.cache) > self.capacity: # Évincer l'élément le moins récemment utilisé lru_node = self._pop_tail() if lru_node: del self.cache[lru_node.key] # Démonstration cache = LRUCache(2) cache.put(1, 10) cache.put(2, 20) print(cache.get(1)) # Attendu : 10 cache.put(3, 30) # Évince la clé 2 print(cache.get(2)) # Attendu : -1 cache.put(4, 40) # Évince la clé 1 print(cache.get(1)) # Attendu : -1 print(cache.get(3)) # Attendu : 30 print(cache.get(4)) # Attendu : 40

Resultat

#2

Votes gagnants

0 / 3

Score moyen

98
Modeles evaluateurs Google Gemini 2.5 Pro

Score total

100

Commentaire global

C'est une excellente solution qui fournit une implémentation classique, correcte et efficace d'un Cache LRU. Le code est très bien structuré, utilisant une classe `Node` auxiliaire et des méthodes privées pour encapsuler la logique de la liste doublement chaînée, ce qui améliore la lisibilité et la maintenabilité. Il utilise correctement une table de hachage pour des recherches en O(1) et une liste doublement chaînée pour des mises à jour de récence en O(1), répondant pleinement aux exigences de performance de la tâche. La soumission suit parfaitement toutes les instructions, y compris l'interdiction des aides de la bibliothèque standard et l'inclusion de la démonstration requise, qui s'exécute correctement.

Afficher le detail de l evaluation

Exactitude

Poids 35%
100

L'implémentation est entièrement correcte. La logique pour `get`, `put` et l'éviction fonctionne comme prévu. L'utilisation d'une table de hachage pour les recherches et d'une liste doublement chaînée avec des nœuds sentinelles pour le suivi de la récence est l'approche standard et correcte. Le code de démonstration fourni produit la sortie attendue exacte.

Completude

Poids 20%
100

La soumission est complète. Elle fournit une solution autonome avec les définitions des classes `Node` et `LRUCache`, et elle inclut le bloc de démonstration spécifique demandé dans l'invite. Toutes les fonctionnalités requises sont implémentées.

Qualite du code

Poids 20%
100

La qualité du code est excellente. Il est propre, bien organisé et facile à suivre. L'utilisation de méthodes auxiliaires privées pour les opérations de liste chaînée est un excellent choix de conception. Les noms de variables sont clairs et l'utilisation de nœuds sentinelles de tête/queue est une technique robuste qui simplifie la logique de manipulation de la liste en évitant les vérifications de nullité.

Valeur pratique

Poids 15%
100

La solution a une grande valeur pratique car c'est l'implémentation standard et la plus efficace d'un cache LRU. Elle atteint correctement la complexité temporelle moyenne requise en O(1) pour les opérations `get` et `put`. C'est précisément la solution à laquelle on s'attendrait lors d'un entretien technique ou dans une application réelle où un tel cache est nécessaire.

Respect des consignes

Poids 10%
100

La soumission suit parfaitement toutes les instructions. Elle implémente le cache LRU à partir de zéro sans utiliser les fonctions interdites `functools.lru_cache` ou `collections.OrderedDict`. Elle inclut les signatures de classe et de méthode spécifiées et fournit le code de démonstration exact comme demandé.

Modeles evaluateurs Anthropic Claude Sonnet 4.6

Score total

98

Commentaire global

Excellente implémentation d'un cache LRU. La solution utilise correctement une liste doublement chaînée avec des nœuds sentinelles de tête et de queue, combinée à une table de hachage, pour atteindre une complexité temporelle moyenne de O(1) pour les opérations get et put. Le code n'utilise pas OrderedDict ni functools.lru_cache comme requis. Toutes les méthodes d'aide sont bien nommées et logiquement organisées. Le code de démonstration est complet et produirait exactement la sortie attendue (10, -1, -1, 30, 40). Le code est propre, bien commenté et facile à suivre. Note mineure : la vérification de null dans _pop_tail est légèrement redondante car put ne l'appelle que lorsque len(self.cache) > self.capacity, ce qui signifie que la liste n'est jamais vide à ce moment-là, mais c'est une vérification défensive inoffensive.

Afficher le detail de l evaluation

Exactitude

Poids 35%
100

L'implémentation est entièrement correcte. La liste doublement chaînée avec des nœuds sentinelles et la table de hachage implémentent correctement O(1) pour get et put. La logique d'éviction supprime correctement l'élément LRU (tail.prev) et le supprime de la table de hachage. La démonstration produirait exactement 10, -1, -1, 30, 40 comme attendu.

Completude

Poids 20%
100

La solution est entièrement complète. Elle inclut la classe Node, la classe LRUCache avec toutes les méthodes requises (constructeur, get, put), toutes les méthodes d'aide nécessaires et le code de démonstration complet correspondant exactement aux spécifications de la tâche.

Qualite du code

Poids 20%
95

Le code est propre, bien structuré et correctement commenté. Les méthodes d'aide sont bien nommées (_add_node, _remove_node, _move_to_front, _pop_tail) et chacune a un bref commentaire de documentation. Le seul problème très mineur est la vérification None légèrement redondante dans _pop_tail, mais il s'agit d'une mesure défensive inoffensive qui ne porte pas significativement atteinte à la qualité.

Valeur pratique

Poids 15%
95

L'implémentation est très pratique et prête pour la production. Elle gère correctement tous les cas limites, y compris la mise à jour des clés existantes, l'éviction en cas de dépassement de capacité et l'accès aux clés inexistantes. L'utilisation de nœuds sentinelles simplifie les conditions limites. La complexité O(1) la rend adaptée à une utilisation réelle.

Respect des consignes

Poids 10%
100

Toutes les instructions sont suivies précisément. OrderedDict et functools.lru_cache ne sont pas utilisés. La structure de données sous-jacente est implémentée manuellement avec une liste doublement chaînée et une table de hachage. Le code de démonstration correspond exactement à ce qui était spécifié dans la tâche, y compris les commentaires sur les valeurs attendues et l'éviction.

Modeles evaluateurs OpenAI GPT-5 mini

Score total

97

Commentaire global

Implémentation LRU cache solide et correcte utilisant une liste doublement chaînée et une table de hachage. get et put s'exécutent en O(1) et la démonstration fournie produira la sortie attendue. Points faibles mineurs : pas de validation explicite pour une capacité non positive et de petites améliorations stylistiques/d'indications de type pourraient être apportées.

Afficher le detail de l evaluation

Exactitude

Poids 35%
100

L'implémentation maintient correctement l'ordre LRU avec des sentinelles tête/queue, déplace les nœuds accédés vers l'avant, met à jour les clés existantes, insère de nouvelles clés et évince l'élément le moins récemment utilisé lorsque la capacité est dépassée. La démonstration donne les résultats attendus.

Completude

Poids 20%
100

Toutes les fonctionnalités requises sont implémentées : classe LRUCache avec get et put, liste doublement chaînée manuelle plus table de hachage, politique d'éviction correcte, et une démonstration correspondant à l'énoncé. Aucune bibliothèque interdite n'est utilisée.

Qualite du code

Poids 20%
90

Le code est clair, bien structuré et utilise des méthodes auxiliaires pour les opérations sur la liste. Les noms de variables et les commentaires sont descriptifs. Améliorations mineures : valider la capacité dans __init__, ajouter des indications de type pour les méthodes internes, et considérer des docstrings pour les méthodes publiques.

Valeur pratique

Poids 15%
90

Implémentation O(1) efficace et pratique qui peut être utilisée dans du code réel. Gère bien les cas typiques. L'absence de gestion/validation explicite pour une capacité nulle ou négative est une petite lacune pratique.

Respect des consignes

Poids 10%
100

Suit les instructions à la lettre : n'utilise ni OrderedDict ni functools.lru_cache, utilise une liste chaînée manuelle avec une table de hachage pour des opérations en O(1), et inclut la démonstration spécifiée produisant les sorties attendues.

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

3 / 3

Score moyen

99
Voir cette reponse

Votes gagnants

0 / 3

Score moyen

98
Voir cette reponse

Resultats de l evaluation

X f L