Codage/décodage d'une liste d'entiers en une autre liste d'entiers uniques

Fermé
corebreaker - 6 août 2020 à 18:48
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 - 7 août 2020 à 22:50
Bonjour,

Je cherche un algorithme qui prend en entrée une liste d'entiers (qu'on nomme `l`) dont les valeurs sont comprises dans l'intervalle 0 à N exclus, et qui produit une liste d'entiers (qu'on nomme `r`) dans le même intervalle de valeur. La liste en entrée contient au plus N valeurs.

Les contraintes de la liste produite sont:
- Sa taille doit être au plus celle la même taille que la liste d'entrée (len(r) <= len(l))
- Chaque valeur est unique, il n'y a pas de doublons

J'ai déjà programmée une version mais les contraintes ne sont respectée pour des listes qui en moyenne font une taille de N/4 soit 25%. J'aimerais un algo qui puisse accepter des listes d'au moins 50% en moyenne (75% serait encore mieux).

Voici la version en Python de cet encodeur:
def encode(l, N):
    size = N // 2
 
    vals = list(range(size))
    r = []
 
    for i in l:
        idx = i % len(vals)
 
        v = vals[idx]
        if i > len(vals):
            v += size
 
        r.append(v)
 
        del vals[idx]
 
    return r


Le décodeur associé:
def decode(l, N):
    size = N // 2
 
    vals = list(range(size))
    r = []
 
    for i in l:
        after = i >= size
 
        if after:
            i -= size
 
        v = vals.index(i)
        idx = v
        if after:
            v += len(vals)
 
        r.append(v)
 
        del vals[idx]
 
    return r


Enfin une fonction qui sert à vérifier les contraintes:
def check(l, N):
    cod = encode(l, N)
    sz = len(cod)
 
    if sz > len(l):
        raise Exception('The length of the encoded list can exceed the len of the input list')
 
    if sz != len(set(cod)):
        raise Exception('The values are not unique')
 
    if decode(cod, N) != l:
        raise Exception('The decoded list is wrong')

4 réponses

yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 Ambassadeur 1 557
6 août 2020 à 20:46
bonjour, je pense que ton code n'est pas du tout adéquat. il me semble que tu as codé avant d'avoir bien réfléchi à l'énoncé de l'exercice.
peux-tu expliquer comment tu imagines résoudre cet exercice?
je suggère que tu commences avec un exemple d'une petite liste, et que tu réfléchisses et explique la solution que tu imagines.
0
Bonjour, en substance il est résolu, il existe des solutions, je cherche juste une solution plus performante.

De plus, ce n'est pas un exercice, ce n'est pas pour s'exercer, mais un problème à résoudre.

Et oui le code n'est pas adapté, et c'est justement cela le problème, je demande de l'améliorer. Comme indiqué dans la description du problème.

J'ai déjà une solution, donc j'ai imaginé comment résoudre le problème, c'est juste que ma solution n'est pas assez performante.

L'exemple est simple c'est simplement quelque chose du genre :
import random
N = CE_QU_ON_VEUT
X = N//4 # Là je veux avoir N//2 ou 3*N//4
check([random.choice(range(N)) for _ in range(X)], N)
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557
6 août 2020 à 22:15
dans quel contexte veux-tu résoudre ce problème?
le code que tu montres est-il la solution au problème?
je te recommande d'oublier python quelques minutes, de donner un exemple de liste l, et de réfléchir comment obtenir une(des) liste(s) r correspondante(s).
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557 > yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024
6 août 2020 à 22:17
relisant l'énoncé de ton problème/exercice, je dirais qu'une liste vide est une solution.
n'est-il pas simple de programmer une fonction qui retourne une liste vide?
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557
7 août 2020 à 09:54
je me demande comment tu as testé ton code que tu présentes comme une solution: j'ai presque toujours "The decoded list is wrong".
ce qui me semble logique, le problème n'ayant pas de solution.
0
Est-ce que le décodage d'une liste vide pourra retrouver ta liste d'origine, je ne pense pas donc la liste vide n'est pas une solution car il n'est pas en accord avec l'énoncé. Donc non, en lisant l'énoncé tu ne peux pas en déduire que la liste vide est une solution c'est tout le contraire.

Je veux bien oublier Python, mais l'exemple en Python est un cas concret, chose que tu as demandé.

Il n'y a pas besoin de contexte pour résoudre ce problème. Il est suffisamment clair et complet, aucun élément ne manque. Il y a même la façon de tester la solution grâce à la fonction `check`.

Je ne comprends ce qui manque:
1. tu prends une liste de valeurs quelconque dans l'intervalle défini
2. tu encodes cette liste et en obtiens une autre en suivant les contraintes
3. tu vérifies en passant cette liste résultante au décodeur et tu regarde que tu obtiens bien la liste d'origine.

Peut importe les valeurs obtenues, il juste que le décodeur puisse retrouver les valeur passée à l'encodeur, il faut juste que l'encodeur produise des valeurs qui suivent les contraintes.

Franchement, je ne comprends pas quelle genre d'information manque, tout est là.

Encore une fois (je me répète), la solution que je propose est une solution mais j'en cherche une meilleure, je ne comprends vraiment pas, j'ai utilisé un vocabulaire suffisamment clair pourtant.

Ce qui est dans l'énoncé est «J'ai déjà programmé une version mais les contraintes ne sont respectée pour des listes qui en moyenne font une taille de N/4 soit 25%».

«J'ai déjà programmé une version» est je pense dans son sens quelque chose qui dit que j'ai déjà une solution. Ou alors ma notion de «déjà» n'est pas la même que tout le monde ?

En plus, j'ai fait l'effort de publier un exemple d'encodeur et de décodeur pour avoir un exemple de résultat attendu afin de les corréler avec l'énoncé. Normalement, juste appeler la fonction `encode` et de voir le résultat et de le faire correspondre avec l'énoncé c'est simple.

Par exemple tu fais cela:
import random
N = 256
X = N//4
print(encode([random.choice(range(N)) for _ in range(X)], N))


Et tu vérifies avec l'énoncé: «les valeurs sont-elles uniques ?», etc.
Je ne comprends le problème, où est la difficulté ?
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557
6 août 2020 à 23:21
en quoi la liste vide ne correspond-elle pas à l'énoncé?

quel est le contexte de cet exercice? il me semble que l'énoncé est incohérent, peut-être incomplet.

je suggère que tu réfléchisses à un cas concret, avec des données. les programmes que tu proposent ne sont pas des solutions adéquates.

montre-nous un exemple de liste l et du résultat obtenu pas tes codes.
0
corebreaker > yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024
Modifié le 7 août 2020 à 00:14
Ecoute, laisse tombé car visiblement je me répète trop souvent (j'ai déjà précisé pourquoi la liste vide ne fonctionne pas), il faut lire attentivement et pas en diagonale.

L'énoncé est clair, complet et cohérent, rien ne manque.

Le code est en exemple, c'est une manière d'appliquer l'algorithme, je veux bien faire de l'algorithmique théorique dénuée de tout code ou du formalisme mathématique mais je ne pense pas que ce sera plus clair pour toi.

Et encore une fois, j'ai déjà mis un exemple. Si tu lances l'instruction python tu aura la liste qui peut être en exemple, ça ne sert à rien que je te donne cette liste: `[23, 4, 53, 53, 2, 54]`, je ne pense pas que ce soit plus utile.

Lance le code et tu auras ta liste, c'est plus simple en général que de taper une série de chiffres, car le code tu peux le lancer avec différentes valeurs alors que si je poste 10 ou 20 listes ici, c'est moins utile que de lancer 50 fois le code.

J'ai déjà réfléchi à un cas concret, ne me fait pas la leçon STP, le cas concret est le résultat quand tu lances le code, comme le code fonctionne, tu obtiendras forcément un cas concret. Les contraintes sont dans le code donc tout y est. Je ne voit pas pourquoi il faudrait occulter le code car il aide justement d'appui à l'énoncé.

Je ne comprends pas pourquoi tu demandes un seul cas concret alors que tu peux en produire des milliers avec le code, vouloir poster ici un seul cas concret est assez inefficace voire contre -productif.

Si tu ne veux pas du code suit juste l'énoncé qui est clair, complet, et cohérent. Mais avec le code ça aide, je pense.

Mais bon sinon je te dis laisse tomber, tu dis que l'énoncée est incomplet alors que c'est complètement faux, il y a toutes les informations, simplement tu ne les comprends, peut-être est-trop compliqué pour toi et tu dis juste que c'est incomplet alors que tout y est.

Donc, pas grave, passe à autre chose.
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557 > corebreaker
7 août 2020 à 08:47
si la liste l est [23, 4, 53, 53, 2, 54], qu'attends-tu comme liste r?
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 Ambassadeur 1 557
7 août 2020 à 08:55
ah, je commence à comprendre.
tu n'as écrit qu'une partie de l'énoncé: tu veux aussi que la liste l puisse être reconstruite à partir de la liste r!
ai-je bien deviné?
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557
Modifié le 7 août 2020 à 09:46
examinons alors si une solution est possible. intuitivement, il n'y a pas de solution. examinons cela.
pour pouvoir garantir la reconstruction de la liste l à partir de la liste r, il faut que le nombre de listes r soit au moins égal au nombre de listes l.
je pense que cela n'est possible que si la liste ne contient qu'un seul élément.
import math
def possible(N,X):
    L=N**X
    R=int(math.factorial(N)/math.factorial(N-X))
    if L > R:
        res="NOK"
    else:
        res="ok"
    print(N,X,L,R,res)
0
quent217 Messages postés 421 Date d'inscription vendredi 25 septembre 2015 Statut Membre Dernière intervention 1 mars 2024 347 > yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024
7 août 2020 à 18:54
Bonjour,
dans votre calcul, vous supposez que la liste r fait la même taille que la liste l, ce qui n'est pas forcément le cas. Si on prend en compte les listes r plus petite que l, le calcul devient le suivant :
import math
def possible(N,X):
    L=N**X
    R=sum(int(math.factorial(N)/math.factorial(N-i)) for i in range(X+1))
    if L > R:
        res="NOK"
    else:
        res="ok"
    print(N,X,L,R,res)

Ca a donc l'air possible pour les listes allant jusqu'à 2 éléments. Ça ne change pas grand chose mais je voulais le préciser ^^'
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557 > quent217 Messages postés 421 Date d'inscription vendredi 25 septembre 2015 Statut Membre Dernière intervention 1 mars 2024
7 août 2020 à 22:50
en effet, bien vu!
on peut alors encoder ainsi:
si deux éléments identiques dans la liste l, la liste r n'a qu'un élément, reprenant une des valeurs dans la liste l.
sinon, r=l.
0