XD blog

blog page

print


2013-11-08 De l'idée au programme informatique

Lorsqu'on apprend à programmer, on a souvent une idée précise de l'objectif à atteindre et pourtant, on reste perplexe devant l'écran ne sachant pas par où commencer. Par exemple, si on dispose d'une matrice de trois colonnes :
xypoids
AC3
AD1
AE4
BD6
Et on souhaite calculer combien de fois on a le couple (x,y) divisé par combien de fois on a x :

 \frac{ \# (x,y) } { \# x }

Par exemple, si x=A et y=D, on aura 1 / (3 + 1 + 4) = 0.125. Maintenant, comment s'y prend-on ?

Tout d'abord, on cherche à calculer un ratio de trucs qui ne sont pas des nombres entiers. Un dictionnaire est tout indiqué pour stocker ces trucs car il permet d'associer n'importe quoi (valeur) à presque n'importe quoi (clé). La valeur est une somme d'entiers, la clé est un couple de lettres ou une lettre. Sans me soucier des petits détails, voilà ce que j'ai envie d'écrire comme premier jet :

l = [ ['A','B', 3], ['A','C', 1], 
      ['A','E', 4], ['B','D', 6], ]

def transition(l):
    d = {}
    for x,y,n in l :
        d [x,y] += n  # erreur ici : KeyError: ('A', 'B')
        d [x] += n
    
    for x,y in d :
        d[x,y] /= d [x]
    return d
    
print (transition(l))

Bien sûr ça ne marche pas (voir l'erreur ci-dessus). Mais j'ai foi en moi. La logique est bonne. Lorsque j'écris d [a,b] += n, je suppose que le couple (x,y) existe dans le dictionnaire même la toute première fois. Et c'est pas possible ! Il est vide au début.

l = [ ['A','B', 3], ['A','C', 1], 
      ['A','E', 4], ['B','D', 6], ]

def transition(l):
    d = {}
    for x,y,n in l :
        if (x,y) not in d : d[x,y] = 0   # j'ajoute la clé si elle est absente 
        d [x,y] += n  
        if x not in d : d[x] = 0   # j'ajoute la clé si elle est absente 
        d [x] += n
    
    for x,y in d :         # erreur ici : ValueError: need more than 1 value to unpack
        d[x,y] /= d [x]
    return d
    
print (transition(l))

Ca ne marche pas mieux mais on avance. L'erreur est plus loin (ce qui ne veut pas forcément dire grand chose)... Mais en fait, là je ne comprends pas ce qu'il se passe. Donc je mets des print.

l = [ ['A','B', 3], ['A','C', 1], 
      ['A','E', 4], ['B','D', 6], ]

def transition(l):
    d = {}
    for x,y,n in l :
        if (x,y) not in d : d[x,y] = 0
        d [x,y] += n  
        if x not in d : d[x] = 0
        d [x] += n
    
    for cle in d :         
        print (cle)     # valeurs affichées ('A', 'C') et puis ('A', 'E') et puis ('A', 'B') et B
        x,y = cle       # erreur ici : ValueError: need more than 1 value to unpack
        d[x,y] /= d [x]
    return d
    
print (transition(l))

Ca affiche des choses mais comme je ne suis pas certain de ce que je devrais lire. Tout ce que je sais est que la dernière valeur traitée est cle='B' mais si ça se trouve, il n'y en a pas d'autre. Je remets un coup de print pour savoir. J'affiche un plus avant la ligne incriminée, et un moins derrière. Si je vois un + et un -, c'est bon. Si je ne vois qu'un +, c'est pas bon.

l = [ ['A','B', 3], ['A','C', 1], 
      ['A','E', 4], ['B','D', 6], ]

def transition(l):
    d = {}
    for x,y,n in l :
        if (x,y) not in d : d[x,y] = 0
        d [x,y] += n  
        if x not in d : d[x] = 0
        d [x] += n
    
    for cle in d :         
        print ("+",cle)
        x,y = cle
        print ("-",cle)
        x,y = cle       
        d[x,y] /= d [x]
    return d
    
print (transition(l))

Et ça donne :

+ ('A', 'C')
- ('A', 'C')
+ ('A', 'E')
- ('A', 'E')
+ ('B', 'D')
- ('B', 'D')
+ B

J'ai compris, c'est B qui plante. Il est tout seul et je peux pas le couper en deux pour avoir x,y. Je corrige de telle sorte que je ne découpe cle en x,y que lorsqu'il y a deux lettres :

l = [ ['A','B', 3], ['A','C', 1], 
      ['A','E', 4], ['B','D', 6], ]

def transition(l):
    d = {}
    for x,y,n in l :
        if (x,y) not in d : d[x,y] = 0
        d [x,y] += n  
        if x not in d : d[x] = 0
        d [x] += n
    
    for cle in d :         
        if len(cle) == 2 :    # deux lettres ?
            x,y = cle       
            d[x,y] /= d [x]
    return d
    
print (transition(l))

Et j'ai bien le résultat souhaité :

{('A', 'B'): 0.375, ('A', 'C'): 0.125, ('B', 'D'): 1.0, 'B': 6, 'A': 8, ('A', 'E'): 0.5}

Il ne reste plus qu'à passer à de plus grands tableaux.

On verra ça un autre jour.


Xavier Dupré