Initiation à la programmation ENSAE 1A

support de cours, version longue

File: chap1_introduction.tex, line 185


>>> x = 3
>>> y = 6 
>>> z = x * y
>>> print z
18
>>>

File: chap1_introduction.tex, line 258


if PLAT_WIN
    command.go.*.py=python -u "$(FileNameExt)"
    command.go.subsystem.*.py=0
    command.go.*.pyw=pythonw -u "$(FileNameExt)"
    command.go.subsystem.*.pyw=1

File: chap1_introduction.tex, line 266


if PLAT_WIN
    command.go.*.py=c:\Python26\python -u "$(FileNameExt)"
    command.go.subsystem.*.py=0
    command.go.*.pyw=c:\Python26\pythonw -u "$(FileNameExt)"
    command.go.subsystem.*.pyw=1

File: chap1_introduction.tex, line 340


print "premier message"

File: chap1_introduction.tex, line 344


print 3.141592 * 5*5
print 3.141592 * 5**2

File: chap1_introduction.tex, line 349


from math import *  # permet d'utiliser les extensions mathématiques de Python
print pi * 5**2

File: chap1_introduction.tex, line 356


print (3.141592 * 5*5)

File: chap1_introduction.tex, line 366


print "accentué"

File: chap1_introduction.tex, line 372


  File "essai.py", line 1
SyntaxError: Non-ASCII character '\xe9' in file i.py on line 1, 
             but no encoding declared; 
             see http://www.python.org/peps/pep-0263.html for details

File: chap1_introduction.tex, line 381


# coding: latin-1
print "accentué"

File: chap1_introduction.tex, line 390


# coding: cp1252
print "accentué"

File: chap1_introduction.tex, line 399


# coding: utf-8
print "accentué"

File: chap1_introduction.tex, line 411


#!/usr/local/bin/python

File: chap1_introduction.tex, line 524


import psyco
psyco.full ()

File: chap1_introduction.tex, line 596


import matplotlib.pylab as pylab

File: chap1_introduction.tex, line 603


#!/usr/bin/env pythonw2.6
import matplotlib
matplotlib.use("WXAgg")
import matplotlib.pylab as pylab

File: chap1_introduction.tex, line 618


2004-08-07 21:08:15.153 Python[695] *** _NSAutoreleaseNoPool(): Object
0x30ead0 of class NSCFArray autoreleased with no pool in place - just
leaking

File: chap2_type.tex, line 22


somme = 0                   # initialisation : la somme est nulle 
for i in range(1,n) :       # pour tous les indices de 1 à n exclu
    somme = somme + i       # on ajoute le i ème élément à somme

File: chap2_type.tex, line 55


x   = 3.5      # création d'une variable nombre réel appelée x initialisée à 3.5
               # 3.5 est un réel, la variable est de type "float"
sc = "chaîne"  # création d'une variable chaîne de caractères appelée str 
               # initialisée à "chaîne", sc est de type "str"

File: chap2_type.tex, line 70


x = 3          # affectation de la valeur entière 3 à la variable x
y = 3.0        # affectation de la valeur réelle 3.0 à la variable y

File: chap2_type.tex, line 83


x = 
    5.5

File: chap2_type.tex, line 94


x =  \
    5.5

File: chap2_type.tex, line 128


s = None
print s    # affiche None

File: chap2_type.tex, line 146


x = 3
y = 3.0
print "x =", x, type(x)
print "y =", y, type(y)

File: chap2_type.tex, line 155




x = 3 <type 'int'>
y = 3.0 <type 'float'>

File: chap2_type.tex, line 196


x = int (3.5)
y = float (3)
z = int ("3")
print "x:", type(x), "   y:", type(y), "   z:", type(z)
# affiche   x: <type 'int'>    y: <type 'float'>    z: <type 'int'>

File: chap2_type.tex, line 207


i = int ("3.5")          # provoque une erreur
i = int (float ("3.5"))  # fonctionne

File: chap2_type.tex, line 221


x = 11
y = 2
z = x / y      # le résultat est 5 et non 5.5 car la division est entière

File: chap2_type.tex, line 229


x = float (11)
y = float (2)
z = x / y      # le résultat est 5.5 car c'est une division entre deux réels

File: chap2_type.tex, line 255


x = 4 < 5
print x         # affiche True
print not x     # affiche False

File: chap2_type.tex, line 287


x = True
y = False

File: chap2_type.tex, line 309


t = "string = texte"
print type (t), t
t = 'string = texte, initialisation avec apostrophes'
print type (t), t

t = "morceau 1" \
    "morceau 2"    # second morceau ajouté au premier par l'ajout du symbole \, 
                   # il ne doit rien y avoir après le symbole \, 
                   # pas d'espace ni de commentaire
print t

t = """première ligne		
seconde ligne"""   # chaîne de caractères qui s'étend sur deux lignes
print t

File: chap2_type.tex, line 330


<type 'str'> string = texte
<type 'str'> string = texte, initialisation avec apostrophes
morceau 1morceau 2
première ligne
seconde ligne

File: chap2_type.tex, line 374


s = "C:\\Users\\Dupre\\exemple.txt"
s = r"C:\Users\Dupre\exemple.txt"

File: chap2_type.tex, line 395


x = 5.567
s = str (x)
print type(s), s   # <type 'str'> 5.567
print len(s)       # affiche 5

File: chap2_type.tex, line 444



res = s.fonction (...)

File: chap2_type.tex, line 535


st = "langage python"
st = st.upper ()              # mise en lettres majuscules
i  = st.find ("PYTHON")       # on cherche "PYTHON" dans st
print i                       # affiche 8
print st.count ("PYTHON")     # affiche 1
print st.count ("PYTHON", 9)  # affiche 0

File: chap2_type.tex, line 549


s    = "un;deux;trois"
mots = s.split (";")        # mots est égal à ['un', 'deux', 'trois']
mots.reverse ()             # retourne la liste, mots devient égal à 
                            #                 ['trois', 'deux', 'un']
s2 = ";".join (mots)        # concaténation des éléments de mots séparés par ";"
print s2                    # affiche trois;deux;un

File: chap2_type.tex, line 569



".... %c1  ....  %c2 " % (v1,v2)

File: chap2_type.tex, line 579


x = 5.5
d = 7
s = "caractères"
res =   "un nombre réel %f et un entier %d, une chaîne de %s, \n" \
        "un réel d'abord converti en chaîne de caractères %s" % (x,d,s, str(x+4))
print res        
res =   "un nombre réel " + str (x) + " et un entier " + str (d) + \
        ", une chaîne de " + s + \
        ",\n un réel d'abord converti en chaîne de caractères " + str(x+4)
print res        

File: chap2_type.tex, line 595


un nombre réel 5.500000 et un entier 7, une chaîne de caractères, 
un réel d'abord converti en chaîne de caractères 9.5
un nombre réel 5.5 et un entier 7, une chaîne de caractères,
un réel d'abord converti en chaîne de caractères 9.5

File: chap2_type.tex, line 606



"%n.df" % x

File: chap2_type.tex, line 618


x = 0.123456789
print x             # affiche 0.123456789
print "%1.2f" % x   # affiche 0.12
print "%06.2f" % x  # affiche 000.12

File: chap2_type.tex, line 651


x = (4,5)               # création d'un T-uple composé de 2 entiers
x = ("un",1,"deux",2)   # création d'un T-uple composé de 2 chaînes de caractères
                        # et de 2 entiers, l'ordre d'écriture est important
x = (3,)                # création d'un T-uple d'un élément, sans la virgule, 
                        # le résultat est un entier

File: chap2_type.tex, line 713


a     = (4,5)
a [0] = 3      # déclenche une erreur d'exécution

File: chap2_type.tex, line 720


Traceback (most recent call last):
  File "<pyshell#78>", line 1, in -toplevel-
    a[0]=3
TypeError: object doesn't support item assignment

File: chap2_type.tex, line 729


a = (4,5)
a = (3,) + a[1:2]  # crée un T-uple d'un élément concaténé 
                   # avec la partie inchangée de a

File: chap2_type.tex, line 745


print complex (1,1)   # affiche (1+1j)

File: chap2_type.tex, line 786


x = [4,5]               # création d'une liste composée de deux entiers
x = ["un",1,"deux",2]   # création d'une liste composée de 
                        # deux chaînes de caractères
                        # et de deux entiers, l'ordre d'écriture est important
x = [3,]                # création d'une liste d'un élément, sans la virgule, 
                        # le résultat reste une liste
x = [ ]                 # crée une liste vide
x = list ()             # crée une liste vide
y = x [0]               # accède au premier élément
y = x [-1]              # accède au dernier élément

File: chap2_type.tex, line 958


[9, 0, 3, 5, 4, 7, 8]
[0, 3, 4, 5, 7, 8, 9]

File: chap2_type.tex, line 964


def compare (x,y):           # crée une fonction
    if   x >  y : return -1  # qui retourne -1 si x<y,
    elif x == y : return 0   # 0 si x == y
    else        : return 1   # 1 si x < y

x.sort (compare)             # trie la liste x à l'aide de la fonction compare
                             # cela revient à la trier par ordre décroissant
print x

File: chap2_type.tex, line 979


[9, 8, 7, 5, 4, 3, 0]

File: chap2_type.tex, line 987


x = [9,0,3,5,0]
print x.index (1) # cherche la position de l'élément 1

File: chap2_type.tex, line 996


Traceback (most recent call last):
  File "c:/temp/temp", line 2, in -toplevel-
    print x.index(1)
ValueError: list.index(x): x not in list

File: chap2_type.tex, line 1007


x = [9,0,3,5,0]
try:               print x.index(1)
except ValueError: print "1 n'est pas présent dans la liste x"
else:              print "trouvé"

File: chap2_type.tex, line 1018


1 n'est pas présent dans la liste x

File: chap2_type.tex, line 1030



range (debut, fin [,marche])

File: chap2_type.tex, line 1043


print range (0,10,2)       # affiche [0, 2, 4, 6, 8]

File: chap2_type.tex, line 1051


print xrange (0,10,2)      # affiche xrange(0,10,2)

File: chap2_type.tex, line 1062


s = 0
for n in range (1,20,2) :  # ce programme est équivalent à
    s += n                 # s = sum (range(1,20,2))

File: chap2_type.tex, line 1073


x = ["un", 1, "deux", 2, "trois", 3]
for n in range (0, len(x)) :
    print "x [%d] = %s" % (n, x [n])
    
# le résultat est présenté à droite    
    

File: chap2_type.tex, line 1084


x [0] = un
x [1] = 1
x [2] = deux
x [3] = 2
x [4] = trois
x [5] = 3

File: chap2_type.tex, line 1105


x = ["un", 1, "deux", 2]
for el in x :  
    print "la liste inclut : ", el

File: chap2_type.tex, line 1115


la liste inclut :  un
la liste inclut :  1
la liste inclut :  deux
la liste inclut :  2

File: chap2_type.tex, line 1126


y = list ()
for i in range(0,5) : y.append (i+1)
print y                                # affiche [1,2,3,4,5]        

File: chap2_type.tex, line 1137


y = [ i+1 for i in range (0,5)]
print y                                # affiche [1,2,3,4,5]        

File: chap2_type.tex, line 1147


y = [ i for i in range(0,5) if i % 2 == 0]   # sélection les éléments pairs
print y                                      # affiche [0,2,4]        
z = [ i+j for i in range(0,5) \
          for j in range(0,5)]      # construit tous les nombres i+j possibles
print z                             # affiche [0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 
                                    # 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8]

File: chap2_type.tex, line 1162


a = (1,0,7,0,0,0)
b = [2,2,3,5,5,5]
c = [ "un", "deux", "trois", "quatre" ]
d = zip (a,b,c)
print d           # affiche [(1, 2, 'un'),    (0, 2, 'deux'), 
                  #          (7, 3, 'trois'), (0, 5, 'quatre')]

File: chap2_type.tex, line 1177


s = ""
while <condition> : s += ...
    

File: chap2_type.tex, line 1185


s = []
while <condition> : s.append ( ... )
s = "".join (s)

File: chap2_type.tex, line 1201


l  = [4,5,6]
l2 = l
print l            # affiche [4,5,6]
print l2           # affiche [4,5,6]
l2 [1] = "modif"
print l            # affiche [4, 'modif', 6]
print l2           # affiche [4, 'modif', 6]

File: chap2_type.tex, line 1213


l      = [[0,1], [2,3]]
l1     = l [0]
l1 [0] = "modif" # ligne équivalente à : l [0][0] = "modif"

File: chap2_type.tex, line 1223


import copy
l  = [4,5,6]
l2 = copy.copy(l)
print l            # affiche [4,5,6]
print l2           # affiche [4,5,6]
l2 [1] = "modif"
print l            # affiche [4,5,6]
print l2           # affiche [4, 'modif', 6]

File: chap2_type.tex, line 1238


import copy
l  = [1,2,3]
l2 = copy.copy (l)
l3 = l

print l == l2  # affiche True
print l is l2  # affiche False
print l is l3  # affiche True 

File: chap2_type.tex, line 1253


import copy
l  = [[1,2,3],[4,5,6]]
l2 = copy.copy (l)
l3 = copy.deepcopy (l)
l [0][0] = 1111
print l                # affiche [[1111, 2, 3], [4, 5, 6]]
print l2               # affiche [[1111, 2, 3], [4, 5, 6]]
print l3               # affiche [[1, 2, 3], [4, 5, 6]]
print l is l2          # affiche False
print l [0] is l2 [0]  # affiche True
print l [0] is l3 [0]  # affiche False

File: chap2_type.tex, line 1270


l     = [1,"a"]
ll    = [l,3]   # ll contient l
l [0] = ll      # l contient ll
print l         # affiche [[[...], 3], 'a']
print ll        # affiche [[[...], 'a'], 3]

import copy
z = copy.deepcopy (l)
print z         # affiche [[[...], 3], 'a']

File: chap2_type.tex, line 1306


x = { "cle1":"valeur1", "cle2":"valeur2" }
y = { }         # crée un dictionnaire vide
z = dict ()     # crée aussi un dictionnaire vide

File: chap2_type.tex, line 1316


print x ["cle1"]

File: chap2_type.tex, line 1443


d = { "un":1, "zéro":0, "deux":2, "trois":3, "quatre":4, "cinq":5, \
       "six":6, "sept":1, "huit":8, "neuf":9, "dix":10 }
key = d.keys ()
key.sort ()
for k in key:
    print k,d [k]

File: chap2_type.tex, line 1456


d = { "un":1,   "zero":0, "deux":2, "trois":3, "quatre":4, "cinq":5, \
      "six":6,  "sept":1, "huit":8, "neuf":9,  "dix":10 }
       
dinv = { }                      # création d'un dictionnaire vide, on parcout
for key,value in d.items ()  :  # les éléments du dictionnaire comme si
                                # c'était une liste de 2-uple (clé,valeur)
    dinv [value] = key          # on retourne le dictionnaire

print dinv                      # affiche {0: 'zero', 1: 'un', 2: 'deux', 
                                # 3: 'trois', 4: 'quatre', 5: 'cinq', 6: 'six', 
                                # 8: 'huit', 9: 'neuf', 10: 'dix'}

File: chap2_type.tex, line 1474


d = { "un":1, "zero":0, "deux":2, "trois":3, "quatre":4, "cinq":5, \
       "six":6, "sept":1, "huit":8, "neuf":9, "dix":10 }
print d.items ()
print d.iteritems ()

File: chap2_type.tex, line 1483


[('trois', 3), ('sept', 1), ('neuf', 9), ('six', 6), ('zero', 0), 
 ('un', 1), ('dix', 10), ('deux', 2), ('huit', 8), ('quatre', 4), 
                                                      ('cinq', 5)]
 
<dictionary-itemiterator object at 0x0115DC40>

File: chap2_type.tex, line 1495


  File "essai.py", line 6, in <module>
    for k in d :
RuntimeError: dictionary changed size during iteration

File: chap2_type.tex, line 1508


d  = {4:4,5:5,6:6}
d2 = d
print d            # affiche {4: 4, 5: 5, 6: 6}
print d2           # affiche {4: 4, 5: 5, 6: 6}
d2 [5] = "modif"
print d            # affiche {4: 4, 5: 'modif', 6: 6}
print d2           # affiche {4: 4, 5: 'modif', 6: 6}

File: chap2_type.tex, line 1523


d  = {4:4,5:5,6:6}
import copy
d2 = copy.copy(l)
print d            # affiche {4: 4, 5: 5, 6: 6}
print d2           # affiche {4: 4, 5: 5, 6: 6}
d2 [5] = "modif"
print d            # affiche {4: 4, 5: 5, 6: 6}
print d2           # affiche {4: 4, 5: 'modif', 6: 6}

File: chap2_type.tex, line 1544


k = { 1:1}
d = { }
d [k] = 0



File: chap2_type.tex, line 1554


Traceback (most recent call last):
  File "cledict.py", line 3, in <module>
    d [k] = 0
TypeError: dict objects are unhashable

File: chap2_type.tex, line 1567


k = { 1:1}
d = { }
d [id (k)] = 0

File: chap2_type.tex, line 1575


k = {1:1}
d = { }
d [id (k)] = 0
b = k
print d [id(b)]  # affiche bien zéro
c = {1:1}
print d [id(c)]  # provoque une erreur car même si k et c ont des contenus égaux,
                 # ils sont distincts, la clé id(c) n'existe pas dans d

File: chap2_type.tex, line 1590


class A : pass

k = A ()
d = { }
d [k] = 0
print d                   # affiche {<__main__.A object at 0x0120DB90>: 0}
print id (k), hex(id(k))  # affiche 18930576, 0x120db90
print d [id(k)]           # provoque une erreur

File: chap2_type.tex, line 1605


class A (dict):
    def __hash__(self):
        return id(self)
        
k = A ()
k ["t"]= 4
d = { }
d [k] = 0
print d         # affiche {{'t': 4}: 0}

File: chap2_type.tex, line 1635


x == eval (repr(x)) # est toujours vrai (True)
x == eval (str (x)) # n'est pas toujours vrai

File: chap2_type.tex, line 1648


x  = 32
y  = 9
op = "+ - * / % // & | and or << >>".split ()
for o in op :
    s = str (x) + " " + o + "  " + str (y)
    print s, " = ", eval (s)

File: chap2_type.tex, line 1661


32 +  9  =  41
32 -  9  =  23
32 *  9  =  288
32 /  9  =  3
32 %  9  =  5
32 //  9  =  3
32 &  9  =  0
32 |  9  =  41
32 and  9  =  9
32 or  9  =  32
32 <<  9  =  16384
32 >>  9  =  0

File: chap2_type.tex, line 1687


x = 3
print dir ()

File: chap2_type.tex, line 1694


['__builtins__', '__doc__', '__file__', '__name__', 'x']

File: chap2_type.tex, line 1733


x = 3
print x, type(x)     # affiche 3 <type 'int'>
x = 3.5
print x, type(x)     # affiche 3.5 <type 'float'>

File: chap2_type.tex, line 1754


x = 5       # affecte 5 à x
y = 6       # affecte 6 à y
x,y = 5,6   # affecte en une seule instruction 5 à x et 6 à y

File: chap2_type.tex, line 1767


x,y = divmod (17,5)
print x,y                          # affiche 3 2
print "17 / 5 = 5 * ", x, " + ",y  # affiche 17 / 5 = 5 *  3  +  2

File: chap2_type.tex, line 1778


x,y = point = 5,5

File: chap2_type.tex, line 1789


i = int(2**28)   
for k in range (0,4) :
    i *= int(2)
    print type(i),i

File: chap2_type.tex, line 1798


<type 'int'> 536870912
<type 'int'> 1073741824
<type 'long'> 2147483648
<type 'long'> 4294967296

File: chap2_type.tex, line 1815


print set ( (1,2,3) ) & set ( (2,3,5) )  
           # construit l'intersection qui est set([2, 3])

File: chap3_syntaxe.tex, line 44


initialisation de la variable moy à 0
faire pour i allant de 1 à N
      moy reçoit moy + ni
moy reçoit moy / N

File: chap3_syntaxe.tex, line 53


ligne 1 : initialisation de la variable moy à 0
ligne 2 : initialisation de la variable i à 1
ligne 3 : moy reçoit moy + ni
ligne 4 : i reçoit i + 1
ligne 5 : si i est inférieur ou égal à N alors aller à la ligne 3
ligne 6 : moy reçoit moy / N

File: chap3_syntaxe.tex, line 75


import keyword
print keyword.iskeyword("for")     # affiche True
print keyword.iskeyword("until")   # affiche False

File: chap3_syntaxe.tex, line 144



if condition1 :
   instruction1
   instruction2
   ...
else :
   instruction3
   instruction4
   ...

File: chap3_syntaxe.tex, line 158


if condition1 :
   instruction1
   instruction2
   ...

File: chap3_syntaxe.tex, line 168


if condition1 :
   instruction1
   instruction2
   ...
elif condition2 :
   instruction3
   instruction4
   ...
elif condition3 :
   instruction5
   instruction6
   ...
else :
   instruction7
   instruction8
   ...

File: chap3_syntaxe.tex, line 207


le nombre est positif
le nombre est négatif
signe = 1

File: chap3_syntaxe.tex, line 232


  File "test.py", line 7
    print "le nombre est négatif" 
                                 ^
IndentationError: unindent does not match any outer indentation level

File: chap3_syntaxe.tex, line 293


if condition :
    instruction1
else :
    instruction2

File: chap3_syntaxe.tex, line 306


if condition : instruction1
else : instruction2



File: chap3_syntaxe.tex, line 333


x = -5
if x < 0 :
   signe = -1
elif x == 0 :
   signe = 0
else :
   signe = 1

File: chap3_syntaxe.tex, line 349


x = -5
if x < 0 : signe = -1
elif x == 0 : signe = 0
else : signe = 1




File: chap3_syntaxe.tex, line 366


s = raw_input ("dites oui : ")    # voir remarque suivante
if s == "oui" or s [0:1] == "o" or s [0:1] == "O" or s == "1" :
       print "oui"
else : print "non"

version graphique de la fonction \codesindex{raw\_input

import Tkinter
def question (legende) :
    reponse = [""]
    root = Tkinter.Tk ()
    root.title ("pseudo raw_input")
    Tkinter.Label (text = legende).pack (side = Tkinter.LEFT)
    s = Tkinter.Entry (text= "def", width=80)
    s.pack (side = Tkinter.LEFT)
    def rget () :
        reponse [0] = s.get ()
        root.destroy ()
    Tkinter.Button (text = "ok", command = rget).pack (side = Tkinter.LEFT)
    root.mainloop ()
    return reponse [0]
    
print "reponse ", question ("texte de la question")  

File: chap3_syntaxe.tex, line 425


signe = 0
x = 0
if x < 0 : signe = -1
elif x == 0:
   pass          # signe est déjà égal à 0
else : signe = 1   

File: chap3_syntaxe.tex, line 437


File "nopass.py", line 6
    else :
    ^
IndentationError: expected an indented block

File: chap3_syntaxe.tex, line 471



while cond : 
    instruction 1
    ...
    instruction n

File: chap3_syntaxe.tex, line 488


n = 0
while n < 3:
   print "à l'intérieur ", n
   n += 1
print "à l'extérieur ", n   

File: chap3_syntaxe.tex, line 502


à l'intérieur  0
à l'intérieur  1
à l'intérieur  2
à l'extérieur  3


File: chap3_syntaxe.tex, line 519


n = 0
while n < 3 :
   print n
   n + 1        # n n'est jamais modifié, l'instruction correcte serait n += 1

File: chap3_syntaxe.tex, line 541



for x in set :
    instruction 1
    ...
    instruction n

File: chap3_syntaxe.tex, line 556


t = (1,2,3,4)
for x in t:       # affiche les nombres 1,2,3,4
    print x       # chacun sur une ligne différente

File: chap3_syntaxe.tex, line 565


d = { 1:2, 3:4, 5:6, 7:-1, 8:-2 }
print d                # affiche le dictionnaire {8: -2, 1: 2, 3: 4, 5: 6, 7: -1}
k = d.keys ()
print k                # affiche les clés [8, 1, 3, 5, 7]
k.sort ()
print k                # affiche les clés triées [1, 3, 5, 7, 8]
for x in k:            # affiche les éléments du dictionnaire 
    print x,":",d [x]  # triés par clés croissantes

File: chap3_syntaxe.tex, line 578


d = { 1:2, 3:4, 5:6, 7:-1, 8:-2 }
for x in sorted(d):    # pour les clés dans l'ordre croissant
    print x,":",d [x]

File: chap3_syntaxe.tex, line 589


sum = 0
N   = 10
for n in range(0,N):     # ou for n in xrange(0,N):  (plus rapide)
   sum += n              # additionne tous les entiers compris entre 0 et N-1

File: chap3_syntaxe.tex, line 598


l   = [ 4, 5, 3, -6, 7, 9]
sum = 0
for n in range(0,len (l)):  # ou for n in xrange(0,len (l)) :  (plus rapide)
   sum += l [n]             # additionne tous les éléments de l

File: chap3_syntaxe.tex, line 613



[ expression for x in ensemble ]

File: chap3_syntaxe.tex, line 623


y = list ()
for i in range(0,5) : 
   y.append (i+1)
print y             # affiche [1,2,3,4,5]        

File: chap3_syntaxe.tex, line 632


y = [ i+1 for i in range(0,5)] # résume trois lignes du programme précédent
print y                        # affiche [1,2,3,4,5]        

File: chap3_syntaxe.tex, line 647


d = ["un", "deux", "trois"]
for x in d: 
   print x          # affichage de tous les éléments de d

File: chap3_syntaxe.tex, line 660


d = ["un", "deux", "trois"]
it = iter (d)                     # obtient un itérateur sur d
while True:
    try: x = it.next ()           # obtient l'élément suivant, s'il n'existe pas
    except StopIteration: break   # déclenche une exception
    print x                       # affichage de tous les éléments de d

File: chap3_syntaxe.tex, line 674


d = [ (1,0,0), (0,1,0), (0,0,1) ]
for v in d: print v

File: chap3_syntaxe.tex, line 683


d = [ (1,0,0), (0,1,0), (0,0,1) ]
for x,y,z in d: print x,y,z

File: chap3_syntaxe.tex, line 691


d = [ (1,0,0), (0,1,0,6), (0,0,1) ]  # un élément de taille quatre
for x,y,z in d: print x,y,z

File: chap3_syntaxe.tex, line 699


Traceback (most recent call last):
  File "c:\temp\delete.py", line 2, in -toplevel-
    for x,y,z in d: print x,y,z
ValueError: unpack tuple of wrong size

File: chap3_syntaxe.tex, line 713


a = range(0,5)
b = [x**2 for x in a]
for x,y in zip (a,b):
    print y, " est le carré de ", x
    # affichage à droite

File: chap3_syntaxe.tex, line 723


0  est le carré de  0
1  est le carré de  1
4  est le carré de  2
9  est le carré de  3
16  est le carré de  4

File: chap3_syntaxe.tex, line 743


d = ["un", "deux", "trois"]
for x in d: print x          # une seule instruction

File: chap3_syntaxe.tex, line 750


d = ["un", "deux", "trois"]
i = 0
while d [i] != "trois" : i += 1
print "trois a pour position ", i

File: chap3_syntaxe.tex, line 769


d = dict ()
for i in range(1,100):            # d [i] est vrai si i est un nombre premier
    d [i] = True                  # au début, comme on ne sait pas, on suppose
                                  # que tous les nombres sont premiers
for i in range(2,100):
                                  # si d [i] est faux, 
   if not d [i]: continue         # les multiples de i ont déjà été cochés
                                  # et peut passer à l'entier suivant
   for j in range (2,100):        
       if i*j < 100: 
           d [i*j] = False        # d [i*j] est faux pour tous les multiples de i
                                  # inférieurs à 100
print "liste des nombres premiers"       
for i in d:
    if d [i]: print i

File: chap3_syntaxe.tex, line 789


d = dict ()
for i in range(1,100): d [i] = True

for i in range(2,100):
   if d [i]:                       
       for j in range (2,100):     
           if i*j < 100 : 
               d [i*j] = False

print "liste des nombres premiers"       
for i in d:
    if d [i]: print i

File: chap3_syntaxe.tex, line 813


l = [6,7,5,4,3]
n = 0
c = 5
for x in l:
   if x == c: break   # l'élément a été trouvé, on sort de la boucle
   n += 1             # si l'élément a été trouvé, cette instruction 
                      # n'est pas exécutée
print "l'élément ",c, " est en position ",
print n               # affiche l'élément 5 est en position 2

File: chap3_syntaxe.tex, line 829


set = range (1,21)
n = 53
for x in set:
    for y in set:
        c = x*x + y*y
        if c == n: break
    if c == n: break   # cette seconde instruction break est nécessaire 
                       # pour sortir de la seconde boucle 
                       # lorsque la solution a été trouvée
if c == n:
    # le symbole \ permet de passer à la ligne sans changer d'instruction
    print n, " est la somme des carrés de deux entiers :", \  
          x, "*", x, "+", y, "*", y, "=", n
else:
    print n, " n'est pas la somme des carrés de deux entiers"

File: chap3_syntaxe.tex, line 849


53  est la somme des carrés de deux entiers : 2 * 2 + 7 * 7 = 53

File: chap3_syntaxe.tex, line 863


L = [6,7,5,4,3]
n = 0
c = 1
for x in L :
   if x == c :
       print "l'élément ", c, " est en position ", n
       break  
   n += 1      
else:
   print "aucun élément ", c, " trouvé"  # affiche aucun élément  1  trouvé

File: chap3_syntaxe.tex, line 886


li = range (0,10)
print li                # affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in range (0, len (li)):
    if i == 5 :
        del li [i:i+2]
    print li [i]        # affiche successivement 0, 1, 2, 3, 4, 7, 8, 9 et 
                        # produit une erreur
print li

File: chap3_syntaxe.tex, line 901


li = range (0,10)
print li                # affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
i = 0
for t in li :
    if i == 5 : del li [i:i+2]
    i = i+1
    print t             # affiche successivement 0, 1, 2, 3, 4, 5, 8, 9
print li                # affiche [0, 1, 2, 3, 4, 7, 8, 9]

File: chap3_syntaxe.tex, line 916


li = range (0,10)
print li                # affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in li :
    if i == 5 : del i
print li                # affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

File: chap3_syntaxe.tex, line 956



def fonction_nom (par_1, ..., par_n) :
    instruction_1
    ...
    instruction_n
    return res_1, ..., res_n

File: chap3_syntaxe.tex, line 971



x_1, ..., x_n = fonction_nom (valeur_1, valeur_2, ..., valeur_n)

File: chap3_syntaxe.tex, line 978


fonction_nom (valeur_1, valeur_2, ..., valeur_n)

File: chap3_syntaxe.tex, line 992


import math
def coordonnees_polaires (x,y):
    rho     = math.sqrt(x*x+y*y)   # calcul la racine carrée de x*x+y*y
    theta   = math.atan2 (y,x)     # calcule l'arc tangente de y/x en tenant 
                                   # compte des signes de x et y
    return rho, theta

def affichage (x,y):
    r,t = coordonnees_polaires(x,y)
    print "cartésien (%f,%f) --> polaire (%f,%f degrés)" \
                  % (x,y,r,math.degrees(t))

affichage (1,1)
affichage (0.5,1)
affichage (-0.5,1)
affichage (-0.5,-1)
affichage (0.5,-1)

File: chap3_syntaxe.tex, line 1016


cartésien (1.000000,1.000000) --> polaire (1.414214,45.000000 degrés)
cartésien (0.500000,1.000000) --> polaire (1.118034,63.434949 degrés)
cartésien (-0.500000,1.000000) --> polaire (1.118034,116.565051 degrés)
cartésien (-0.500000,-1.000000) --> polaire (1.118034,-116.565051 degrés)
cartésien (0.500000,-1.000000) --> polaire (1.118034,-63.434949 degrés)

File: chap3_syntaxe.tex, line 1033



def fonction_nom (param_1, param_2 = valeur_2, ..., param_n = valeur_n):
    ...

File: chap3_syntaxe.tex, line 1046


def commander_carte_orange (nom, prenom, paiement = "carte", nombre = 1, zone = 2):
    print "nom : ", nom
    print "prénom : ", prenom
    print "paiement : ", paiement
    print "nombre : ", nombre
    print "zone :", zone
    
commander_carte_orange ("Dupré", "Xavier", "chèque")  
        # les autres paramètres nombre et zone auront pour valeur
        # leurs valeurs par défaut

File: chap3_syntaxe.tex, line 1063


def commander_carte_orange (nom, prenom, paiement = "carte", nombre = 1, zone):
    print "nom : ", nom
    # ...

File: chap3_syntaxe.tex, line 1069


  File "problem_zone.py", line 1
    def commander_carte_orange (nom, prenom, paiement = "carte", nombre = 1, zone):
SyntaxError: non-default argument follows default argument

File: chap3_syntaxe.tex, line 1082


def fonction (l = [0,0]) :
    l [0] += 1
    return l
    
print fonction ()         # affiche [1,0] : résultat attendu
print fonction ()         # affiche [2,0] : résultat surprenant
print fonction ( [0,0])   # affiche [1,0] : résultat attendu

File: chap3_syntaxe.tex, line 1096


import copy
def fonction (l = [0,0]) :
    l = copy.copy (l)
    l [0] += 1
    return l

File: chap3_syntaxe.tex, line 1114



x_1, ..., x_n = fonction_nom (param_1 = valeur_1, ..., param_n = valeur_n)

File: chap3_syntaxe.tex, line 1125


def identite (nom, prenom):
    print "nom : ", nom, " prénom : ", prenom

identite("Xavier", "Dupré")                 # nom :  Xavier prénom :  Dupré
identite(prenom = "Xavier", nom = "Dupré")  # nom :  Dupré  prénom :  Xavier

File: chap3_syntaxe.tex, line 1137


def commander_carte_orange (paiement = "carte", nombre = 1, zone = 2):
    print "paiement : ", paiement
    print "nombre : ", nombre
    print "zone :", zone
    
commander_carte_orange (zone = 5)  # seule la valeur par défaut 
                                   # du paramètre zone sera changée

File: chap3_syntaxe.tex, line 1157


def fonction (a,b):
    return a + b
    
def fonction (a,b,c):
    return a + b + c

print fonction (5,6)
print fonction (5,6,7)

File: chap3_syntaxe.tex, line 1172


Traceback (most recent call last):
  File "cours4.py", line 7, in ?
    print fonction (5,6)
TypeError: fonction() takes exactly 3 arguments (2 given)

File: chap3_syntaxe.tex, line 1191


>>> help (round)

File: chap3_syntaxe.tex, line 1197


Help on built-in function round:

round(...)
    round(number[, ndigits]) -> floating point number
    
    Round a number to a given precision in decimal digits (default 0 digits).
    This always returns a floating point number.  Precision may be negative.

File: chap3_syntaxe.tex, line 1211


>>> help (coordonnees_polaires)

File: chap3_syntaxe.tex, line 1216


Help on function coordonnees_polaires in module __main__:

coordonnees_polaires(x, y)

File: chap3_syntaxe.tex, line 1226


import math
def coordonnees_polaires (x,y):
    """convertit des coordonnées cartésiennes en coordonnées polaires
    (x,y) --> (pho,theta)"""
    rho     = math.sqrt(x*x+y*y)
    theta   = math.atan2 (y,x)
    return rho, theta
help (coordonnees_polaires)

File: chap3_syntaxe.tex, line 1241


Help on function coordonnees_polaires in module __main__:

coordonnees_polaires(x, y)
    convertit des coordonnées cartésiennes en coordonnées polaires
    (x,y) --> (pho,theta)

File: chap3_syntaxe.tex, line 1268


def somme_n_premier_terme(n,liste):
    """calcul la somme des n premiers termes d'une liste"""
    somme = 0
    for i in liste:
        somme += i
        n -= 1             # modification de n (type immuable)
        if n <= 0: break
    liste[0] = 0           # modification de liste (type modifiable)
    return somme

l = [1,2,3,4]
nb = 3
print "avant la fonction ",nb,l   # affiche   avant la fonction  3 [1, 2, 3, 4]
s = somme_n_premier_terme (nb,l)  
print "après la fonction ",nb,l   # affiche   après la fonction  3 [0, 2, 3, 4]
print "somme : ", s               # affiche   somme :  6

File: chap3_syntaxe.tex, line 1295


def fonction (liste):
    liste = []

liste = [0,1,2]
print liste       # affiche [0,1,2]
fonction (liste)
print liste       # affiche [0,1,2]

File: chap3_syntaxe.tex, line 1312


def fonction (liste):
    del liste

liste = [0,1,2]
print liste       # affiche [0,1,2]
fonction (liste)
print liste       # affiche [0,1,2]

File: chap3_syntaxe.tex, line 1326


def fonction (liste):
    del liste[0:len(liste)]  # on peut aussi écrire : liste[:] = []

liste = [0,1,2]
print liste       # affiche [0,1,2]
fonction (liste)
print liste       # affiche []

File: chap3_syntaxe.tex, line 1350


def factorielle(n):
    if n == 0 : return 1
    else : return n * factorielle(n-1)

File: chap3_syntaxe.tex, line 1360


Traceback (most recent call last):
  File "fact.py", line 5, in <module>
    factorielle(999)
  File "fact.py", line 3, in factorielle
    else : return n * factorielle(n-1)
  File "fact.py", line 3, in factorielle
    else : return n * factorielle(n-1)
  ...

File: chap3_syntaxe.tex, line 1375


def factorielle_non_recursive (n) :
    r = 1
    for i in range (2, n+1) :
        r *= i
    return r

File: chap3_syntaxe.tex, line 1393


print x   # déclenche une erreur

File: chap3_syntaxe.tex, line 1398


Traceback (most recent call last):
  File "pas_declaree.py", line 1, in <module>
    print x
NameError: name 'x' is not defined

File: chap3_syntaxe.tex, line 1409


def portee_variable(x):
    var = x
    print var
    
portee_variable(3)
print var           # déclenche une erreur car var est déclarée dans
                    # la fonction portee_variable

File: chap3_syntaxe.tex, line 1444


n = 1                   # déclaration d'une variable globale
def locale_globale():
    n = 2               # déclaration d'une variable locale
    print n             # affiche le contenu de la variable locale

print n                 # affiche 1
locale_globale()        # affiche 2
print n                 # affiche 1

File: chap3_syntaxe.tex, line 1460


n = 1                   # déclaration d'une variable globale
def locale_globale():
    global n            # cette ligne indique que n désigne la variable globale
    n = 2               # change le contenu de la variable globale
    print n             # affiche le contenu de la variable globale

print n                 # affiche 1
locale_globale()        # affiche 2
print n                 # affiche 2

File: chap3_syntaxe.tex, line 1488


print type(factorielle)  # affiche <type 'function'>

File: chap3_syntaxe.tex, line 1496


def affiche_pair():
    def fonction_locale(i):            # fonction locale ou imbriquée
        if i % 2 == 0 : return True
        else : return False
    for i in range(0,10):
        if fonction_locale(i):
            print i
    
affiche_pair()
fonction_locale(5)      # l'appel à cette fonction locale 
                        # déclenche une erreur d'exécution

File: chap3_syntaxe.tex, line 1525



def fonction (param_1, ..., param_n, *liste, **dictionnaire) : 

File: chap3_syntaxe.tex, line 1536



fonction (valeur_1, ..., valeur_n, \
          liste_valeur_1, ..., liste_valeur_p, \
          nom_1 = v_1, ..., nom_q = v_q)

File: chap3_syntaxe.tex, line 1550


def fonction(p,*l,**d):
    print "p = ",p
    print "liste (tuple) l :", l 
    print "dictionnaire d :", d
    
fonction (1,2,3,a=5,b=6) # 1 est associé au paramètre p
                         # 2 et 3 sont insérés dans la liste l
                         # a=5 et b=6 sont insérés dans le dictionnaire d

File: chap3_syntaxe.tex, line 1566


p =  1
liste l : (2, 3)
dictionnaire d : {'a': 5, 'b': 6}

File: chap3_syntaxe.tex, line 1578


def fonction(p,*l,**d):
    print "p = ",p
    print "liste l :", l 
    print "dictionnaire d :", d
    
def fonction2 (p, *l, **d) :
    l += (4,)              # on ajoute une valeur au tuple
    d ["c"] = 5            # on ajoute un couple (paramètre,valeur)
    fonction (p, *l, **d)  # ne pas oublier le symbole *
    
fonction2 (1,2,3,a=5,b=6)

File: chap3_syntaxe.tex, line 1596


p =  1
liste l : (2, 3, 4)
dictionnaire d : {'a': 5, 'c': 5, 'b': 6}

File: chap3_syntaxe.tex, line 1610



nom_fonction = lambda param_1, ..., param_n : expression

File: chap3_syntaxe.tex, line 1621


min = lambda x,y : (abs (x+y) - abs (x-y))/2

print min (1,2)      # affiche 1
print min (5,4)      # affiche 4

File: chap3_syntaxe.tex, line 1632


def min(x,y):
    return (abs (x+y) - abs (x-y))/2

print min (1,2)      # affiche 1
print min (5,4)      # affiche 4

File: chap3_syntaxe.tex, line 1644


fs = []
for a in range (0,10) :
    f = lambda x : x + a
    fs.append (f)
for f in fs :
    print (f(1))   # le programme affiche 10 fois 10 de suite
                   # car la variable a vaut dix à la fin de la boucle

File: chap3_syntaxe.tex, line 1657


fs = []
for a in range (0,10) :
    f = lambda x,y=a : x + y   # ligne changée
    fs.append (f)
for f in fs :
    print (f(1))

File: chap3_syntaxe.tex, line 1677


def fonction_yield(n):
    i = 0
    while i < n-1:
        print "yield 1" # affichage : pour voir ce que fait le programme
        yield i         # arrête la fonction qui reprendra
        i = i+1         # à la ligne suivante lors du prochain appel
    print "yield 2"     # affichage : pour voir ce que fait le programme
    yield i             # arrête la fonction qui ne reprendra pas
                        # lors du prochain appel car le code de la fonction
                        # prend fin ici
                        
for a in fonction_yield(2):
    print a                 # affiche tous les éléments que retourne la 
                            # fonction fonction_yield, elle simule la liste
                            # [0,1]
print "-----------------------------------------------"                            
for a in fonction_yield(3):
    print a                 # nouvel appel, l'exécution reprend 
                            # au début de la fonction,
                            # affiche tous les éléments que retourne la 
                            # fonction fonction_yield, elle simule la liste
                            # [0,1,2]

File: chap3_syntaxe.tex, line 1706


yield 1
0
yield 2
1
-----------------------------------------------
yield 1
0
yield 1
1
yield 2
2

File: chap3_syntaxe.tex, line 1733


x = 5
def y () :
    return None
print callable (x)  # affiche False car x est une variable
print callable (y)  # affiche True car y est une fonction

File: chap3_syntaxe.tex, line 1754


x = 3
y = 4
print eval ("x*x+y*y+2*x*y")  # affiche 49
print (x+y)**2                # affiche 49

File: chap3_syntaxe.tex, line 1763


x = 3
y = 4
print eval ("x*x+y*y+2*x*y+z")

File: chap3_syntaxe.tex, line 1771


Traceback (most recent call last):
  File "c:\temp\cours.py", line 3, in -toplevel-
    print eval ("x*x+y*y+2*x*y+z")
  File "<string>", line 0, in -toplevel-
NameError: name 'z' is not defined

File: chap3_syntaxe.tex, line 1790


import math
str = """def coordonnees_polaires (x,y):
    rho     = math.sqrt(x*x+y*y)
    theta   = math.atan2 (y,x)
    return rho, theta"""       # fonction définie par une chaîne de caractères

obj = compile(str,"","exec")   # fonction compilée
exec obj                       # fonction incorporée au programme
print coordonnees_polaires(1,1)# affiche (1.4142135623730951, 0.78539816339744828)

File: chap3_syntaxe.tex, line 1806


import math
str = """math.sqrt(x*x+y*y)"""  # expression définie par une chaîne de caractères

obj = compile(str,"","eval")    # expression compilée
x = 1
y = 2
print eval (obj)                # résultat de l'expression

File: chap3_syntaxe.tex, line 1826


sys:1: DeprecationWarning: Non-ASCII character '\xe9' 
SyntaxError: Non-ASCII character '\xe9' in file i.py on line 1, 
             but no encoding declared; 
             see http://www.python.org/peps/pep-0263.html for details

File: chap3_syntaxe.tex, line 1837


# coding: cp1252

File: chap3_syntaxe.tex, line 1841


# coding: latin-1

File: chap3_syntaxe.tex, line 1872


l = [0,3,4,4,5,6]
print [ est_pair (i) for i in l ]  # affiche [0, 1, 0, 0, 1, 0]
print map (est_pair, l)            # affiche [0, 1, 0, 0, 1, 0]

File: chap3_syntaxe.tex, line 1880


def addition (x,y) : return x + y
l = [0,3,4,4,5,6]
m = [1,3,4,5,6,8]
print [ addition (l [i], m [i]) for i in range (0, len (l)) ]
print map (addition, l, m)   # affiche [1, 6, 8, 9, 11, 14]

File: chap3_syntaxe.tex, line 1890


print map (None, l,m)  # affiche [(0, 1), (3, 3), (4, 4), (4, 5), (5, 6), (6, 8)]
print zip (l,m)        # affiche [(0, 1), (3, 3), (4, 4), (4, 5), (5, 6), (6, 8)]

File: chap3_syntaxe.tex, line 1903


l   = [ 4, 5, 3, -6, 7, 9]
l.sort ()
for n in l : 
    print n

File: chap3_syntaxe.tex, line 1912


l   = [ 4, 5, 3, -6, 7, 9]

for n in sorted (l) :
    print n    

File: chap3_syntaxe.tex, line 1927


l   = [ 4, 5, 3, -6, 7, 9]
for i in xrange (0, len (l)) :
    print i, l [i]

File: chap3_syntaxe.tex, line 1935


l   = [ 4, 5, 3, -6, 7, 9]
for i,v in enumerate (l) :
    print i, v

File: chap3_syntaxe.tex, line 1997


def recherche (li, c) :
    for i,v in enumerate (li) :
        if v == c : return i
    return -1
li = [ 45, 32, 43, 56 ]
print recherche (li, 43)    # affiche 2

File: chap3_syntaxe.tex, line 2008


print li.index (43)

File: chap3_syntaxe.tex, line 2014


def recherche (li, c,d) :
    for i,v in enumerate (li) :
        if v in [c,d] : return i
    return -1
li = [ 45, 32, 43, 56 ]
print recherche (li, 43, 32)    # affiche 1

File: chap3_syntaxe.tex, line 2030


li = [ 0, 434, 43, 6436, 5 ]
m  = li [0]             # initialisation
for l in li :           # boucle
    if m < l : m = l    # m est le maximum

File: chap3_syntaxe.tex, line 2044


li = [ 0, 434, 43, 6436, 5 ]
m  = 0
for i in xrange (0, len (li)) : 
    if li [m] < li [i] : m = i

File: chap3_syntaxe.tex, line 2057


k = [ (v,i) for i,v in enumerate (li) ]
m = max (k) [1]

File: chap3_syntaxe.tex, line 2065


li = [ (0,0), (434,0), (43,1), (6436,1), (5,0) ]
m  = -1 # -1 car le premier élément peut ne pas faire partie du sous-ensemble
for i in range (0, len (li)) : 
    if li [i][1] == 0 and (m == -1 or li [m][0] < li [i][0]) : m = i

recherche dichotomique

def recherche_dichotomique (li, c) :
    a,b = 0, len (li)-1
    while a <= b :
        m = (a+b)//2
        if   c == li [m] : return m
        elif c <  li [m] : b = m-1   # partie supérieure éliminée
        else             : a = m+1   # partie inférieure éliminée
    return -1  # élément non trouvé
    
li = range (0,100,2)
print (recherche_dichotomique (li, 48))  # affiche 24
print (recherche_dichotomique (li, 49))  # affiche -1

File: chap3_syntaxe.tex, line 2089


s       = "case11;case12;case13|case21;case22;case23"
# décomposition en matrice
ligne   = s.split ("|")                     # lignes
mat     = [ l.split (";") for l in ligne ]  # colonnes

File: chap3_syntaxe.tex, line 2096


ligne   = [ ";".join (l) for l in mat ]     # colonnes
s       = "|".join (ligne)                  # lignes

File: chap3_syntaxe.tex, line 2106


li = [ 0, 434, 43, 6456 ]
s  = 0                       # initialisation
for l in li :                # boucle
    s += l                   # addition

File: chap3_syntaxe.tex, line 2115


def fonction (x) : return x*x
s  = 0
for l in li : s += fonction (l)

File: chap3_syntaxe.tex, line 2128


s = sum ( [fonction (l) for l in li] )

s = sum ( map (fonction, li) )

File: chap3_syntaxe.tex, line 2146


for i in xrange (0, len (li)) :
    # recherche du minimum entre i et len (li) exclu
    pos = i
    for j in xrange (i+1, len (li)) :
        if li [j] < li [pos] : pos = j
    # échange
    ech      = li [pos]
    li [pos] = li [i]
    li [i]   = ech

tri avec positions initiales

tab = ["zéro", "un", "deux"]                        # tableau à trier
pos = [ (tab [i],i) for i in range (0, len (tab)) ] # tableau de couples
pos.sort ()                                         # tri    
print pos                # affiche [('deux', 2), ('un', 1), ('zéro', 0)]

File: chap3_syntaxe.tex, line 2173


ordre = range (0, len (pos))
for i in xrange (0, len (pos)) : ordre [pos [i][1]] = i

File: chap3_syntaxe.tex, line 2185


li = ["un", "deux", "un", "trois"]
d  = { }
for l in li :
    if l not in d : d [l] = 1
    else : d [l] += 1
print d   # affiche {'un': 2, 'trois': 1, 'deux': 1}

File: chap3_syntaxe.tex, line 2198


mat = [ [1,1,1], [2,2,2], [1,1,1]]
d  = { }
for l in mat :
    k = str (l)    # k = tuple (l) lorsque cela est possible
    if k not in d : d [k] = 1
    else : d [k] += 1
print d   # affiche {'[1, 1, 1]': 2, '[2, 2, 2]': 1}

File: chap3_syntaxe.tex, line 2212


li = ["un", "deux", "un", "trois"]
d  = { }
for i,v in enumerate (li) :
    if v not in d : d [v] = [ i ]
    else : d [v].append (i)
print d   # affiche {'un': [0, 2], 'trois': [3], 'deux': [1]}

File: chap3_syntaxe.tex, line 2228


mat = [[0,1,2],[3,4,5]]
lin = [ i * len (mat [i]) + j \
            for i in range (0, len (mat)) \
            for j in range (0, len (mat [i])) ]

File: chap3_syntaxe.tex, line 2237


nc = len (mat [0])
mat = [ [ lin [i * nc + j] for j in range (0, len (mat [i])) ] \
                           for i in range (0, len (mat)) ]

File: chap3_syntaxe.tex, line 2250


def fonction_carre(x) :  return x*x
def fonction_cube (x) :  return x*x*x

def calcul_n_valeur (l,f):
    res = [ f(i) for i in l ]
    return res

l = [0,1,2,3]
print l   # affiche [0, 1, 2, 3]

l1 = calcul_n_valeur (l, fonction_carre)
print l1  # affiche [0, 1, 4, 9]

l2 = calcul_n_valeur (l, fonction_cube)
print l2  # affiche [0, 1, 8, 27]

File: chap4_classe.tex, line 38


class nom_classe :
    # corps de la classe
    # ...

File: chap4_classe.tex, line 58



cl = nom_classe ()

File: chap4_classe.tex, line 79


class classe_vide:
    pass

File: chap4_classe.tex, line 88


class classe_vide:
    pass
cl = classe_vide ()

File: chap4_classe.tex, line 99


print type (cl)   # affiche <type 'instance'>

File: chap4_classe.tex, line 107


isinstance (cl,classe_vide)   # affiche True

File: chap4_classe.tex, line 126



class nom_classe :
    def nom_methode (self, param_1, ..., param_n) :
        # corps de la méthode...

File: chap4_classe.tex, line 140



cl = nom_classe ()    # variable de type nom_classe
t  = cl.nom_methode (valeur_1, ..., valeur_n)

File: chap4_classe.tex, line 152


rnd = 42

class exemple_classe:
    def methode1(self,n):
        """simule la génération d'un nombre aléatoire 
           compris entre 0 et n-1 inclus"""
        global rnd
        rnd = 397204094 * rnd % 2147483647
        return int (rnd % n)

nb  = exemple_classe ()
l   = [ nb.methode1(100) for i in range(0,10) ]
print l   # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]

nb2 = exemple_classe ()
l2  = [ nb2.methode1(100) for i in range(0,10) ]
print l2   # affiche [46, 42, 89, 66, 48, 12, 61, 84, 71, 41]

File: chap4_classe.tex, line 195



class nom_classe :
    def nom_methode (self, param_1, ..., param_n) :
        self.nom_attribut = valeur

File: chap4_classe.tex, line 209


class exemple_classe:
    def methode1(self,n):
        """simule la génération d'un nombre aléatoire 
           compris entre 0 et n-1 inclus"""
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)

nb = exemple_classe ()
l  = [ nb.methode1(100) for i in range(0,10) ]
print l

File: chap4_classe.tex, line 226


Traceback (most recent call last):
  File "cours.py", line 8, in -toplevel-
    l = [ nb.methode1(100) for i in range(0,10) ]
  File "cours.py", line 4, in methode1
    self.rnd = 397204094 * self.rnd % 2147483647
AttributeError: exemple_classe instance has no attribute 'rnd'

File: chap4_classe.tex, line 240


class exemple_classe:
    def methode1(self,n):
        """simule la génération d'un nombre aléatoire 
           compris entre 0 et n-1 inclus"""
        self.rnd = 42  # déclaration à l'intérieur de la méthode, 
                       # doit être précédé du mot-clé self
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)

nb = exemple_classe ()
l  = [ nb.methode1(100) for i in range(0,10) ]
print l  # affiche [19, 19, 19, 19, 19, 19, 19, 19, 19, 19]

File: chap4_classe.tex, line 259


class exemple_classe:
    def methode1(self,n):
        """simule la génération d'un nombre aléatoire 
           compris entre 0 et n-1 inclus"""
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)

nb     = exemple_classe ()
nb.rnd = 42              # déclaration à l'extérieur de la classe, 
                         # indispensable pour utiliser la méthode methode1
l = [ nb.methode1(100) for i in range(0,10) ]
print l  # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]

File: chap4_classe.tex, line 283



class nom_classe :
    def __init__(self, param_1, ..., param_n):
        # code du constructeur

File: chap4_classe.tex, line 296



x = nom_classe (valeur_1,...,valeur_n)

File: chap4_classe.tex, line 307


class classe1:
    def __init__(self):
        # pas de paramètre supplémentaire
        print "constructeur de la classe classe1"
        self.n = 1 # ajout de l'attribut n

x = classe1 ()     # affiche constructeur de la classe classe1
print x.n          # affiche 1
        
class classe2:
    def __init__(self,a,b):
        # deux paramètres supplémentaires
        print "constructeur de la classe classe2"
        self.n = (a+b)/2  # ajout de l'attribut n

x = classe2 (5,9)  # affiche constructeur de la classe classe2
print x.n          # affiche 7

File: chap4_classe.tex, line 335


class exemple_classe:
    def __init__ (self) : # constructeur
        self.rnd = 42     # on crée l'attribut rnd, identique pour chaque instance
                          # --> les suites générées auront toutes le même début
    def methode1(self,n):
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)

nb  = exemple_classe ()
l   = [ nb.methode1(100) for i in range(0,10) ]
print l   # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]

nb2 = exemple_classe ()
l2  = [ nb2.methode1(100) for i in range(0,10) ]
print l2   # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]

File: chap4_classe.tex, line 366


class exemple_classe:
    def __init__ (self) :
        self.rnd = 42
    def methode1(self,n):
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)

nb = exemple_classe ()
print nb.__dict__        # affiche {'rnd': 42}

File: chap4_classe.tex, line 382


class exemple_classe:
    def methode1(self,n):
        if "rnd" not in self.__dict__ :  # l'attribut existe-t-il ? 
            self.rnd = 42                # création de l'attribut
            self.__dict__ ["rnd"] = 42   # autre écriture possible
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)

nb = exemple_classe ()
l  = [ nb.methode1(100) for i in range(0,10) ]
print l  # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8]

File: chap4_classe.tex, line 455


class classe_vide:
    pass
cl = classe_vide ()
print cl.__module__             # affiche __main__
print cl.__class__              # affiche __main__.classe_vide ()
print cl.__dict__               # affiche {}
print cl.__doc__                # affiche None  (voir paragraphe suivant)
print cl.__class__.__doc__      # affiche None  
print cl.__class__.__dict__     # affiche {'__module__': '__main__', 
                                #          '__doc__': None}
print cl.__class__.__name__     # affiche classe_vide
print cl.__class__.__bases__    # affiche ()

File: chap4_classe.tex, line 486


class exemple_classe:
    """simule une suite de nombres aléatoires"""
    def __init__ (self) :
        """constructeur : initialisation de la première valeur"""
        self.rnd = 42
    def methode1(self,n):
        """simule la génération d'un nombre aléatoire 
        compris entre 0 et n-1 inclus"""
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)
nb = exemple_classe ()
help (exemple_classe)     # appelle l'aide associée à la classe

File: chap4_classe.tex, line 502


class exemple_classe
 |  simule une suite de nombres aléatoires
 |  
 |  Methods defined here:
 |  
 |  __init__(self)
 |      constructeur : initialisation de la première valeur
 |  
 |  methode1(self, n)
 |      simule la génération d'un nombre aléatoire 
 |      compris entre 0 et n-1 inclus

File: chap4_classe.tex, line 520


print exemple_classe.__doc__  # affiche simule une suite de nombres aléatoires
print nb.__doc__              # affiche simule une suite de nombres aléatoires
print nb.__class__.__doc__    # affiche simule une suite de nombres aléatoires

File: chap4_classe.tex, line 533


class essai_class:
    def meth(self):
        x      = 6
        self.y = 7

a = essai_class()
print dir (a)             # affiche ['__doc__', '__module__', 'meth']
a.meth ()
print dir (a)             # affiche ['__doc__', '__module__', 'meth', 'y']
print dir (essai_class)   # affiche ['__doc__', '__module__', 'meth']

File: chap4_classe.tex, line 559


class ensemble_element :
    
    class element :
        def __init__ (self) :
            self.x, self.y, self.z = 0,0,0
    
    def __init__ (self) :
        self.all = [ ensemble_element.element () for i in xrange (0,3) ]
                     
    def barycentre (self) :
        b = ensemble_element.element ()
        for el in self.all :
            b.x += el.x
            b.y += el.y
            b.z += el.z
        b.x /= len (self.all)
        b.y /= len (self.all)
        b.z /= len (self.all)
        return b
    
f = ensemble_element ()
f.all [0].x, f.all [0].y, f.all [0].z = 4.5,1.5,1.5
b = f.barycentre ()
print b.x,b.y,b.z # affiche 1.5 0.5 0.5

File: chap4_classe.tex, line 598


class nouvelle_classe:
    pass
x = nouvelle_classe () + nouvelle_classe ()

File: chap4_classe.tex, line 613


class nombre_complexe:
    def __init__ (self, a = 0, b= 0) : self.a, self.b = a,b
    def get_module (self) :  return math.sqrt (self.a * self.a + self.b * self.b)

    def ajoute (self,c):
        return nombre_complexe (self.a + c.a, self.b + c.b)
    
c1 = nombre_complexe (0,1)    
c2 = nombre_complexe (1,0)    
c  = c1.ajoute (c2)         # c = c1 + c2
print c.a, c.b

File: chap4_classe.tex, line 633



class nom_class :
    def __add__ (self, autre) :
        # corps de l'opérateur
        return ...   # nom_classe

File: chap4_classe.tex, line 647


class nombre_complexe:
    def __init__ (self, a = 0, b= 0) : self.a, self.b = a,b
    def get_module (self) : return math.sqrt (self.a * self.a + self.b * self.b)
        
    def __add__(self, c):
        return nombre_complexe (self.a + c.a, self.b + c.b)
    
c1 = nombre_complexe (0,1)    
c2 = nombre_complexe (1,0)    
c  = c1 + c2          # cette expression est maintenant syntaxiquement correcte
c  = c1.__add__ (c2)  # même ligne que la précédente mais écrite explicitement
print c.a, c.b

File: chap4_classe.tex, line 667



class nom_class :
    def __iadd__ (self, autre) :
        # corps de l'opérateur
        return self

File: chap4_classe.tex, line 682


class nombre_complexe:
    def __init__ (self, a = 0, b= 0) : self.a, self.b = a,b
    def get_module (self) : return math.sqrt (self.a * self.a + self.b * self.b)
    def __add__(self, c)  : return nombre_complexe (self.a + c.a, self.b + c.b)
    
    def __iadd__(self, c) :
        self.a += c.a
        self.b += c.b
        return self
        
c1  = nombre_complexe (0,1)    
c2  = nombre_complexe (1,0)    
c1 += c2           # utilisation de l'opérateur +=
c1.__iadd__ (c2)   # c'est la transcription explicite de la ligne précédente
print c1.a, c1.b

File: chap4_classe.tex, line 706



class nom_class :
    def __str__ (self) :
        # corps de l'opérateur
        return...

File: chap4_classe.tex, line 721


class nombre_complexe:
    def __init__ (self, a = 0, b= 0) : self.a, self.b = a,b
    def __add__(self, c) : return nombre_complexe (self.a + c.a, self.b + c.b)
    
    def __str__ (self) :
        if   self.b == 0 : return "%f" % (self.a)
        elif self.b >  0 : return "%f + %f i" % (self.a, self.b) 
        else             : return "%f - %f i" % (self.a, -self.b) 

c1 = nombre_complexe (0,1)    
c2 = nombre_complexe (1,0)    
c3 = c1 + c2
print c3       # affiche 1.000000 + 1.000000 i

File: chap4_classe.tex, line 745


class point_espace:
    def __init__ (self, x,y,z): self._x, self._y, self._z = x,y,z

    def __getitem__(self,i):
        if i == 0 : return self._x
        if i == 1 : return self._y
        if i == 2 : return self._z
        # pour tous les autres cas --> erreur
        raise IndexError ("indice impossible, 0,1,2 autorisés")

    def __setitem__(self,i,x):
        if   i == 0 : self._x = x
        elif i == 1 : self._y = y
        elif i == 2 : self._z = z
        # pour tous les autres cas --> erreur
        raise IndexError ("indice impossible, 0,1,2 autorisés")
        
    def __str__(self):
        return "(%f,%f,%f)" % (self._x, self._y, self._z)
        
a = point_espace (1,-2,3)

print a                      # affiche (1.000000,-2.000000,3.000000)
a [1] = -3                   # (__setitem__) affecte -3 à a.y
print "abscisse : ", a [0]   # (__getitem__) affiche abscisse :  1  
print "ordonnée : ", a [1]   # (__getitem__) affiche ordonnée :  -3
print "altitude : ", a [2]   # (__getitem__) affiche altitude :  3

File: chap4_classe.tex, line 779


Traceback (most recent call last):
  File "point_espace.py", line 31, in ?
    print a [4]
  File "point_espace.py", line 13, in __getitem__
    raise IndexError, "indice impossible, 0,1,2 autorisés"
IndexError: indice impossible, 0,1,2 autorisés

File: chap4_classe.tex, line 923


a = point_espace (1,-2,3)
for x in a:   
    print x      # affiche successivement 1,-2,3

File: chap4_classe.tex, line 933


a = point_espace (1,-2,3)
it = iter (a)
while True:
    try : print it.next ()
    except StopIteration : break

File: chap4_classe.tex, line 944


class point_espace:
    def __init__ (self, x,y,z):
        self._x, self._y, self._z = x,y,z
    def __str__(self):
        return "(%f,%f,%f)" % (self._x, self._y, self._z)
    def __getitem__(self,i):
        if i == 0 : return self._x
        if i == 1 : return self._y
        if i == 2 : return self._z
        # pour tous les autres cas --> erreur
        raise IndexError ("indice impossible, 0,1,2 autorisés")
        
    class class_iter:
        """cette classe définit un itérateur pour point_espace"""
        def __init__ (self,ins):
            """initialisation, self._ins permet de savoir quelle 
               instance de point_espace on explore, 
               self._n mémorise l'indice de l'élément exploré"""
            self._n   = 0
            self._ins = ins
            
        def __iter__ (self) :   # le langage impose cette méthode 
           return self          # dans certaines configurations
           
        def next (self):
            """retourne l'élément d'indice self._n et passe à l'élément suivant"""
            if self._n <= 2:
                v = self._ins [self._n]
                self._n += 1
                return v
            else :
                # si cet élément n'existe pas, lève une exception
                raise StopIteration
    
    def __iter__(self):
        """opérateur de la classe point_espace, retourne un itérateur
           permettant de l'explorer"""
        return point_espace.class_iter (self)

a = point_espace (1,-2,3)
for x in a:   
    print x      # affiche successivement 1,-2,3

File: chap4_classe.tex, line 993


class point_espace:
    def __init__ (self, x,y,z):
        self._x, self._y, self._z = x,y,z
    def __str__(self):
        return "(%f,%f,%f)" % (self._x, self._y, self._z)
    def __getitem__(self,i):
        if i == 0 : return self._x
        if i == 1 : return self._y
        if i == 2 : return self._z
        # pour tous les autres cas --> erreur
        raise IndexError ("indice impossible, 0,1,2 autorisés")
        
    def __iter__(self):
        """itérateur avec yield (ou générateur)"""
        _n = 0
        while _n <= 2 : 
            yield self.__getitem__ (_n)
            _n += 1
            
a = point_espace (1,-2,3)
for x in a:   
    print x      # affiche successivement 1,-2,3

File: chap4_classe.tex, line 1040

			
class essai_class:
    def methode (self):
        print "méthode non statique"

x = essai_class ()
x.methode ()

File: chap4_classe.tex, line 1053



class nom_class :
    def nom_methode(params, ...) : 
        # corps de la méthode
        ...
    nom_methode = staticmethod (nom_methode)

File: chap4_classe.tex, line 1068


class essai_class:
    def methode ():
        print "méthode statique"
    methode = staticmethod(methode)

essai_class.methode ()

File: chap4_classe.tex, line 1080


def methode ():
    print "méthode statique"
    
class essai_class:
    pass

essai_class.methode = staticmethod(methode)
essai_class.methode ()

File: chap4_classe.tex, line 1094


class essai_class:
    print "création d'une instance de la classe essai_class"
    methode = staticmethod(methode)
cl = classe_vide () # affiche création d'une instance de la classe essai_class
ck = classe_vide () # n'affiche rien

File: chap4_classe.tex, line 1106


class Couleur :
    def __init__ (self, r, v, b) : self.r, self.v, self.b =  r, v, b
    def __str__ (self) : return str ( (self.r,self.v,self.b))
    def blanc () : return Couleur (255,255,255)
    def noir  () : return Couleur (0,0,0)
    blanc = staticmethod (blanc)
    noir  = staticmethod (noir)
    
c = Couleur.blanc ()
print c               # affiche (255, 255, 255)
c = Couleur.noir ()
print c               # affiche (0, 0, 0)

File: chap4_classe.tex, line 1135



class nom_class :
    attribut_statique = valeur
    def nom_methode (self,params, ...):
        nom_class.attribut_statique2 = valeur2 
    def nom_methode_st (params, ...) : 
        nom_class.attribut_statique3 = valeur3 
    nom_methode_st = staticmethod (nom_methode_st)

File: chap4_classe.tex, line 1153


class essai_class:
    x = 5
    def meth(self):
        print essai_class.x
        essai_class.x += 1

y = essai_class ()
z = essai_class ()
y.meth()    # affiche 5
z.meth()    # affiche 6

File: chap4_classe.tex, line 1172


class exemple_classe:
    rnd = 42
    def incremente_rnd (self):
        self.rnd += 1
        return self.rnd

cl = exemple_classe()

print cl.__dict__                    # affiche {}
print cl.__class__.__dict__ ["rnd"]  # affiche 42
cl.incremente_rnd ()
print cl.__dict__                    # affiche {'rnd': 43}
print cl.__class__.__dict__ ["rnd"]  # affiche 42

File: chap4_classe.tex, line 1202



def nom_methode (cls) :
    # code de la fonction}
    
class nom_classe :
    # code de la classe
    nom_methode = classmethod (nom_methode)        # syntaxe 1
    
nom_classe.nom_methode = classmethod (nom_methode) # syntaxe 2

File: chap4_classe.tex, line 1222


def meth3 (cls): print "ok meth3", cls.x
def meth4 (cls): print "ok meth4", cls.x
    
class essai_classe:
    x = 5
    def meth(self): print "ok meth", self.x
    def meth2(cls): print "ok meth2", cls.x

    meth3 = classmethod (meth3)

x = essai_classe ()
x.meth ()                                 # affiche ok meth 5
x.meth2 ()                                # affiche ok meth2 5
x.meth3 ()                                # affiche ok meth3 5

essai_classe.meth4 = classmethod (meth4)
x.meth4 ()                                # affiche ok meth4 5

File: chap4_classe.tex, line 1252



class nom_classe :
    # code de la classe
    nom_propriete = property (fget, fset, fdel, doc)

File: chap4_classe.tex, line 1268


import math

class nombre_complexe(object):           # voir remarque après l'exemple
    def __init__ (self, a = 0, b= 0):
        self.a = a
        self.b = b
        
    def __str__ (self) :
        if   self.b == 0 : return "%f" % (self.a)
        elif self.b >  0 : return "%f + %f i" % (self.a, self.b) 
        else             : return "%f - %f i" % (self.a, -self.b) 
        
    def get_module (self): 
        return math.sqrt (self.a * self.a + self.b * self.b)

    def set_module (self,m):
        r = self.get_module ()
        if r == 0:
            self.a = m
            self.b = 0
        else :
            d       = m / r
            self.a *= d
            self.b *= d
            
    def get_argument (self) : 
        r = self.get_module ()
        if r == 0 : return 0
        else      : return math.atan2 (self.b / r, self.a / r)
            
    def set_argument (self,arg) :
        m       = self.get_module ()
        self.a  = m * math.cos (arg)
        self.b  = m * math.sin (arg)
        
    def get_conjugue (self):
        return nombre_complexe (self.a,-self.b)
        
    module = property (fget = get_module,   fset = set_module,   doc = "module")
    arg    = property (fget = get_argument, fset = set_argument, doc = "argument")
    conj   = property (fget = get_conjugue,                      doc = "conjugué")
    
c = nombre_complexe (0.5,math.sqrt (3)/2)
print "c = ",         c          # affiche c =  0.500000 + 0.866025 i
print "module = ",    c.module   # affiche module =  1.0
print "argument = ",  c.arg      # affiche argument =  1.0471975512                    

c           = nombre_complexe ()
c.module    = 1
c.arg       = math.pi * 2 / 3
print "c = ",         c          # affiche c =  -0.500000 + 0.866025 i
print "module = ",    c.module   # affiche module =  1.0  
print "argument = ",  c.arg      # affiche argument =  2.09439510239
print "conjugué = ",  c.conj     # affiche conjugué =  -0.500000 - 0.866025 i

File: chap4_classe.tex, line 1329


Traceback (most recent call last):
  File "cour2.py", line 53, in ?
    c.conj = nombre_complexe (0,0)
AttributeError: can't set attribute

File: chap4_classe.tex, line 1356


class exemple_classe:
    def __init__ (self) : self.rnd = 42
    def methode1(self,n):
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)

nb  = exemple_classe ()
nb2 = nb
print nb.rnd        # affiche 42
print nb2.rnd       # affiche 42

nb2.rnd = 0

print nb2.rnd       # affiche 0, comme prévu
print nb.rnd        # affiche 0, si nb et nb2 étaient des objets différents, 
                    # cette ligne devrait afficher 42

File: chap4_classe.tex, line 1379



import copy
nom_copy = copy.copy (nom_instance)

File: chap4_classe.tex, line 1392


class exemple_classe:
    def __init__ (self) : self.rnd = 42
    def methode1(self,n):
        self.rnd = 397204094 * self.rnd % 2147483647
        return int (self.rnd % n)

nb = exemple_classe ()

import copy           # pour utiliser le module copy
nb2 = copy.copy (nb)  # copie explicite

print nb.rnd    # affiche 42
print nb2.rnd   # affiche 42

nb2.rnd = 0

print nb2.rnd   # affiche 0
print nb.rnd    # affiche 42

File: chap4_classe.tex, line 1420


m  = [ 0, 1 ]
m2 = m
del m2   # supprime l'identificateur mais pas la liste
print m  # affiche [0, 1]

référencement d'objets

class CreationDestruction (object) :
    
    def __init__ (self) :
        print "constructeur"
        
    def __new__ (self) :
        print "__new__"
        return object.__new__ (self)
        
    def __del__ (self) :
        print "__del__"

print "a"
m = CreationDestruction ()
print "b"
m2 = m
print "c"
del m
print "d"
del m2
print "e"

File: chap4_classe.tex, line 1436


a
__new__
constructeur
b
c
d
__del__
e

File: chap4_classe.tex, line 1457


class classe_incluse:
    def __init__ (self) : self.attr = 3

class exemple_classe:
    def __init__ (self) : 
        self.inclus = classe_incluse ()
        self.rnd    = 42

nb = exemple_classe ()

import copy            # pour utiliser le module copy
nb2 = copy.copy (nb)   # copie explicite

print nb.inclus.attr   # affiche 3
print nb2.inclus.attr  # affiche 3

nb2.inclus.attr = 0

print nb.inclus.attr   # affiche 0 (on voudrait 3 ici)
print nb2.inclus.attr  # affiche 0

File: chap4_classe.tex, line 1485



class nom_classe :
    def __copy__ () :
        copie = nom_classe (...)
        # ...
        return copie

File: chap4_classe.tex, line 1503


import copy

class classe_incluse:
    def __init__ (self) : self.attr = 3

class exemple_classe:
    def __init__ (self) : 
        self.inclus  = classe_incluse ()
        self.rnd     = 42
    def __copy__ (self):
        copie        = exemple_classe ()
        copie.rnd    = self.rnd
        copie.inclus = copy.copy (self.inclus)
        return copie

nb  = exemple_classe ()

nb2 = copy.copy (nb)   # copie explicite,
                       # utilise l'opérateur __copy__,
                       # cette ligne est équivalente à
                       # nb2 = nb.__copy__()

print nb.rnd           # affiche 42
print nb2.rnd          # affiche 42
print nb.inclus.attr   # affiche 3
print nb2.inclus.attr  # affiche 3

nb.inclus.attr = 0
nb.rnd         = 1

print nb.rnd           # affiche 1
print nb2.rnd          # affiche 42
print nb.inclus.attr   # affiche 0
print nb2.inclus.attr  # affiche 3 (c'est le résultat souhaité)

File: chap4_classe.tex, line 1546


def fonction_liste ():
    return range (4,7) # retourne la liste [4,5,6]
l = fonction_liste ()  # la liste [4,5,6] n'est pas recopiée,
                       # l'identificateur l lui est affecté

File: chap4_classe.tex, line 1558


def fonction_liste ():
    return range (4,7)
fonction_liste () # la liste [4,5,6] n'est pas recopiée,
                  # elle n'est pas non plus attribuée à une variable,
                  # elle est alors détruite automatiquement par le langage Python

File: chap4_classe.tex, line 1575


l  = [4,5,6]
l2 = l
print l       # affiche [4, 5, 6]
print l2      # affiche [4, 5, 6]
l2 [1] = 10
print l       # affiche [4, 10, 6]
print l2      # affiche [4, 10, 6]

File: chap4_classe.tex, line 1589


l  = [4,5,6]
import copy
l2 = copy.copy (l)
print l       # affiche [4, 5, 6]
print l2      # affiche [4, 5, 6]
l2 [1] = 10
print l       # affiche [4, 5, 6]
print l2      # affiche [4, 10, 6]

File: chap4_classe.tex, line 1604


import copy
l  = [ [i] for i in range(0,3)]
ll = copy.copy (l)
print l, "  -  ", ll    # affiche [[0], [1], [2]]   -   [[0], [1], [2]]
ll [0][0] = 6
print l, "  -  ", ll    # affiche [[6], [1], [2]]   -   [[6], [1], [2]]

File: chap4_classe.tex, line 1619


import copy
l  = [ [i] for i in range(0,3)]
ll = copy.deepcopy (l)
print l, "  -  ", ll    # affiche [[0], [1], [2]]   -   [[0], [1], [2]]
ll [0][0] = 6
print l, "  -  ", ll    # affiche [[0], [1], [2]]   -   [[6], [1], [2]]

File: chap4_classe.tex, line 1635



import copy
memo = { } 
nom_copy = copy.deepcopy (nom_instance [,memo])

File: chap4_classe.tex, line 1648



class nom_classe :
    def __deepcopy__ (self,memo) :
        copie = copy.copy (self)
        # ...
        return copie

File: chap4_classe.tex, line 1665


import copy

class classe_incluse:
    def __init__ (self) : self.attr = 3

class exemple_classe:
    def __init__ (self) :
        self.inclus = classe_incluse ()
        self.rnd    = 42
    def __copy__ (self):
        copie       = exemple_classe ()
        copie.rnd   = self.rnd
        return copie
    def __deepcopy__ (self,memo):
        if self in memo : return memo [self]
        copie        = copy.copy (self)
        memo [self]  = copie    # mémorise la copie de self qui est copie
        copie.inclus = copy.deepcopy (self.inclus,memo)
        return copie

nb = exemple_classe ()

nb2 = copy.deepcopy (nb)   # copie explicite à tous niveaux,
                           # utilise l'opérateur __copy__,
                           # cette ligne est équivalente à
                           # nb2 = nb.__deepcopy__()

print nb.rnd           # affiche 42
print nb2.rnd          # affiche 42
print nb.inclus.attr   # affiche 3
print nb2.inclus.attr  # affiche 3

nb.inclus.attr = 0
nb.rnd = 1

print nb.rnd           # affiche 1
print nb2.rnd          # affiche 42
print nb.inclus.attr   # affiche 0
print nb2.inclus.attr  # affiche 3  # résultat souhaité

File: chap4_classe.tex, line 1711


import copy

class Objet1 :
    def __init__ (self, i) : self.i = i
    def __str__ (self) : 
        return "o1 " + str (self.i) + " : " + str (self.o2.i)

class Objet2 :
    def __init__ (self, i, o) :
        self.i  = i
        self.o1 = o
        o.o2    = self
    def __str__ (self) : 
        return "o2 " + str (self.i) + " : " + str (self.o1.i)
        
    def __deepcopy__ (self,memo) : return Objet2 (self.i, self.o1)
        
o1 = Objet1 (1)
o2 = Objet2 (2, o1)
print o1  # affiche o1 1 : 2
print o2  # affiche o2 2 : 1

o3   = copy.deepcopy (o2)
o3.i = 4
print o1  # affiche o1 1 : 4    --> on voudrait 2
print o2  # affiche o2 2 : 1
print o3  # affiche o2 4 : 1      

File: chap4_classe.tex, line 1745


import copy

class Objet1 :
    def __init__ (self, i) : self.i = i
    def __str__ (self) : 
        return "o1 " + str (self.i) + " : " + str (self.o2.i)
    def __deepcopy__ (self,memo={}) :
        if self in memo : return memo [self]
        r           = Objet1 (self.i)
        memo [self] = r
        r.o2        = copy.deepcopy (self.o2, memo)
        return r

class Objet2 :
    def __init__ (self, i, o) :
        self.i  = i
        self.o1 = o
        o.o2    = self
    def __str__ (self) : 
        return "o2 " + str (self.i) + " : " + str (self.o1.i)
        
    def __deepcopy__ (self,memo = {}) :
        if self in memo : return memo [self]
        r           = Objet2 (self.i, self.o1)
        memo [self] = r
        r.o1        = copy.deepcopy (self.o1, memo)
        return r
        
o1 = Objet1 (1)
o2 = Objet2 (2, o1)

print o1  # affiche o1 1 : 2
print o2  # affiche o2 2 : 1

o3   = copy.deepcopy (o2)
o3.i = 4
print o1  # affiche o1 1 : 2    --> on a 2 cette fois-ci
print o2  # affiche o2 2 : 1
print o3  # affiche o2 4 : 1      

File: chap4_classe.tex, line 1796



class nom_classe (object) :
    __slots__ = "attribut_1", ..., "attribut_n"

File: chap4_classe.tex, line 1807


class point_espace(object):
    __slots__ = "_x", "_y", "_z"
    
    def __init__ (self, x,y,z): self._x, self._y, self._z = x,y,z
    def __str__(self): return "(%f,%f,%f)" % (self._x, self._y, self._z)
        
a = point_espace (1,-2,3)
print a

File: chap4_classe.tex, line 1822


Traceback (most recent call last):
  File "cours4.py", line 15, in ?
    a.j = 6
AttributeError: 'point_espace' object has no attribute 'j'

File: chap4_classe.tex, line 1849


import random  # extension interne incluant des fonctions
               # simulant des nombres aléatoires,
               # random.randint (a,b) --> retourne un nombre entier entre a et b
               # cette ligne doit être ajoutée à tous les exemples suivant
               # même si elle n'y figure plus

def cent_tirages () :
    s = 0
    for i in range (0,100) : s += random.randint (0,1)
    return s
    
print cent_tirages ()

File: chap4_classe.tex, line 1869


def cent_tirages () :
    s = 0
    for i in range (0,100) :
        t = random.randint (0,10)
        if t >= 3 : s += 1
    return s
    
print cent_tirages ()

File: chap4_classe.tex, line 1884


def piece_normale () :
    return random.randint (0,1)
    
def piece_truquee () :
    t = random.randint (0,10)
    if t >= 3 : return 1
    else : return 0
    
def cent_tirages (piece) :
    s = 0
    for i in range (0,100) : s += piece ()
    return s
    
print cent_tirages (piece_normale)
print cent_tirages (piece_truquee)

File: chap4_classe.tex, line 1915


class piece_normale :
    def tirage (self) :
        return random.randint (0,1)
        
    def cent_tirages (self) :
        s = 0
        for i in range (0,100) : s += self.tirage ()
        return s

p = piece_normale ()
print p.cent_tirages ()

File: chap4_classe.tex, line 1933


class piece_normale :
    def tirage (self) :
        return random.randint (0,1)
        
    def cent_tirages (self) :
        s = 0
        for i in range (0,100) : s += self.tirage ()
        return s

class piece_truquee :
    def tirage (self) :
        t = random.randint (0,10)
        if t >= 3 : return 1
        else : return 0
        
    def cent_tirages (self) :
        s = 0
        for i in range (0,100) : s += self.tirage ()
        return s
        
p  = piece_normale ()
print p.cent_tirages ()
p2 = piece_truquee ()
print p2.cent_tirages ()

File: chap4_classe.tex, line 1967


class piece_normale :
    def tirage (self) :
        return random.randint (0,1)
        
    def cent_tirages (self) :
        s = 0
        for i in range (0,100) : s += self.tirage ()
        return s

class piece_truquee (piece_normale) :
    def tirage (self) :
        t = random.randint (0,10)
        if t >= 3 : return 1
        else : return 0
        
p  = piece_normale ()
print p.cent_tirages ()
p2 = piece_truquee ()
print p2.cent_tirages ()

File: chap4_classe.tex, line 1994


class piece_normale :
    def tirage (self) :
        return random.randint (0,1)
        
    def cent_tirages (self) :
        s = 0
        for i in range (0,100) : s += self.tirage ()
        return s

class piece_truquee (piece_normale) :
    def tirage (self) :
        t = random.randint (0,10)
        if t >= 3 : return 1
        else : return 0
        
class piece_tres_truquee (piece_truquee) :
    def __init__(self) :
        # création de l'attribut avant
        self.avant = 0 
        
    def tirage (self) :
        if self.avant == 0 :
            # appel de la méthode tirage de la classe piece_truquee
            self.avant = piece_truquee.tirage (self)
        else :
            # appel de la méthode tirage de la classe piece_normale
            self.avant = piece_normale.tirage (self)
        return self.avant
        
p = piece_normale ()
print "normale ", p.cent_tirages ()
p2 = piece_truquee ()
print "truquee ", p2.cent_tirages ()
p3 = piece_tres_truquee ()
print "tres truquee ", p3.cent_tirages ()

File: chap4_classe.tex, line 2063



class nom_classe (nom_ancetre) :
    # corps de la classe
    # ...

File: chap4_classe.tex, line 2078


help (piece_tres_truquee)

File: chap4_classe.tex, line 2086


Help on class piece_tres_truquee in module __main__:

class piece_tres_truquee(piece_truquee)
 |  Method resolution order:
 |      piece_tres_truquee
 |      piece_truquee
 |      piece_normale
 |  
 |  Methods defined here:
 |  
 |  __init__(self)
 |  
 |  tirage(self)
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from piece_normale:
 |  
 |  cent_tirages(self)

File: chap4_classe.tex, line 2116


for l in piece_tres_truquee.__bases__ : 
    print l   # affiche __main__.piece_truquee
print piece_normale in piece_tres_truquee.__bases__  # affiche False
print piece_truquee in piece_tres_truquee.__bases__  # affiche True

File: chap4_classe.tex, line 2126


print issubclass (piece_tres_truquee, piece_normale)  # affiche True
print issubclass (piece_truquee, piece_normale)       # affiche True

File: chap4_classe.tex, line 2140



class nom_classe (nom_ancetre) :
    def nom_autre_methode (self, ...) :
        # ...
    def nom_methode (self, ...) :
        nom_ancetre.nom_methode (self, ...)
            # appel de la méthode définie chez l'ancêtre
        nom_ancetre.nom_autre_methode (self, ...)
            # appel d'une autre méthode définie chez l'ancêtre
        self.nom_autre_methode (...)
            # appel d'une méthode surchargée

File: chap4_classe.tex, line 2159


class A :
    def __init__ (self) :
        self.x = 0
class B (A) :
    def __init__ (self) :
        A.__init__ (self)
        self.y = 0

File: chap4_classe.tex, line 2175


class ancetre :
    def __init__(self) :
        self.a = 5
    def __str__ (self) :
        return "a = " + str (self.a)

class fille (ancetre) :
    def __init__(self) :
        ancetre.__init__(self)     # cette ligne est importante
                                   # car sans elle, l'attribut a n'existe pas
        self.a += 1
    def __str__ (self) :
        s = "a = " + str (self.a)
        return s

x = ancetre ()  
print x         # affiche a = 5
y = fille ()
print y         # affiche a = 6

File: chap4_classe.tex, line 2209


class rectangle :
    def __init__(self,a,b) :
        self.a,self.b = a,b
    def __str__ (self) :
        return "rectangle " + str (self.a) +  " x " +  str (self.b)
        
class carre (rectangle) :
    def __init__( self, a) :
        rectangle.__init__ (self, a,a)
        
r = rectangle (3,4)
print r  # affiche rectangle 3 x 4
c = carre (5)
print c  # affiche rectangle 5 x 5

File: chap4_classe.tex, line 2230


class carre :
    def __init__( self, a) :
        self.a = a
    def __str__ (self) :
        return "carre " + str (self.a) 
        
class rectangle (carre):
    def __init__(self,a,b) :
        carre.__init__(self, a)
        self.b = b
    def __str__ (self) :
        return "rectangle " + str (self.a) +  " x " +  str (self.b)
        
r = rectangle (3,4)
print r  # affiche rectangle 3 x 4
c = carre (5)
print c  # affiche carre 5

File: chap4_classe.tex, line 2275


class A :
    def __init__ (self) : self.a = 5
    def carre (self) : return self.a ** 2

class B :
    def __init__ (self) : self.a = 6
    def cube (self) : return self.a ** 3

class C (A,B) :
    def __init__ (self):
        A.__init__ (self)

x = C ()
print x.carre ()    # affiche 25
print x.cube ()     # affiche 125

File: chap4_classe.tex, line 2297


class A :
    def __init__ (self) : self.a = 5
    def calcul (self) : return self.a ** 2

class B :
    def __init__ (self) : self.a = 6
    def calcul (self) : return self.a ** 3

class C (A,B) :
    def __init__ (self):
        A.__init__ (self)

x = C ()
print x.calcul ()  # affiche 25

File: chap4_classe.tex, line 2317


class C(A, B)
 |  Method resolution order:
 |      C
 |      A
 |      B
 |  
 |  Methods defined here:
 |  
 |  __init__(self)
 |  
 |  calcul(self)

File: chap4_classe.tex, line 2335


class A :
    def __init__ (self) : self.a = 5
    def calcul (self) : return self.a ** 2

class B :
    def __init__ (self) : self.a = 6
    def calcul (self) : return self.a ** 3

class C (A,B) :
    def __init__ (self):
        A.__init__ (self)
        
    def calcul (self) :
        return B.calcul (self)

x = C ()
print x.calcul ()  # affiche 125

File: chap4_classe.tex, line 2359


class C (A,B) :
    def __init__ (self):
        A.__init__ (self)
        B.__init__ (self)

File: chap4_classe.tex, line 2374



issubclass (B,A)

File: chap4_classe.tex, line 2385


class A (object) : pass
class B (A)      : pass
class C (B)      : pass
    
print issubclass (A, B)     # affiche False
print issubclass (B, A)     # affiche True
print issubclass (A, C)     # affiche False
print issubclass (C, A)     # affiche True

File: chap4_classe.tex, line 2398


a = A ()
b = B ()
print issubclass (a.__class__, B)     # affiche False
print issubclass (b.__class__, A)     # affiche True
print issubclass (a.__class__, A)     # affiche True

File: chap4_classe.tex, line 2409


a = A ()
b = B ()
print isinstance (a, B)     # affiche False
print isinstance (b, A)     # affiche True
print isinstance (a, A)     # affiche True

fonction \codesindex{isinstance

def fonction_somme_list (ens) :
    r = "list "
    for e in ens : r += e
    return r

def fonction_somme_dict (ens) :
    r = "dict "
    for k,v in ens.items () : r += v
    return r

def fonction_somme (ens) :
    if   isinstance (ens, dict) : return fonction_somme_dict (ens)
    elif isinstance (ens, list) : return fonction_somme_list (ens)
    else                        : return "erreur"
        
li = ["un", "deux", "trois"]
di = {1:"un", 2:"deux", 3:"trois"}
tu = ("un", "deux", "trois")
print fonction_somme (li)  # affiche list undeuxtrois
print fonction_somme (di)  # affiche dict undeuxtrois
print fonction_somme (tu)  # affiche erreur

File: chap4_classe.tex, line 2434


s = """class carre :
    def __init__( self, a) : self.a = a
    def __str__ (self)     : return "carre " + str (self.a) 
        
class rectangle (carre):
    def __init__(self,a,b) :
        carre.__init__(self, a)
        self.b = b
    def __str__ (self) :
        return "rectangle " + str (self.a) +  " x " +  str (self.b)"""

obj = compile(s,"","exec")       # code à compiler
exec (obj)                       # classes incorporées au programme
       
r = rectangle (3,4)
print r  # affiche rectangle 3 x 4
c = carre (5)
print c  # affiche carre 5

File: chap4_classe.tex, line 2459


# coding: latin-1
"""erreur de compilation incluses dans le code inséré dans la
chaîne de caractère s"""
s = """class carre :
    def __init__( self, a) :
        seilf.a = a   # erreur de compilation
    def __str__ (self) :
        return "carre " + str (self.a) """
        
obj = compile(s,"variable s","exec")   # code à compiler
exec (obj)                             # classes incorporées au programme
       
c = carre (5)
print c  # affiche carre 5

File: chap4_classe.tex, line 2480


Traceback (most recent call last):
  File "C:\temp\cours.py", line 14, in -toplevel-
    c = carre (5)
  File "variable s", line 3, in __init__
NameError: global name 'seilf' is not defined

exemple de classe

# coding: latin-1
# la première ligne autorise les accents
class fromage :
    
    def __init__ (self, p,c,o) :
        self.poids = p
        self.couleur = c
        self.odeur = o
        
    def decouper (self,nb) :
        l = []
        for i in range (0,nb) :
            f = fromage (self.poids/nb, \
                            self.couleur, self.odeur)
            l.append (f)
        return l

    def __str__ (self) :
        s = "poids : " + str (self.poids)
        s += " couleur : " + str (self.couleur)
        s += " odeur : " + str (self.odeur)
        return s

    def __add__ (self,f) :
        print "ajout fromage"
        poids = self.poids + f.poids
        couleur = [0,0,0]
        for i in range (0,3) :
            couleur [i] = (self.couleur [i] * self.poids \
                       + f.couleur [i] * f.poids) / poids
        odeur = (self.odeur * self.poids + \
                 f.odeur * f.poids) / poids
        couleur = ( couleur [0], couleur [1], couleur [2])
        return fromage (poids, couleur, odeur)

class gruyere (fromage) :
    def __init__ (self,p) :
        fromage.__init__ (self, p, c = (150,150,0), o = 0.1)

    def __str__ (self) :
        s = fromage.__str__(self)
        s = "gruyère, " + s
        return s

    def __add__ (self,f) :
        print "ajout gruyère"
        if not isinstance (f, gruyere) :
            return fromage.__add__ (self, f)
        else :
            r = gruyere (self.poids + f.poids)
            return r

#--------------------------------------------
fr = fromage (5.0, (255,0,0), 0.5)
fr2 = fromage (10.0, (0,255,0), 1)
fr3 = fr + fr2
print fr
print fr2
print fr3
print "----------------------"
g = gruyere (3.0)
g2 = gruyere (7.0)
g3 = g + g2
print g
print g2
print g3
print "----------------------"
print fr2 + g

héritage

class Fonction :
    def calcul (self, x) : pass
    def calcul_n_valeur (self, l) :
        res = [ self.calcul (i) for i in l ]
        return res
        
class Carre (Fonction) :
    def calcul (self, x) : return x*x
        
class Cube (Fonction) :
    def calcul (self, x) : return x*x*x

l = [0,1,2,3]
print l   # affiche [0, 1, 2, 3]

l1 = Carre ().calcul_n_valeur (l)  # l1 vaut [0, 1, 4, 9]
l2 = Cube () .calcul_n_valeur (l)  # l2 vaut [0, 1, 8, 27]

méthode paramètre d'une fonction

class Fonction :
    def calcul (self, x) : pass
class Carre (Fonction) :
    def calcul (self, x) : return x*x
class Cube (Fonction) :
    def calcul (self, x) : return x*x*x
        
def calcul_n_valeur (l,f):
    res = [ f(i) for i in l ]
    return res

l = [0,1,2,3]
l1 = calcul_n_valeur (l, Carre ().calcul) # l1 vaut [0, 1, 4, 9]
l2 = calcul_n_valeur (l, Cube ().calcul)  # l2 vaut [0, 1, 8, 27]

File: chap4_classe.tex, line 2523


class Matrice :
    def __init__ (self,lin,col,coef):
        self.lin, self.col = lin, col
        
    # interface d'échange
    def get_lin () : return self.lin
    def get_col () : return self.col
    def __getitem__(self,i,j): pass
    def __setitem__(self,i,j,v): pass
    def get_submat(self, i1,j1,i2,j2): pass
    def set_submat(self, i1,j1,mat): pass 
    # fin de l'interface d'échange
    
    def trace (self) :
        t = 0
        for i in xrange (0, self.lin):
            t += self (i,i)
        return t
        
class MatriceList (Matrice) :
    def __init__ (self,lin,col,coef):
        Matrice.__init__ (self, \
                      lin, col, coef)
        #...

    def __getitem__ (self, i,j) : #...
    def __setitem__ (self, i,j, v) : #...
    def get_submat(self, i1,j1,i2,j2): #...
    def set_submat(self, i1,j1,mat): #...
    
class MatriceDict (Matrice) :
    def __init__ (self,lin,col,coef):
        Matrice.__init__ (self, \
                       lin, col, coef)
        #...
        
    def __getitem__ (self, i,j) : #...
    def __setitem__ (self, i,j, v) : #...
    def get_submat(self, i1,j1,i2,j2): #...
    def set_submat(self, i1,j1,mat): #...

File: chap4_classe.tex, line 2568


class Produit :
    def calcul (self, mat1, mat2):
        pass

class ProduitClassique (Produit) :
    def calcul (self, mat1, mat2):
        #...
        return 
        
class ProduitStrassen (Produit) :
    def calcul (self, mat1,mat2):
        #...
        return 

File: chap5_exception.tex, line 19


x = 0
y = 1.0 / x

File: chap5_exception.tex, line 28


Traceback (most recent call last):
  File "cours.py", line 2, in ?
    y = 1.0 / x
ZeroDivisionError: float division

File: chap5_exception.tex, line 51


def inverse (x):
    y = 1.0 / x
    return y
    
a = inverse (2)
print a
b = inverse (0)
print b

File: chap5_exception.tex, line 66


Traceback (most recent call last):
  File "cours.py", line 8, in ?
    b = inverse (0)
  File "cours.py", line 3, in inverse
    y = 1.0 / x
ZeroDivisionError: float division

File: chap5_exception.tex, line 80


def inverse (x):
    y = 1.0 / x
    return y
    
try :
    a = inverse (2)
    print a
    b = inverse (0)  # déclenche une exception
    print b
except :
    print "le programme a déclenché une erreur"

File: chap5_exception.tex, line 98


0.5
le programme a déclenché une erreur

File: chap5_exception.tex, line 108


def inverse (x):
    y = 1.0 / x
    return y
    
try :
    print inverse (2)  # pas d'erreur
    print inverse (1)  # pas d'erreur non plus
except :
    print "le programme a déclenché une erreur"
else :
    print "tout s'est bien passé"

File: chap5_exception.tex, line 125


0.5
1.0
tout s'est bien passé

File: chap5_exception.tex, line 135


try : 
    # ... instructions à protéger
except :
    # ... que faire en cas d'erreur 
else : 
    # ... que faire lorsque aucune erreur n'est apparue

File: chap5_exception.tex, line 152


def inverse (x):
    y = 1.0 / x
    return y
    
try :
    print (-2.1) ** 3.1  # première erreur
    print inverse (2)
    print inverse (0)    # seconde erreur
except :
    print "le programme a déclenché une erreur"

File: chap5_exception.tex, line 174


def inverse (x):
    y = 1.0 / x
    return y
    
try :
    print inverse (2)
    print inverse (0)
except Exception, exc:
    print "exception de type ", exc.__class__  
         # affiche exception de type  exceptions.ZeroDivisionError
    print "message ", exc
         # affiche le message associé à l'exception

File: chap5_exception.tex, line 194


def inverse (x):
    y = 1.0 / x
    return y
    
try :
    print (-2.1) ** 3.1  # première erreur
    print inverse (2)
    print inverse (0)    # seconde erreur
except Exception, exc:
    if isinstance (exc, ZeroDivisionError) :
        print "division par zéro"
    else :
        print "erreur insoupçonnée : ", exc.__class__
        print "message ", exc

File: chap5_exception.tex, line 215


erreur insoupçonnée :  exceptions.ValueError

File: chap5_exception.tex, line 223


def inverse (x):
    y = 1.0 / x
    return y
    
try :
    print (-2.1) ** 3.1
    print inverse (2)
    print inverse (0)
except ZeroDivisionError:
    print "division par zéro"
except Exception, exc:
    print "erreur insoupçonnée : ", exc.__class__
    print "message ", exc

File: chap5_exception.tex, line 243



try :
    # ... instructions à protéger
except type_exception_1 :
    # ... que faire en cas d'erreur de type type_exception_1
except type_exception_i :
    # ... que faire en cas d'erreur de type type_exception_i
except type_exception_n :
    # ... que faire en cas d'erreur de type type_exception_n
except :
    # ... que faire en cas d'erreur d'un type différent de tous 
    #     les précédents types
else :
    # ... que faire lorsque une erreur aucune erreur n'est apparue

File: chap5_exception.tex, line 381


def inverse (x):
    if x == 0 :
        raise ValueError
    y = 1.0 / x
    return y
    
try :
    print inverse (0)  # erreur
except ValueError:
    print "erreur"

File: chap5_exception.tex, line 399


def inverse (x):
    if x == 0 :
        raise ValueError ("valeur nulle interdite, fonction inverse")
    y = 1.0 / x
    return y
    
try :
    print inverse (0)  # erreur
except ValueError, exc:
    print "erreur, message : ", exc

File: chap5_exception.tex, line 417



raise exception_type (message) :

File: chap5_exception.tex, line 437


class ZeroDivisionError(ArithmeticError)
 |  Second argument to a division or modulo operation was zero.
 |  
 |  Method resolution order:
 |      ZeroDivisionError
 |      ArithmeticError
 |      StandardError
 |      Exception

File: chap5_exception.tex, line 473


def inverse (x):
    y = 1.0 / x
    return y
    
try :
    try :    
        print inverses (0)  # fonction inexistante --> exception NameError
        print inverse (0)   # division par zéro --> ZeroDivisionError
    except NameError:
        print "appel à une fonction non définie"
except ZeroDivisionError, exc:
    print "erreur ", exc

File: chap5_exception.tex, line 492


def inverse (x):
    y = 1.0 / x
    return y
    
try :
    try :    
        print inverse (0)   # division par zéro --> ZeroDivisionError
        print inverses (0)  # fonction inexistante --> exception NameError
    except NameError:
        print "appel à une fonction non définie"
except ZeroDivisionError, exc:
    print "erreur ", exc

File: chap5_exception.tex, line 511


def inverse (x):
    try :
        y = 1.0 / x
    except ZeroDivisionError, exc:
        print "erreur ", exc
        if x > 0 : return 1000000000
        else : return -1000000000
    return y
    
try :    
    print inverse (0)   # division par zéro    --> la fonction inverse sait gérer
    print inverses (0)  # fonction inexistante --> exception NameError
except NameError:
    print "appel à une fonction non définie"

File: chap5_exception.tex, line 541


class AucunChiffre (Exception) :
    """chaîne de caractères contenant aussi autre chose que des chiffres"""

def conversion (s) :
    """conversion d'une chaîne de caractères en entier"""
    if not s.isdigit () :
        raise AucunChiffre (s)
    return int (s)

try :
    s = "123a"
    print s, " = ", conversion (s)
except AucunChiffre, exc :
    # on affiche ici le commentaire associé à la classe d'exception
    # et le message associé
    print AucunChiffre.__doc__, " : ", exc

File: chap5_exception.tex, line 564


class AucunChiffre (Exception) :
    """chaîne de caractères contenant aussi autre chose que des chiffres"""
    def __str__ (self) :
        return self.__doc__ + " " + Exception.__str__ (self)

File: chap5_exception.tex, line 585


class AucunChiffre (Exception) :
    """chaîne de caractères contenant aussi autre chose que des chiffres"""
    def __init__(self, s, f = "") :
        Exception.__init__(self, s)
        self.s = s
        self.f = f
    def __str__(self) :
        return """exception AucunChiffre, depuis la fonction """ + self.f + \
                  " avec le paramètre " + self.s

def conversion (s) :
    """conversion d'une chaîne de caractères en entier"""
    if not s.isdigit () :
        raise AucunChiffre (s, "conversion")
    return int (s)

try :
    s = "123a"
    i = conversion (s)
    print s, " = ", i
except AucunChiffre, exc :
    print exc
    print "fonction : ", exc.f

File: chap5_exception.tex, line 615


exception AucunChiffre, depuis la fonction conversion avec le paramètre 123a
fonction :  conversion

File: chap5_exception.tex, line 631


class point_espace:
    
    #...
            
    class class_iter:
        def __init__ (self,ins):
            self._n   = 0
            self._ins = ins
        def __iter__ (self) : 
            return self
        def next (self):
            if self._n <= 2:
                v = self._ins [self._n]
                self._n += 1
                return v
            else :
                raise StopIteration
    
    def __iter__(self):
        return point_espace.class_iter (self)

# ...

File: chap5_exception.tex, line 664


def racine_carree(x) :
    if x < 0 : return False, 0
    else : return True, x ** 0.5
print racine_carree (-1)  # (False, 0)
print racine_carree (1)   # (True, 1.0)

File: chap5_exception.tex, line 676


def racine_carree(x) :
    if x < 0 : raise ValueError ("valeur négative")
    return x ** 0.5
print racine_carree (-1)  # déclenche une exception
print racine_carree (1)

fichier ouvert et exception

# coding: latin-1
def ajoute_resultat_division (nom, x, y) :
    """ajoute le résultat de la division x/y au fichier nom"""
    f = open (nom, "a")
    f.write (str (x) + "/" + str (y) + "= ")
    f.write ( str ((float (x)/y)) + "\n" )     # exception si y == 0
    f.close ()
    
for i in range (0, 5) :
    try :
        print str (i-1) + "/" + str (i-2)
        ajoute_resultat_division ("essai.txt", i-1,i-2)
    except Exception, e : print "erreur avec i = ", i, ",", e

File: chap5_exception.tex, line 698


-1/-2
0/-1
1/0
erreur avec i =  2 , float division
2/1
3/2

File: chap5_exception.tex, line 709


-1/-2= 0.5
0/-1= 0.0
2/1= 2.0
3/2= 1.5
1/0= 


# coding: latin-1
"""exemple de module, aide associée"""

exemple_variable = 3

def exemple_fonction () :
    """exemple de fonction"""
    return 0
    
class exemple_classe :
    """exemple de classe"""
    def __str__ (self) :
        return "exemple_classe"

(1)

import module_exemple

c = module_exemple.exemple_classe ()
print c
print module_exemple.exemple_fonction()
help (module_exemple)








File: chap6_module.tex, line 58


import module_exemple
module_exemple.exemple_variable = 10
reload (module_exemple)
print module_exemple.exemple_variable   # affiche 3

(2)

import module_exemple as alias

c = alias.exemple_classe ()
print c
print alias.exemple_fonction ()
help (alias)

(3)

from module_exemple import *

c = exemple_classe ()
print c
print exemple_fonction ()

(4)

alias = __import__ ("module_exemple")

c = alias.exemple_classe ()
print c
print alias.exemple_fonction ()
help (alias)

File: chap6_module.tex, line 99


if __name__ == "__main__" :
    print "ce fichier est le programme principal"

File: chap6_module.tex, line 113


import sys
sys.path.append (sys.path [0] + "/../common")  
################ sys.path [0] = répertoire de ce programme
import nom_module

import dynamique de module

# coding: latin-1
def import_fichier (module) :
    import os.path
    import sys
    if os.path.exists (module) :           # on teste l'existence du fichier
        folder,name = os.path.split (module)  # on obtient le répertoire du module
        if folder not in sys.path :
            sys.path.append (folder)       # on ajoute le répertoire dans la liste
                                           # des répertoires autorisés
        name = name.replace (".py", "")    # on enlève l'extension
        module = __import__ (name)         # on importe le module
        return module
    else :
        # si le fichier n'existe pas --> on lève une exception
        raise ImportError ("impossible d'importer le module " + module)
        
# on importe un module    
mod = import_fichier (r"D:\Dupre\informatique\programme\corde.py")
# on affiche l'aide associée
help (mod)

File: chap6_module.tex, line 137


import sys
for m in sys.modules :
    print m, " " * (14 - len(str(m))), sys.modules [m]

File: chap6_module.tex, line 144


os              <module 'os' from 'c:\python26\lib\os.pyc'>
os.path         <module 'ntpath' from 'c:\python26\lib\ntpath.pyc'>
re              <module 're' from 'c:\python26\lib\re.pyc'>
site            <module 'site' from 'c:\python26\lib\site.pyc'>
sys             <module 'sys' (built-in)>
types           <module 'types' from 'c:\python26\lib\types.pyc'>
...

File: chap6_module.tex, line 158


module_exemple  <module 'module_exemple' from 'D:\python_cours\module_exemple.py'>

File: chap6_module.tex, line 167


if "module_exemple" in sys.modules :
    m = sys.modules ["module_exemple"]
    m.exemple_fonction ()

File: chap6_module.tex, line 191


import os
print os.__name__, os.__doc__
if __name__ == "__main__" : print "ce fichier est le point d'entrée"
else : print "ce fichier est importé"

File: chap6_module.tex, line 211


import mesmodules.extension
import mesmodules.part1.niveaudeux
import mesmodules.part2.niveaudeuxbis

estimation du nombre $\pi$

# coding: latin-1
import random
import math

somme = 0
nb    = 1000000
for i in range (0,nb) :
    x = random.random ()  # nombre aléatoire entre [0,1]
    y = random.random ()
    r = math.sqrt (x*x + y*y)  # racine carrée
    if r <= 1 : somme += 1
        
print "estimation ", 4 * float (somme) / nb
print "PI = ", math.pi

intégrale de Monte Carlo

import random  # import du module random : simulation du hasard
import math    # import du module math : fonctions mathématiques

def integrale_monte_carlo (a,b,f,n) :
    somme = 0.0
    for i in range (0,n) :
        x = random.random () * (b-a) + a
        y = f(x)
        somme += f(x)
    return somme / n
    
def racine (x) : return math.sqrt (x)
    
print integrale (0,1,racine,100000)

File: chap6_module.tex, line 284


def get_page_html (url):
    import urllib
    d = urllib.urlopen(url)
    res = d.read ()
    d.close ()
    return res

url = "http://www.lemonde.fr"
print get_page_html (url)

File: chap6_module.tex, line 304


c:\python26\python c:\python26\lib\pydoc.py -w nom_de_fichier

génération automatique de l'aide avec \codesindex{pydoc

# coding: latin-1
"""aide associée à ce module, exemple d'utiliation de pydoc"""
import os.path
import os

def pydoc_present () :
    """teste la présence du fichier pydoc.py"""
    p = "c:\\python26\\lib\\pydoc.py"""
    return os.path.exists (p)
    
def pydoc_generation (file) :
    """génère la documentation associée au fichier file"""
    if not pydoc_present () :
        raise Exception ("pydoc n'est pas installé")
    os.system ("c:\\python26\\python c:\\python26\\lib\\pydoc.py -w " + file)

class ExempleClass (object) :
    """exemple de classe avec de la documentation
    la classe contient comme attribut :
       - li : liste quelconque
    """
    def __init__ (self) :
        object.__init__ (self)
        self.li = ["un", "deux"]
    def __str__ (self) :
        """permet d'afficher la classe sous forme de chaînes de caractères"""
        return "li = " + str (self.li)
        
if __name__ == "__main__" :
    e = ExempleClass ()
    print e  # affiche li = ['un', 'deux']
    pydoc_generation ("exemple_pydoc")

File: chap6_module.tex, line 342


c:\python26\python setup.py install

File: chap6_module.tex, line 349


python setup.py install

un module en C++

#include <Python.h>
#include <stdio.h>

/** 
Une fois importe, le module definit deux fonctions :
    - exemple qui prend une chaine en argument et retourne 0
    - exemple2 qui leve une exception creee pour l'occasion 
*/



static PyObject* ExempleErreur;

static PyObject* exemple (PyObject* self, PyObject* args)
{
  const char* chaine;

  if (!PyArg_ParseTuple (args, "s", &chaine))
    return NULL;

  return Py_BuildValue("i", 2); 
}

static PyObject* exemple2(PyObject* self, PyObject* args)
{
  //const char* chaine ;

  PyErr_SetString (ExempleErreur, "Exemple de levée d'erreur") ;
  return NULL;
}

////////////////////////////////////////////////////
//////////// export des fonctions //////////////////
////////////////////////////////////////////////////

const char * module_name = "sample_module" ;
char buffer [100] ;

static PyMethodDef fonctions [] = {
  {"exemple",   exemple,    METH_VARARGS, "Un commentaire"},
  {"exemple2",  exemple2,   METH_VARARGS, "Une methode levant une exception"},
  {NULL, NULL, 0, NULL}
} ;

PyMODINIT_FUNC initsample_module(void)
{
  PyObject* m ;
  m = Py_InitModule (module_name, fonctions) ;
  
  
  sprintf (buffer, "%s.Exception", module_name) ;
  ExempleErreur = PyErr_NewException(buffer, NULL, NULL) ;
  Py_INCREF (ExempleErreur) ;
  PyModule_AddObject (m, "Exception", ExempleErreur) ;
}

importer un module en C++

# coding: latin-1
"""
import d'un module C (un fichier), inclut la recompilation 
si le module a évolué depuis sa dernière compilation
"""

import os, sys, re

def _find_compiled_file (path, name) :
    """cherche un fichier compilé"""
    ver         = sys.version_info
    st          = "%d.%d" % ver [:2]
    name        = os.path.splitext (name) [0]
    exp         = re.compile (name + "[.]o$")
    file, rep   = [], []
    for r, d, f in os.walk (path) :
        if st not in r : continue
        for a in f : 
            if exp.search (a) :
                return r,a
    return None,None

def import_c_module (name, mingw = r"c:\MinGW\bin", cpp = True, remove = False, path = None) :
    """
    @ingroup SQLAppModels    
    import d'un module C
    @param      name        nom du module C (nom du fichier sans extension, sans chemin non plus)
    @param      mingw       emplacement du compilateur mingw
    @param      cpp         c++ file?
    @param      remove      remove the file first before compiling
    @param      path        if the file is not found, try to look into this folder
    @return                 objet module
    
    @warning    remove = True must be used when the module is compiled for the first time. 
                Otherwise, the module is already loaded and impossible to remove until Python is closed.
    """
    if os.path.splitext (name) [1] == "" : 
        if cpp : 
            name += ".cpp"
            ext   = "cpp"
        else : 
            name += ".c"
            ext   = "c"
    else :
        ext = os.path.splitext (name) [1] [1:]
        
    mfile   = name
    mod     = os.path.splitext (mfile) [0]
    if path != None :
            mypath  = os.path.normpath (os.path.realpath (path))
            allpath = [mypath, "."]
    else :  allpath = ["."]
        
    for p in sys.path :
        if p not in allpath : allpath.append (p)
    
    for path in allpath :
        whole = os.path.join (path, name)
        if os.path.exists (whole) :
            break
    else :
        path_tried = u"\n".join (allpath)
        raise ImportError ("unable to find file %s in any import path:\n%s" \
                                % (name, path_tried))
        
    if sys.platform == "win32" : fsec = mod + ".pyd"
    else :                       fsec = mod + ".so"
        
    if path not in sys.path :
        sys.path.append (path)
        
    comp = os.path.join (path, fsec)
    if not os.path.exists (comp) :
        cond = True 
        resa = "not found"
    else :
        if remove :
            os.remove (comp)
            cond = True
            resa = "remove"
        else :
            r,f     = _find_compiled_file (path, mfile)
            if f != None :
                wholeo  = os.path.join (r,f)
                datec   = os.path.getmtime (whole)
                date    = os.path.getmtime (wholeo)
                cond    = datec > date
                resa    = "date"
            else :
                cond = True
                resa = "f == None"
                
    if cond :
        mfile = mod

        file =  ("""
                # coding: latin-1
                from distutils.core import setup
                from distutils.core import Extension

                setup(name          = '%s',
                      version       = '0.1',
                      ext_modules   = [Extension('%s', ['%s.%s']), ],
                      url           = '',
                      author        = '',
                      author_email  = '...',
                      )
                """ % (mfile,mfile,mfile,ext)).replace ("                ", "")
        wr   = os.path.join (path, "setup.py")
        f = open (wr, "w")
        f.write (file)
        f.close ()
        
        env = os.getenv ("PATH")
        if mingw not in env : 
            os.putenv ("PATH", env + ";" + mingw)
        
        cwd = os.getcwd ()
        os.chdir (path)
        
        py = sys.executable.replace ("pythonw.exe", "python.exe")
        if sys.platform == "win32" :    
                cmd  = "%s setup.py build_ext --inplace -c mingw32" % (py)
        else :  cmd  = "%s setup.py build_ext --inplace" % (py)
        child_stdin, stdout, child_stderr = os.popen3 (cmd)
        res = stdout.read ()
        err = child_stderr.read ()
        stdout.close ()
        
        os.chdir (cwd)
        
        if len (err) > 0 :
            message  = "\nOUTPUT:\n" + res + "\n\n"
            message += "ERR:\n" + err
            if "error" in err :
                message += "unable to compile %s (resa %s)\n%s" % (name, resa, message)
                print (message)
                raise ImportError (message)
            else :
                print (message)
            
        mod = __import__ (mfile)
        return mod
    
    else :
        mfile   = mod
        mod     = __import__ (mfile)
        return mod
    
if __name__ == "__main__" :
    sample_module = import_c_module ("sample_module", cpp = True)
    print sample_module

    print sample_module.exemple("e")
    print sample_module.exemple2() 

File: chap6_module.tex, line 467


BOOST_PYTHON_MODULE(PythonSample)
{ 
  // étapes d'initialisation
} ;

File: chap6_module.tex, line 479


int fonction (int r, const char * s, double x = 4) ;
BOOST_PYTHON_MODULE(PythonSample)
{ 
  boost::python::def ("fonction", fonction, 
                        (boost::python::arg ("r"), 
                         boost::python::arg ("s"), 
                         boost::python::arg ("x") = 4),
                         "aide associée à la fonction") ;
} ;

File: chap6_module.tex, line 504


import PythonSample
print PythonSample.fonction (4, "second")
print PythonSample.fonction (4, "second", 5)

File: chap6_module.tex, line 520


boost::python::class_<PythonClassSample> obj (
          "ClassSample", 
          "help on PythonClassSample") ) ;

File: chap6_module.tex, line 538

   
boost::python::class_<PythonClassSample> obj (
        "ClassSample", 
        "help on PythonClassSample",
        boost::python::init<int,const char*> (                     // ajout
             (boost::python::arg ("a"),                            // ajout
              boost::python::arg ("s") = "default value for s"),   // ajout
              "help on PythonClassSample constructor" )            // ajout
        ) ;

File: chap6_module.tex, line 551

   
boost::python::class_<PythonClassSample,  
                      boost::python::bases<ClassBase> > obj (
                           "ClassSample", 
                           "help on PythonClassSample") ;

File: chap6_module.tex, line 560


boost::python::class_<PythonClassSample, 
           boost::python::bases<ClassBase> > obj (
         // ...

File: chap6_module.tex, line 575

   
obj.def (   "Random",                      
            &PythonClassSample::Random, 
            (boost::python::arg ("pos")),  
            "help on the method") ;

File: chap6_module.tex, line 584

   
boost::python::class_<MyVector> obj ("Vector", "help on vector",
        boost::python::init<int> (
        (PY_ARG ("n")),
        "crée un vecteur de dimension n")) ;
// ajout d'un constructeur sans paramètre
obj.def (boost::python::init<MyVector> ()) ;

File: chap6_module.tex, line 595

   
v  = PythonSample.Vector ()
v2 = PythonSample.Vector (10)

File: chap6_module.tex, line 604

   
obj.def_readwrite ("a", &PythonClassSample::_a, "retourne un accès à a") ;

File: chap6_module.tex, line 643


#ifndef LIB_MAFONCTION_H
#define LIB_MAFONCTION_H

#include <vector>

void somme_vecteur (
  const std::vector<double> &v1,
  const std::vector<double> &v2,
  std::vector<double> &res) ;

#endif










File: chap6_module.tex, line 668


#include "mafonction.h"
void somme_vecteur (
  const std::vector<double> &v1,
  const std::vector<double> &v2,
  std::vector<double> &res)
{
  if (v1.size () != v2.size ())
    throw std::runtime_error (
         "dimensions différentes") ;
  res.resize (v1.size ()) ;
  std::vector<double>::
          const_iterator it1,it2 ;
  std::vector<double>::iterator it3 ;
  for (it1 = v1.begin (), 
       it2 = v2.begin (),
       it3 = res.begin () ; 
       it1 != v1.end () ;
       ++it1, ++it2, ++it3) 
       *it3 = *it1 + *it2 ;
}	

File: chap6_module.tex, line 695


#ifndef PYTHON_MAFONCTION_H
#define PYTHON_MAFONCTION_H

#include "python/definition.h"

boost::python::list
     python_somme_vecteur (
        boost::python::list v1,
        boost::python::list v2) ;
        
#endif        
        
        
        
        
        
        
        

File: chap6_module.tex, line 719


#include "python/definition.h"
#include "mafonction.h"
#include "../libsample/mafonction.h"
#include "python/conversion.h"
#include "python/conversion.hpp"
boost::python::list 
     python_somme_vecteur (
        boost::python::list v1,
        boost::python::list v2)
{
  std::vector<double> cv1,cv2,cres ;
  PythonConvert (v1, cv1) ;
  PythonConvert (v2, cv2) ;
  somme_vecteur (cv1, cv2, cres) ;
  boost::python::list res ;
  PythonConvert (cres, res) ;
  return res ;
}        

File: chap6_module.tex, line 744


// ...
#include "../mafonction.h"
BOOST_PYTHON_MODULE(PythonSample)
{
  // ...
  def ("somme_vecteur", 
        &python_somme_vecteur,
        (boost::python::arg ("v1"),
         boost::python::arg ("v2")),
 "retourne la somme de deux vecteurs");
  // ...
} ;

File: chap6_module.tex, line 762


import PythonSample as PS
v1 = [1.0, 2.0]
v2 = [6.5, 7.8]
v3 = PS.somme_vecteur (v1, v2) 









File: chap6_module.tex, line 799


class PythonClassSample 
{
    ...
    PythonClassSample & __iadd__ (const PythonClassSample &a) ;
    ...
} ;

File: chap6_module.tex, line 810


x.def ("__iadd__", 
       &PythonClassSample::__iadd__, 
       boost::python::return_internal_reference<>(), 
       "addition") ;

import d'une DLL

import sys
if "PythonSample" not in sys.modules :
    PythonSample = imp.load_dynamic ('PythonSample', PythonSample.dll) 
    sys.modules ["PythonSample"]  = PythonSample

File: chap6_module.tex, line 844


import PythonSampled as PythonSample
# au lieu de import PythonSample

File: chap6_module.tex, line 851


import sys
if "PythonSampled" in sys.modules : PythonSample = sys.modules ["PythonSampled"]
else : import PythonSample

File: chap6_module.tex, line 872


if (<condition>)
    throw std::runtime_error ("message d'erreur") ;

File: chap7_fichiers.tex, line 47


f = open ("nom-fichier", "w")    # ouverture

f.write ( s )    # écriture de la chaîne de caractères  s 
f.write ( s2 )   # écriture de la chaîne de caractères  s2
...

f.close ()  # fermeture

File: chap7_fichiers.tex, line 75


mat =  ... # matrice de type liste de listes
f = open ("mat.txt", "w")
for i in range (0,len (mat)) :                # la fonction join est aussi
    for j in range (0, len (mat [i])) :       # fréquemment utilisée
        f.write ( str (mat [i][j]) + "\t")    # pour assembler les chaînes
    f.write ("\n")                            # un une seule et réduire le
f.close ()                                    # nombre d'appels à f.write

File: chap7_fichiers.tex, line 94


mat = ... # matrice de type liste de listes
f = open ("mat.txt", "w")
for i in range (0,len (mat)) :
    for j in range (0, len (mat [i])) :
        print >> f, str (mat [i][j]), "\t",  # ligne changée
    print >> f                               # ligne changée
f.close ()

File: chap7_fichiers.tex, line 117


f = open ("nom-fichier", "a")    # ouverture en mode ajout, mode "a"
...

File: chap7_fichiers.tex, line 129


f = open ("essai.txt", "w")
f.write (" premiere fois ")
f.close ()
f = open ("essai.txt", "w")
f.write (" seconde fois ")
f.close ()

# essai.txt : seconde fois 

File: chap7_fichiers.tex, line 142


f = open ("essai.txt", "w")
f.write (" premiere fois ")
f.close ()
f = open ("essai.txt", "a")  ###
f.write (" seconde fois ")
f.close ()

# essai.txt : premiere fois  seconde fois 

File: chap7_fichiers.tex, line 180


f = open ("essai.txt", "r")  # ouverture du fichier en mode lecture
for ligne in f :             # pour toutes les lignes du fichier
    print ligne              # on affiche la ligne (*)
f.close ()                   # on ferme le fichier

File: chap7_fichiers.tex, line 192


f = open ("essai.txt", "r") # ouverture du fichier en mode lecture
l = f.readlines ()          # lecture de toutes les lignes, placées dans une liste
f.close ()                  # fermeture du fichier

for s in l : print s        # on affiche les lignes à l'écran (*)

File: chap7_fichiers.tex, line 208


f = open ("essai.txt", "r") # ouverture du fichier en mode lecture
l = f.readlines ()          # lecture de toutes les lignes, placées dans une liste
f.close ()                  # fermeture du fichier

     # contiendra la liste des lignes nettoyées
l_net = [ s.strip ("\n\r") for s in l ] 

File: chap7_fichiers.tex, line 225


nom  ; prénom ; livre
Hugo  ; Victor  ; Les misérables
Kessel ; Joseph  ; Le lion
Woolf ; Virginia  ; Mrs Dalloway
Calvino ; Italo  ; Le baron perché

File: chap7_fichiers.tex, line 237


mat = []                      # création d'une liste vide,
f = open ("essai.txt", "r")   # ouverture du fichier en mode lecture
for li in f :                 # pour toutes les lignes du fichier
    s = li.strip ("\n\r")     # on enlève les caractères de fin de ligne
    l = s.split (";")         # on découpe en colonnes
    mat.append (l)            # on ajoute la ligne à la matrice
f.close ()                    # fermeture du fichier

File: chap7_fichiers.tex, line 267


import zipfile
file = zipfile.ZipFile ("exemplezip.zip", "r")
for info in file.infolist () :
    print info.filename, info.date_time, info.file_size
file.close ()

File: chap7_fichiers.tex, line 279


import zipfile
file = zipfile.ZipFile ("exemplezip.zip", "r")
data = file.read ("informatique/testzip.py")
file.close ()
print data

File: chap7_fichiers.tex, line 296


import zipfile
file = zipfile.ZipFile ("test.zip", "w")
file.write ("fichier.txt", "nom_fichier_dans_zip.txt", zipfile.ZIP_DEFLATED)
file.close ()

envoi d'un mail automatiquement

import smtplib
from email.MIMEMultipart    import MIMEMultipart
from email.MIMEBase         import MIMEBase
from email.MIMEText         import MIMEText
from email.Utils            import formatdate
from email                  import Encoders
import os

def envoyer_mail (aqui, sujet, contenu, files = []):
    de              = "email de l'auteur"
    msg             = MIMEMultipart()
    msg ['From']    = de
    msg ['To']      = aqui
    msg ['Date']    = formatdate (localtime = True)
    msg ['Subject'] = sujet

    msg.attach(  MIMEText (contenu) )
    for file in files:
        part = MIMEBase('application', 'octet-stream')
        part.set_payload ( open(file,'rb').read () )
        Encoders.encode_base64 (part)
        part.add_header ('Content-Disposition',  \
                         'attachment; filename="%s"' % os.path.basename (file))
        msg.attach (part)

    smtp = smtplib.SMTP ("smtp.gmail.com", 587)
    smtp.ehlo ()
    smtp.starttls ()
    smtp.ehlo ()
    smtp.login ("login", "mot_de_passe")

    smtp.sendmail (de, aqui, msg.as_string () )
    smtp.close()
    
envoyer_mail ( "destinataire", "sujet","contenu", ["mail.py"] )

(1)

# coding: latin-1
import glob
import os.path

def liste_fichier_repertoire (folder, filter) :
    # résultats
    file,fold = [], []
    
    # recherche des fichiers obéissant au filtre
    res = glob.glob (folder + "\\" + filter)
    
    # on inclut les sous-répertoires qui n'auraient pas été
    # sélectionnés par le filtre
    rep = glob.glob (folder + "\\*")
    for r in rep : 
        if r not in res and os.path.isdir (r) : 
            res.append (r)
            
    # on ajoute fichiers et répertoires aux résultats
    for r in res :
        path = r
        if os.path.isfile (path) :
            # un fichier, rien à faire à part l'ajouter
            file.append (path)
        else :
            # sous-répertoire : on appelle à nouveau la fonction
            # pour retourner la liste des fichiers inclus 
            fold.append (path)
            fi,fo = liste_fichier_repertoire (path, filter)
            file.extend (fi)  # on étend la liste des fichiers
            fold.extend (fo)  # on étend la liste des répertoires 
    # fin
    return file,fold
    
folder = r"D:\Dupre\_data\informatique"
filter = "*.tex"
file,fold = liste_fichier_repertoire (folder, filter)

for f in file : print "fichier ", f
for f in fold : print "répertoire ", f

(2)

# coding: latin-1
import os

def liste_fichier_repertoire (folder) :
    file, rep = [], []
    for r, d, f in os.walk (folder) :
        for a in d : rep.append (r + "/" + a)
        for a in f : file.append (r + "/" + a)
    return file, rep
    
folder = r"D:\Dupre\_data\informatique"
file,fold = liste_fichier_repertoire (folder)

for f in file : print "fichier ", f
for f in fold : print "répertoire ", f

(1)

# coding: latin-1
import struct
# on enregistre un entier, un réel et 4 caractères
i = 10
x = 3.1415692
s = "ABCD"

# écriture
file = open ("info.bin", "wb")
file.write ( struct.pack ("i" , i) )
file.write ( struct.pack ("d" , x) )
file.write ( struct.pack ("cccc" , *s) )
file.close ()

# lecture
file = open ("info.bin", "rb")
i = struct.unpack ("i",      file.read (4)) 
x = struct.unpack ("d",      file.read (8)) 
s = struct.unpack ("cccc",   file.read (4)) 
file.close ()

# affichage pour vérifier que les données ont été bien lues
print i  # affiche (10,)
print x  # affiche (3.1415692000000002,)
print s  # affiche ('A', 'B', 'C', 'D')

(2)

# coding: latin-1
import struct
# on enregistre un entier, un réel et n caractères
i = 10
x = 3.1415692
s = "ABCDEDF"

# écriture
file = open ("info.bin", "wb")
file.write ( struct.pack ("i" , i) )
file.write ( struct.pack ("d" , x) )
file.write ( struct.pack ("i" , len(s)) )  # on sauve la dimension de s
file.write ( struct.pack ("c" * len(s) , *s) )
file.close ()

# lecture
file = open ("info.bin", "rb")
i = struct.unpack ("i",      file.read (4)) 
x = struct.unpack ("d",      file.read (8)) 
l = struct.unpack ("i",      file.read (4)) # on récupère la dimension de s
l = l [0]  # l est un tuple, on s'intéresse à son unique élément
s = struct.unpack ("c" * l,  file.read (l)) 
file.close ()

# affichage pour contrôler
print i  # affiche (10,)
print x  # affiche (3.1415692000000002,)
print s  # affiche ('A', 'B', 'C', 'D', 'E', 'D', 'F')

File: chap7_fichiers.tex, line 470


import pickle

dico = {'a': [1, 2.0, 3, "e"], 'b': ('string', 2), 'c': None}
lis  = [1, 2, 3]

f = open ('data.bin', 'wb')
pickle.dump (dico, f)
pickle.dump (lis, f)
f.close()

File: chap7_fichiers.tex, line 487


f = open ('data.bin', 'rb')
dico = pickle.load (f)
lis  = pickle.load (f)
f.close()

(1)

import pickle
import copy

class Test :
    def __init__ (self) :
        self.chaine = "a"
        self.entier = 5
        self.tuple  = { "h":1, 5:"j" }

t = Test ()

f = open('data.bin', 'wb')  # lecture
pickle.dump (t, f)
f.close()

f = open('data.bin', 'rb')  # écriture
t = pickle.load (f)
f.close()

(2)

import pickle
import copy

class Test :
    def __init__ (self) :
        self.x = 5
        self.y = 3
        self.calcule_norme ()   # attribut calculé
    def calcule_norme (self) :
        self.n = (self.x ** 2 + self.y ** 2) ** 0.5
    def __getstate__ (self) :
        """conversion de Test en un dictionnaire"""
        d = copy.copy (self.__dict__)
        del d ["n"]  # attribut calculé, on le sauve pas
        return d
    def __setstate__ (self,dic) :
        """conversion d'un dictionnaire dic en Test"""
        self.__dict__.update (dic)
        self.calcule_norme ()  # attribut calculé

t = Test ()

f = open('data.bin', 'wb')  # lecture
pickle.dump (t, f)
f.close()

f = open('data.bin', 'rb')  # écriture
t = pickle.load (f)
f.close()

File: chap7_fichiers.tex, line 516


# coding: latin-1
import glob
import shutil
def copie_repertoire (rep1, rep2) :
    """copie tous les fichiers d'un répertoire rep1 vers un autre rep2"""
    li = glob.glob (rep1 + "/*.*")   # récupère dans une liste fichiers et 
                                     # répertoires qui respectent le filtre
    for l in li :
        to = l.replace (rep1, rep2)  # nom du fichier copié 
                                     # (on remplace rep1 par rep2)
        shutil.copy (l, to)
copie_repertoire ("c:/original", "c:/backup")

File: chap7_fichiers.tex, line 535


c:\python26\python.exe synchro.py c:/original c:/backup

File: chap7_fichiers.tex, line 552


interpréteur_python programme_python argument1 argument2 ...

lancer un programme \pythons en ligne de commande

# coding: latin-1
import glob
import shutil
def copie_repertoire (rep1, rep2) :
    """copie tous les fichiers d'un répertoire rep1 vers un autre rep2"""
    li = glob.glob (rep1 + "/*.*")
    for l in li :
        to = l.replace (rep1, rep2)  # nom du fichier copié 
                                     # (on remplace rep1 par rep2)
        shutil.copy (l, to)
        
import sys
                      # sys.argv [0] --> nom du programme (ici, synchro.py)
rep1 = sys.argv [1]   # récupération du premier paramètre
rep2 = sys.argv [2]   # récupération du second paramètre
copie_repertoire (rep1, rep2)

File: chap7_fichiers.tex, line 578


c:\python26\python.exe c:\batch\synchro.py 
          "c:\Program Files\source" "c:\Program Files\backup"

File: chap7_fichiers.tex, line 588


import os
os.system ("c:\python26\python.exe c:\batch\synchro.py " \
           "\"c:\Program Files\source\" \"c:\Program Files\backup\"")

lancer un navigateur en ligne de commande

mat = ["Victor Hugo 6".split (), "Marcel Proust 3".split () ]
f = open ("tableau.html", "w")
f.write ("<body><html>\n")
f.write ("<table border=\"1\">\n")
for m in mat :
    f.write ("<tr>")
    for c in m :
        f.write ("<td>" + c + "</td>")
    f.write ("</tr>\n")
f.write ("</table>")
f.close ()

import os
os.system ("\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\" tableau.html")
os.system ("\"C:\\Program Files\\Internet Explorer\\iexplore.exe\"" \
           " d:\\temp\\tableau.html")

File: chap7_fichiers.tex, line 611


s = """date 0 : 14/9/2000     
date 1 : 20/04/1971     date 2 : 14/09/1913     date 3 : 2/3/1978     
date 4 : 1/7/1986     date 5 : 7/3/47     date 6 : 15/10/1914     
date 7 : 08/03/1941     date 8 : 8/1/1980     date 9 : 30/6/1976"""

File: chap7_fichiers.tex, line 621


[0-3]?[0-9]/[0-1]?[0-9]/([0-2][0-9])?[0-9][0-9]

File: chap7_fichiers.tex, line 630


import re
# première étape : construction
expression = re.compile ("([0-3]?[0-9]/[0-1]?[0-9]/([0-2][0-9])?[0-9][0-9])")
# seconde étape  : recherche
res = expression.findall (s)  
print res

File: chap7_fichiers.tex, line 641


[('14/9/2000', '20'), ('20/04/1971', '19'),  ('14/09/1913', '19'), 
 ('2/3/1978', '19'),  ('1/7/1986', '19'),    ('7/3/47', ''),      
 ('15/10/1914', '19'), ('08/03/1941', '19'), ('8/1/1980', '19'),  
 ('30/6/1976', '19')]

File: chap7_fichiers.tex, line 679


s = r"D:\Dupre\_data\informatique\support\vba\image/vbatd1_4.png"
print re.compile ( "[\\\\/]image[\\\\/].*[.]png").search(s) # résultat positif
print re.compile (r"[\\/]image[\\/].*[.]png").search(s)     # même résultat

File: chap7_fichiers.tex, line 701


import re
s = "<h1>mot</h1>"
print re.compile ("(<.*>)") .match (s).groups () # ('<h1>mot</h1>',)
print re.compile ("(<.*?>)").match (s).groups () # ('<h1>',)

File: chap7_fichiers.tex, line 750


expression = re.compile ("([0-3]?[0-9]/[0-1]?[0-9]/([0-2][0-9])?[0-9][0-9])[^\d]")
print expression.search (s).group(1,2) # affiche ('14/9/2000', '20')
c = expression.search (s).span(1)      # affiche (9, 18)
print s [c[0]:c[1]]                    # affiche 14/9/2000

(1)

# coding: latin-1
import mutagen.mp3, mutagen.easyid3, os, re

def infoMP3 (file, tags) :
    """retourne des informations sur un fichier MP3 sous forme de 
    dictionnaire (durée, titre, artiste, ...)"""
    a = mutagen.mp3.MP3(file)
    b = mutagen.easyid3.EasyID3(file)
    info = { "minutes":a.info.length/60, "nom":file }
    for k in tags :
        try : info [k] = str (b [k][0])
        except : continue
    return info
    
def all_files (repertoire, tags, ext = re.compile (".mp3$")) :
    """retourne les informations pour chaque fichier d'un répertoire"""
    all = []
    for r, d, f in os.walk (repertoire) :
        for a in f : 
            if not ext.search (a) : continue
            t = infoMP3 (r + "/" + a, tags)
            if len (t) > 0 : all.append (t)
    return all
    
def heart_notitle_mots (all, avoid,sep,heart) :
    """retourne trois résultats
    - les chansons dont le titre valide l'expression régulière heart
    - les chansons dont le titre valide l'expression régulière avoid
    - le nombre moyen de mots dans le titre d'une chanson"""
    liheart, notitle  = [], []
    nbmot,nbsong      = 0,0
    for a in all :
        if "title" not in a : 
            notitle.append (a)
            continue
        ti = a ["title"].lower ()
        if avoid.match (ti) : 
            notitle.append (a)
            continue
        if heart.search (ti) : liheart.append (a)
        nbsong += 1
        nbmot  += len ([ m for m in sep.split (ti) if len (m) > 0 ])
    return liheart, notitle, float (nbmot)/nbsong

tags  = "title album artist genre tracknumber".split ()
all = all_files (r"D:\musique", tags)

avoid = re.compile ("^(((audio)?track( )?( - )?[0-9]{1,2})|(piste [0-9]{1,2}))$")
sep   = re.compile ("[- ,;!'.?&:]")
heart = re.compile ("((heart)(?!((ache)|(land))))")
liheart, notitle, moymot = heart_notitle_mots (all, avoid, sep, heart)

print "nombre de mots moyen par titre ", moymot
print "somme des durée contenant heart ", sum ( [ s ["minutes"] for s in liheart] )
print "chanson sans titre ", len (notitle)
print "liste des titres "
for s in liheart : print "   ",s ["title"]

File: chap7_fichiers.tex, line 787


import re
date = "05/22/2010"
exp  = "([0-9]{1,2})/([0-9]{1,2})/(((19)|(20))[0-9]{2})"
com  = re.compile (exp)
print com.search (date).groups ()    # ('05', '22', '2010', '20', None, '20')

File: chap7_fichiers.tex, line 795


exp  = "(?P<jj>[0-9]{1,2})/(?P<mm>[0-9]{1,2})/(?P<aa>((19)|(20))[0-9]{2})"
com  = re.compile (exp)
print com.search (date).groupdict () # {'mm': '22', 'aa': '2010', 'jj': '05'}

(2)

# coding: latin-1
"""ce programme détermine toutes les fonctions définies dans 
un programme et jamais appelées"""
import glob, os, re

def trouve_toute_fonction (s, exp, gr, expm = "^$") :
    """ à partir d'une chaîne de caractères correspondant
    à un programme Python, cette fonction retourne 
    une liste de 3-uples, chacun contient :
        - le nom de la fonction
        - (debut,fin) de l'expression dans la chaîne
        - la ligne où elle a été trouvée
       
    Paramètres:
       - s    : chaîne de caractères
       - exp  : chaîne de caractères correspond à l'expression
       - gr   : numéro de groupe correspondant au nom de la fonction
       - expm : expression négative
    """
    exp = re.compile (exp)
    res = []
    pos = 0
    r = exp.search (s, pos)   # première recherche
    while r != None :
        temp = (r.groups () [gr], r.span (gr), r.group (gr))
        x    = re.compile ( expm.replace ("function", temp [0]) )
        if not x.match (temp [2]) :  
            # l'expression négative n'est pas trouvé, on peut ajouter ce résultat
            res.append (temp)
        r    = exp.search (s, r.end (gr) )     # recherche suivante
    return res

def get_function_list_definition (s) :
    """trouve toutes les définitions de fonctions"""
    return trouve_toute_fonction (s, \
              "\ndef[ ]+([a-zA-Z_][a-zA-Z_0-9]*)[ ]*[(].*[)][ ]*[:]", 0)

def get_function_list_call (s) :
    """trouve tous les appels de fonctions"""
    return trouve_toute_fonction (s, \
              "\n.*[=(,[{ .]([a-zA-Z_][a-zA-Z_0-9]*)(?![ ]?:)[ ]*[(].*[)]?", 0, \
              "^\\n[ ]*(class|def)[ ]+function.*$")
                
def detection_fonction_pas_appelee (file) :                
    """retourne les couples de fonctions jamais appelées suivies
    du numéro de la ligne où elles sont définies"""

    f       = open (file, "r")
    li      = f.readlines ()
    f.close ()
    sfile   = "".join (li)
    
    funcdef = get_function_list_definition (sfile)
    funccal = get_function_list_call (sfile)
    f2 = [ p [0] for p in funccal ]
    res = []
    for f in funcdef :
        if f [0] not in f2 : 
            ligne = sfile [:f [1][0]].count ("\n")
            res.append ( (f [0], ligne+2))
    return res
    
def fonction_inutile () :  # ligne 63
    pass

if __name__ == "__main__" :
    file    = "fonction.py"
    print detection_fonction_pas_appelee (file)   
            # affiche [('fonction_inutile', 63)]

File: chap7_fichiers.tex, line 823


import datetime
naissance = datetime.datetime (1975,11,8,10,0,0)
jour = naissance.now () # obtient l'heure et la date actuelle
print jour              # affiche 2010-05-22 11:24:36.312000
age = jour - naissance  # calcule une différence
print age               # affiche 12614 days, 1:25:10.712000

File: chap7_fichiers.tex, line 838


import calendar
c = calendar.Calendar ()
for d in c.itermonthdays2 (1975,8) : print d

File: chap7_fichiers.tex, line 862


# coding: latin-1
st =  "eé"
su = u"eé"  # raccourci pour su = unicode ("eé", "latin-1")
            # ou encore      su = unicode ("eé".decode ("latin-1"))
            
print type (st)                                    # affiche <type 'str'>
print type (su)                                    # affiche <type 'unicode'>
print len (st),        ";", st                     # affiche  2 ; eé
print len (repr (st)), ";", repr (st)              # affiche  7 ; 'e\xe9'
print len (su),        ";", su.encode ("latin-1")  # affiche  2 ; eé
print len (repr (su)), ";", repr (su)              # affiche  8 ; u'e\xe9'

File: chap7_fichiers.tex, line 879


import codecs
f = codecs.open ("essai.txt", "r", "cp1252")  # jeu Windows
s = "".join (f.readlines ())
f.close ()
print type (s)              # affiche <type 'unicode'>
print s.encode ("cp1252")   # pour l'afficher, 
                            # il faut convertir l'unicode en "cp1252"

File: chap7_fichiers.tex, line 923


import sys
import locale
             # retourne le jeu de caractères par défaut
print sys.getdefaultencoding ()    # affiche ascii
             # retourne le jeu de caractères du système d'exploitation
print locale.getdefaultlocale()    # affiche ('fr_FR', 'cp1252')

File: chap8_interface.tex, line 59


zone_texte = Tkinter.Label (text = "zone de texte")

File: chap8_interface.tex, line 63


import Tkinter         # import de Tkinter
root = Tkinter.Tk ()   # création de la fenêtre principale
# ...
obj = Tkinter.Label (text = "zone de texte")
# ...
obj.pack ()            # on ajoute l'objet à la fenêtre principale
root.mainloop ()       # on affiche enfin la fenêtre principal et on attend
                       # les événements (souris, clic, clavier)

File: chap8_interface.tex, line 79


zone_texte = Tkinter.Label (text = "zone de texte")

File: chap8_interface.tex, line 83


zone_texte = Tkinter.Label (text = "premier texte")
# ...
# pour changer de texte
zone_texte.config (text = "second texte")

File: chap8_interface.tex, line 104


zone_texte.config (state = Tkinter.DISABLED)

File: chap8_interface.tex, line 108


zone_texte.config (state = Tkinter.NORMAL)

File: chap8_interface.tex, line 127


bouton = Tkinter.Button (text = "zone de texte")

File: chap8_interface.tex, line 131


bouton = Tkinter.Button (text = "premier texte")
# ...
# pour changer de texte
bouton.config (text = "second texte")

File: chap8_interface.tex, line 153


bouton.config (state = Tkinter.DISABLED)

File: chap8_interface.tex, line 157


bouton.config (state = Tkinter.NORMAL)

File: chap8_interface.tex, line 167


b = Tkinter Button ()
im = Tkinter.PhotoImage (file = "chameau.gif")
b.config (image = im)

File: chap8_interface.tex, line 192


saisie = Tkinter.Entry ()

File: chap8_interface.tex, line 196


# le premier paramètre est la position
# où insérer le texte (second paramètre)
saisie.insert (pos, "contenu")

File: chap8_interface.tex, line 202


contenu = saisie.get ()

File: chap8_interface.tex, line 206


# supprime le texte entre les positions pos1, pos2
saisie.delete (pos1, pos2)

File: chap8_interface.tex, line 211


saisie.delete (0, len (saisie.get ()))

File: chap8_interface.tex, line 234


saisie = Tkinter.Text ()

File: chap8_interface.tex, line 238


# le premier paramètre est la position
# où insérer le texte (second paramètre)
pos = "0.0"
saisie.insert (pos, "première ligne\nseconde ligne")

File: chap8_interface.tex, line 245


# retourne le texte entre deux positions
pos1 = "0.0"
pos2 = "end"  # ou Tkinter.END
contenu = saisie.get (pos1, pos2)

File: chap8_interface.tex, line 252


# supprime le texte entre les positions pos1, pos2
saisie.delete (pos1, pos2)

File: chap8_interface.tex, line 257


saisie.delete ("0.0", "end")
# on peut aussi utiliser 
# saisie.delete ("0.0", Tkinter.END)

File: chap8_interface.tex, line 267


# modifie les dimensions de la zone
# width <--> largeur
# height <--> hauteur en lignes
saisie.config (width = 10, height = 5)

File: chap8_interface.tex, line 306


# crée un objet entier pour récupérer la valeur de la case à cocher,
# 0 pour non cochée, 1 pour cochée
v    = Tkinter.IntVar ()
case = Tkinter.Checkbutton (variable = v)

File: chap8_interface.tex, line 315


v.get ()  # égal à 1 si la case est cochée, 0 sinon

File: chap8_interface.tex, line 321


case.select ()      # pour cocher
case.deselect ()    # pour décocher

File: chap8_interface.tex, line 327


case.config (text = "case à cocher")

File: chap8_interface.tex, line 362


# crée un objet entier partagé pour récupérer le numéro du bouton radio activé
v     = Tkinter.IntVar ()
case1 = Tkinter.Radiobutton (variable = v, value = 10)
case2 = Tkinter.Radiobutton (variable = v, value = 20)
case3 = Tkinter.Radiobutton (variable = v, value = 30)

File: chap8_interface.tex, line 370


v.get ()  #  retourne le numéro du bouton radio coché (ici, 10, 20 ou 30)

File: chap8_interface.tex, line 374


v.set (numero)  # numéro du bouton radio à cocher
                # pour cet exemple, 10, 20 ou 30

File: chap8_interface.tex, line 379


case1.config (text = "premier bouton")
case2.config (text = "second bouton")
case3.config (text = "troisième bouton")

File: chap8_interface.tex, line 417


li  = Tkinter.Listbox ()

File: chap8_interface.tex, line 423


# modifie les dimensions de la liste
# width <--> largeur
# height <--> hauteur en lignes
li.config (width = 10, height = 5)

File: chap8_interface.tex, line 432


pos = 0   # un entier, "end" ou Tkinter.END pour insérer ce mot à la fin
li.insert (pos, "première ligne")

File: chap8_interface.tex, line 439


pos1 = 0    # un entier
pos2 = None # un entier, "end" ou Tkinter.END pour supprimer tous les éléments
            # de pos1 jusqu'au dernier
li.delete (pos1, pos2 = None)

File: chap8_interface.tex, line 448


pos1 = 0
li.select_set (pos1, pos2 = None)
# sélectionne tous les éléments entre les indices pos1 et 
# pos2 inclus ou seulement celui d'indice pos1 si pos2 == None

File: chap8_interface.tex, line 457


pos1 = 0
li.select_clear (pos1, pos2 = None)
# retire la sélection de tous les éléments entre les indices 
# pos1 et pos2 inclus ou seulement celui d'indice pos1 si pos2 == None

File: chap8_interface.tex, line 466


sel = li.curselection ()

File: chap8_interface.tex, line 472


for i in range (0,li.size ()) :
    print li.get (i)

File: chap8_interface.tex, line 492


frame      = Tkinter.Frame (parent)
scrollbar  = Tkinter.Scrollbar (frame)
li         = Tkinter.Listbox (frame, width = 88, height = 6, \
                              yscrollcommand = scrollbar.set)
scrollbar.config (command = li.yview)
li.pack (side = Tkinter.LEFT)
scrollbar.pack (side = Tkinter.RIGHT, fill = Tkinter.Y)

File: chap8_interface.tex, line 508


li = Tkinter.Listbox (frame, width = 88, height = 6, exportselection=0)

liste avec barre de défilement

# coding: latin-1
import tkinter as Tk
root = Tk.Tk ()

o = Tk.ScrolledListBox (root)
for k in range (0,100) : o.listbox.insert (Tk.END, "ligne " + str (k))
o.pack ()

def print_file () :                     # voir chapitre sur les événements
    print (o.listbox.selection_get ())  # idem 

b = Tk.Button (root, text = "print")    
b.config (command = print_file)         # idem 
b.pack ()

root.mainloop ()                        # idem 

liste \codesindex{ComboBox

# coding: latin-1
import tkinter as Tk
root = Tk.Tk ()

o = Tk.ComboBox (root, label = "label")
o.insert (Tk.END, "ligne 1")
o.insert (Tk.END, "ligne 2")
o.insert (Tk.END, "ligne 3")
o.insert (Tk.END, "ligne 4")
o.pack ()

def print_file () :                     # voir le chapitre sur les événéments
    print (o.cget ("value"))            # idem

b = Tk.Button (root, text = "print")
b.config (command = print_file)         # idem
b.pack ()

root.mainloop ()                        # idem

File: chap8_interface.tex, line 552


ca  = Tkinter.Canvas ()

File: chap8_interface.tex, line 556


# modifie les dimensions du canevas
# width <--> largeur en pixels
# height <--> hauteur en pixels
ca.config (width = 10, height = 5)

File: chap8_interface.tex, line 563


  # dessine deux lignes du point 10,10 au point 40,100 et au point 200,60
  # de couleur bleue, d'épaisseur 2
ca.create_line (10,10,40,100, 200,60, fill = "blue", width = 2)
  # dessine une courbe du point 10,10 au point 200,60
  # de couleur rouge, d'épaisseur 2, c'est une courbe de Bézier
  # pour laquelle le point  40,100 sert d'assise
ca.create_line (10,10, 40,100, 200,60, smooth=1, fill = "red", width = 2)
  # dessine un rectangle plein de couleur jaune, de bord noir et d'épaisseur 2
ca.create_rectangle (300,100,60,120, fill = "gray", width = 2)
  # écrit du texte de couleur noire au point 80,80 et avec la police arial
ca.create_text (80,80, text = "écrire", fill = "black", font = "arial")

File: chap8_interface.tex, line 592


widget.config (state = Tkinter.DISABLED) # grisé
widget.config (state = Tkinter.NORMAL)   # aspect normal

File: chap8_interface.tex, line 598


l = Tkinter.Label (text = "légende")

File: chap8_interface.tex, line 604


l = Tkinter.Label ()
l.config (text = "légende")

File: chap8_interface.tex, line 611


Help on method configure in module Tkinter:

configure(self, cnf=None, **kw) unbound Tkinter.Label method
    Configure resources of a widget.
    
    The values for resources are specified as keyword
    arguments. To get an overview about
    the allowed keyword arguments call the method keys.

File: chap8_interface.tex, line 624


__init__(self, master=None, cnf={}, **kw) unbound Tkinter.Label method
    Construct a label widget with the parent MASTER.
    
    STANDARD OPTIONS
    
        activebackground, activeforeground, anchor,
        background, bitmap, borderwidth, cursor,
        disabledforeground, font, foreground,
        highlightbackground, highlightcolor,
        highlightthickness, image, justify,
        padx, pady, relief, takefocus, text,
        textvariable, underline, wraplength
    
    WIDGET-SPECIFIC OPTIONS
    
        height, state, width

File: chap8_interface.tex, line 664


l = Tkinter.Label (text = "première ligne")
l.pack ()
s = Tkinter.Entry ()
s.pack ()
e = Tkinter.Label (text = "seconde ligne")
e.pack ()

File: chap8_interface.tex, line 686


l = Tkinter.Label (text = "première ligne")
l.pack (side = Tkinter.RIGHT)
s = Tkinter.Entry ()
s.pack (side = Tkinter.RIGHT)
e = Tkinter.Label (text = "seconde ligne")
e.pack (side = Tkinter.RIGHT)

File: chap8_interface.tex, line 711


s.pack_forget ()  # disparition
s.pack ()         # insertion à un autre endroit

File: chap8_interface.tex, line 723


l = Tkinter.Label (text = "première ligne")
l.grid (column = 0, row = 0)
s = Tkinter.Entry ()
s.grid (column = 0, row = 1)
e = Tkinter.Label (text = "seconde ligne")
e.grid (column = 1, row = 0)

File: chap8_interface.tex, line 757


s.grid_forget ()  # disparition

File: chap8_interface.tex, line 769


l = Tkinter.Label (text = "première ligne")
l.place (x=10,y=50)

File: chap8_interface.tex, line 784


f = Tkinter.Frame ()

File: chap8_interface.tex, line 790


l = Tkinter.Label (f, text = "première ligne")

File: chap8_interface.tex, line 796


f = Tkinter.Frame ()
l = Tkinter.Label (f, text = "première ligne")
l.pack ()                     # positionne l à l'intérieur de f
s = Tkinter.Entry (f)
s.pack ()                     # positionne s à l'intérieur de f
f.pack (side = Tkinter.LEFT)  # positionne f à l'intérieur   
                              #   de la fenêtre principale
e = Tkinter.Label (text = "seconde ligne")
e.pack_forget ()
e.pack (side = Tkinter.RIGHT) # positionne e à l'intérieur 
                              #   de la fenêtre principale

File: chap8_interface.tex, line 832


root = Tkinter.Tk ()
#  ici, on trouve le code qui définit les objets
#  et leur positionnement
root.mainloop ()

File: chap8_interface.tex, line 856


e = Tkinter.Entry ()
e.pack ()
e.focus_set ()

Tkinter, bouton

# coding: latin-1
# la première ligne autorise les accents
import Tkinter
root = Tkinter.Tk ()
b = Tkinter.Button (text = "fonction change_legende")
b.pack ()

def change_legende () :
    global b
    b.config (text = "nouvelle légende")

b.config (command = change_legende)
root.mainloop ()

File: chap8_interface.tex, line 951



w.bind (ev, fonction)

Tkinter, fonction \codesindex{bind

import Tkinter
root = Tkinter.Tk ()
b = Tkinter.Button (text = "appuyer sur une touche")
b.pack ()

def affiche_touche_pressee (evt) :
    print "--------------------------- touche pressee"
    print "evt.char = ", evt.char
    print "evt.keysym = ", evt.keysym
    print "evt.num = ", evt.num
    print "evt.x,evt.y = ", evt.x, ",", evt.y
    print "evt.x_root,evt.y_root = ", evt.x_root, ",", evt.y_root
    print "evt.widget = ", evt.widget
    
b.bind ("<Key>", affiche_touche_pressee)
b.bind ("<Button-1>", affiche_touche_pressee)
b.bind ("<Motion>", affiche_touche_pressee)
b.focus_set ()

root.mainloop ()

File: chap8_interface.tex, line 1020


evt.char =  ??
evt.keysym =  ??
evt.num =  1
evt.x,evt.y =  105 , 13
evt.x_root,evt.y_root = 
               292 , 239
evt.widget =  .9261224

File: chap8_interface.tex, line 1032


evt.char =  
evt.keysym =  Return
evt.num =  ??
evt.x,evt.y =  105 , 13
evt.x_root,evt.y_root = 
               292 , 239
evt.widget =  .9261224

File: chap8_interface.tex, line 1061


b.bind ("<button-1>", affiche_touche_pressee)

File: chap8_interface.tex, line 1067


Traceback (most recent call last):
  File "exemple_bind.py", line 17, in ?
    b.bind ("<button-1>", affiche_touche_pressee)
  File "c:\python26\lib\lib-tk\Tkinter.py", line 933, in bind
    return self._bind(('bind', self._w), sequence, func, add)
  File "c:\python26\lib\lib-tk\Tkinter.py", line 888, in _bind
    self.tk.call(what + (sequence, cmd))
_tkinter.TclError: bad event type or keysym "button"

File: chap8_interface.tex, line 1083


b.bind_all ("<Button-1>", affiche_touche_pressee)

File: chap8_interface.tex, line 1097



w.unbind (ev)
w.unbind_all (ev)

File: chap8_interface.tex, line 1132


m = Tkinter.Menu ()

File: chap8_interface.tex, line 1136


root.config (menu = m)

File: chap8_interface.tex, line 1140


mainmenu  = Tkinter.Menu ()
msousmenu = Tkinter.Menu ()
mainmenu.add_cascade (label = "sous-menu 1", menu = msousmenu)

File: chap8_interface.tex, line 1146


def fonction1 () :
    ....
m = Tkinter.Menu ()
mainmenu.add_command (label = "fonction 1", command = fonction1)

Tkinter, menu

import tkinter as Tkinter
root = Tkinter.Tk ()

e = Tkinter.Text (width = 50, height = 10)
e.pack ()

m = Tkinter.Menu ()

sm1 = Tkinter.Menu ()
sm2 = Tkinter.Menu ()

m.add_cascade (label = "sous-menu 1", menu = sm1)
m.add_cascade (label = "sous-menu 2", menu = sm2)

nb = 0

def affiche () : print ("fonction affiche")
def calcul () : print ("fonction calcul ", 3 * 4)
def ajoute_bouton () :
    global nb
    nb += 1
    b = Tkinter.Button (text = "bouton " + str (nb))
    b.pack ()

sm1.add_command (label = "affiche",       command = affiche)
sm1.add_command (label = "calcul",        command = calcul)
sm2.add_command (label = "ajoute_bouton", command = ajoute_bouton)
sm2.add_command (label = "fin",           command = root.destroy)

root.config (menu = m, width = 200)
root.title ("essai de menu")
#help (Tkinter.Tk)
root.mainloop ()

File: chap8_interface.tex, line 1169


m = Tkinter.Menu ()
m.add_command (...)
m.delete (1, 2) # supprime le second intitulé
                # supprime les intitulés compris entre 1 et 2 exclu

File: chap8_interface.tex, line 1180


import Tkinter
root = Tkinter.Tk ()
Tkinter.Button (text = "fin", command = root.destroy).pack ()
root.mainloop ()

File: chap8_interface.tex, line 1213


import Tkinter
win = Tkinter.Toplevel ()
win.mainloop ()

File: chap8_interface.tex, line 1221


# zone_texte appartient à la fenêtre principale
zone_texte = Tkinter.Label (text = "premier texte")

File: chap8_interface.tex, line 1226


# zone_texte appartient à la fenêtre top
top = Tkinter.Toplevel ()
zone_texte = Tkinter.Label (top, text = "premier texte")

plusieurs fenêtre \codesindex{Toplevel

# coding: latin-1
import Tkinter

class nouvelle_fenetre :
    resultat = []
    def top (self) :
        sec = Tkinter.Toplevel ()
        Tkinter.Label (sec, text="entrer quelque chose").pack ()
        saisie = Tkinter.Entry (sec)
        saisie.pack()
        Tkinter.Button (sec, text = "valider", command = sec.quit).pack ()
        sec.mainloop ()
        nouvelle_fenetre.resultat.append ( saisie.get () )
        sec.destroy ()

root = Tkinter.Tk() #fenetre principale
a = Tkinter.Button (text    = "fenêtre Toplevel", 
                    command = nouvelle_fenetre ().top)
a.pack()
root.mainloop()

for a in nouvelle_fenetre.resultat :
    print "contenu ", a

sélection d'un fichier

import Tix as Tk
root = Tk.Tk ()

def command_print () : print box.cget("value")

box = Tk.FileSelectBox (root)
box.config (directory="c:\\")
box.pack ()
Tk.Button (root, text = "print", command = command_print).pack ()

root.mainloop ()

Tkinter, compte à rebours

import Tkinter
root = Tkinter.Tk ()
l = Tkinter.Label (text = "0 secondes")
l.pack ()
sec = 0
id = None

def change_legende() :
    global l
    global sec
    global id
    sec += 1
    l.config (text = "%d secondes" % sec)
    id = l.after (1000, change_legende)

l.after (1000, change_legende)

root.mainloop ()

File: chap8_interface.tex, line 1294


l.after_cancel (id)

\codesindex{Listbox

# coding: latin-1
import Tkinter

class MaListbox (Tkinter.Listbox) :
    def __init__ (self, master = None, cnf={}, **kw) :
        Tkinter.Listbox.__init__ (self, master, cnf, **kw)  
        self.bind ("<Motion>", self.mouvement)
        self.pos = None  # mémoire l'ancienne position du curseur
    def mouvement (self, ev) :
        pos = self.nearest (ev.y)  # nouvelle position du curseur
        if pos < 0 or pos >= self.size () : return
        if self.pos != pos :
            if self.pos != None : self.itemconfigure(self.pos, bg='')
            self.itemconfigure (pos, bg='gray')
            self.pos = pos

root = Tkinter.Tk ()
b = MaListbox ()
b.insert ("end", "ligne 1")
b.insert ("end", "ligne 2")
b.insert ("end", "ligne 3")
b.pack ()
b.focus_set ()
root.mainloop ()

Tkinter avec des classes

# coding: latin-1
import Tkinter as Tk

class MaFenetre :
    def __init__ (self, win) :
        self.win = win
        self.creation ()
        
    def creation (self) :
        b1 = Tk.Button (self.win, text="bouton 1", command=self.commande_bouton1)
        b2 = Tk.Button (self.win, text="bouton 2", command=self.commande_bouton2)
        b3 = Tk.Button (self.win, text="disparition", command=self.disparition)
        b1.grid (row=0, column=0)
        b2.grid (row=0, column=1)
        b3.grid (row=0, column=2)
        self.lab = Tk.Label (self.win, text = "-")
        
    def commande_bouton1 (self) :
        # on déplace l'objet lab de type Label
        self.lab.configure (text = "bouton 1 appuyé")
        self.lab.grid (row = 1, column = 0)
        
    def commande_bouton2 (self) :
        # on déplace l'objet lab de type Label
        self.lab.configure (text = "bouton 2 appuyé")
        self.lab.grid (row = 1, column = 1)
        
    def disparition (self) :
        # on fait disparaître l'objet lab de type Label
        self.lab.grid_forget ()
    
if __name__ == "__main__" :
    root = Tk.Tk ()
    f = MaFenetre (root)
    root.mainloop ()

File: chap8_interface.tex, line 1332


root = Tk.Tk ()
f = Tk.Frame ()
f.pack ()
MaFenetre (f)      # première instance
g = Tk.Frame ()
g.pack ()
MaFenetre (g)      # seconde instance
root.mainloop ()

Tkinter, séquence d'événements

# coding: latin-1
import Tkinter as Tk

class MaFenetreSeq :
    def __init__ (self, win) :
        self.win = win
        self.creation ()
        self.sequence = []
        
    def creation (self) :
        b1 = Tk.Button (self.win, text="bouton 1", command=self.commande_bouton1)
        b2 = Tk.Button (self.win, text="bouton 2", command=self.commande_bouton2)
        b3 = Tk.Button (self.win, text="remise à zéro", command=self.zero)
        b1.grid (row=0, column=0)
        b2.grid (row=0, column=1)
        b3.grid (row=0, column=2)
        self.lab = Tk.Label (self.win, text = "-")
        
    def commande_bouton1 (self) :
        # ajoute 1 à la liste self.sequence
        self.sequence.append (1)
        self.controle ()
        
    def commande_bouton2 (self) :
        # ajoute 2 à la liste self.sequence
        self.sequence.append (2)
        self.controle ()
        
    def zero (self) :
        # on vide la liste self.sequence
        self.sequence = []
        self.lab.grid_forget ()
        
    def controle (self) :
        # on compare la liste sequence à [1,2,1] et [2,2,1,1]
        # dans ce cas, on fait apparaître l'objet lab
        l = len (self.sequence)
        if l >= 3 and self.sequence [l-3:] == [1,2,1] :
            self.lab.configure (text = "séquence 1 2 1")
            self.lab.grid (row = 1, column = 0)
        elif l >= 4 and self.sequence [l-4:] == [2,2,1,1] :
            self.lab.configure (text = "séquence 2 2 1 1")
            self.lab.grid (row = 1, column = 1)
    
if __name__ == "__main__" :
    root = Tk.Tk ()
    f = MaFenetreSeq (root)
    root.mainloop ()

utilisation de messages personnalisés

# coding: latin-1
import Tkinter
def affiche_touche_pressee () : root.event_generate ("<<perso>>", rooty = -5)
def perso (evt) : print "perso", evt.y_root
root = Tkinter.Tk ()
b = Tkinter.Button (text = "clic", \
                    command = affiche_touche_pressee)
b.pack ()
root.bind ("<<perso>>", perso)  # on intercepte un événement personnalisé
root.mainloop ()

premier thread

# coding: cp1252
import threading, time

class MonThread (threading.Thread) :
    def __init__ (self, jusqua) :      # jusqua = donnée supplémentaire
        threading.Thread.__init__(self)# ne pas oublier cette ligne 
                                       # (appel au constructeur de la classe mère)
        self.jusqua = jusqua           # donnée supplémentaire ajoutée à la classe
        
    def run (self) :
        for i in range (0, self.jusqua) :
            print "thread ", i
            time.sleep (0.1)    # attend 100 millisecondes sans rien faire
                                # facilite la lecture de l'affichage
        
m = MonThread (1000)        # crée le thread
m.start ()                  # démarre le thread, 
                            # l'instruction est exécutée en quelques millisecondes
                            # quelque soit la durée du thread

for i in range (0,1000) :
    print "programme ", i
    time.sleep (0.1)            # attend 100 millisecondes sans rien faire
                                # facilite la lecture de l'affichage

File: chap9_thread.tex, line 59


programme  0
thread  0
thread  1
programme  1
thread  2
programme  2
programme  3
thread  3
programme  4
thread  4
...

deux threads secondaires

# coding: cp1252
import threading, time

class MonThread (threading.Thread) :
    def __init__ (self, jusqua, s) :
        threading.Thread.__init__ (self)
        self.jusqua = jusqua
        self.s = s
        
    def run (self) :
        for i in range (0, self.jusqua) :
            print "thread ", self.s, " : ", i
            time.sleep (0.1)
        
m = MonThread (1000, "A")
m.start ()

m2 = MonThread (1000, "B")  # crée un second thread
m2.start ()                 # démarre le thread, 

for i in range (0,1000) :
    print "programme ", i
    time.sleep (0.1)

File: chap9_thread.tex, line 82


thread  A  :  0
programme  0
thread  B  :  0
thread  A  :  1
thread  B  :  1
programme  1
thread  B  :  2
thread  A  :  2
...

(1)

# coding: latin-1
import threading, time

class MonThread (threading.Thread) :
    def __init__ (self, jusqua) :
        threading.Thread.__init__ (self)
        self.jusqua = jusqua
        self.etat = False       # l'état du thread est soit False (à l'arrêt)
                                # soit True (en marche)
        
    def run (self) :
        self.etat = True                        # on passe en mode marche
        for i in range (0, self.jusqua) :
            print "thread itération ", i
            time.sleep (0.1)
        self.etat = False                       # on revient en mode arrêt
        
m = MonThread (10)          # crée un thread
m.start ()                  # démarre le thread, 

print "début"

while m.etat == False :
    # on attend que le thread démarre
    time.sleep (0.1)  # voir remarque ci-dessous
    
while m.etat == True :
    # on attend que le thread s'arrête
    # il faut introduire l'instruction time.sleep pour temporiser, il n'est pas 
    # nécessaire de vérifier sans cesse que le thread est toujours en marche
    # il suffit de le vérifier tous les 100 millisecondes
    # dans le cas contraire, la machine passe son temps à vérifier au lieu
    # de se consacrer à l'exécution du thread
    time.sleep (0.1)
    
print "fin"

(2)

# coding: latin-1
import threading, time

class MonThread (threading.Thread) :
    def __init__ (self, jusqua, event) :    # event = objet Event
        threading.Thread.__init__ (self)    #       = donnée supplémentaire
        self.jusqua = jusqua                
        self.event  = event                 # on garde un accès à l'objet Event
        
    def run (self) :
        for i in range (0, self.jusqua) :
            print "thread itération ", i
            time.sleep (0.1)
        self.event.set ()                   # on indique qu'on a fini : 
                                            # on active l'object self.event
print "début"
        
event = threading.Event ()       # on crée un objet de type Event
event.clear ()                   # on désactive l'ojet Event
m = MonThread (10, event)        # crée un thread
m.start ()                       # démarre le thread, 
event.wait ()                    # on attend jusqu'à ce que l'objet soit activé
                                 # event.wait (0.1) : n'attend qu'un
print "fin"                      #          seulement 1 dizième de seconde

File: chap9_thread.tex, line 136


m.start ()
while not event.isSet ():
    print "j'attends"
    event.wait (0.1)
print "fin"

partager des données

# coding: latin-1
import threading, time

message = ""
verrou  = threading.Lock ()

def ajoute (c) :
    global message     # message et verrou sont des variables gloables
    global verrou      # pour ne pas qu'elle disparaisse dès la fin de la fonction
    verrou.acquire ()  # on protège ce qui suit  (*)
    
    s = message + c    # instructions jamais exécutée simultanément par 2 threads
    time.sleep (0.001) # time.sleep : pour exagérer le défaut de synchronisation
    message = s        # si verrou n'est pas utilisé
    
    verrou.release ()  # on quitte la section protégée  (*)

class MonThread (threading.Thread) :
    def __init__ (self, jusqua, event, s) :
        threading.Thread.__init__ (self)
        self.jusqua = jusqua 
        self.s      = s
        self.event  = event
        
    def run (self) :
        for i in range (0, self.jusqua) :
            ajoute (self.s)
            time.sleep (0.003)
        self.event.set ()
        
print "début"

# synchronisation attente
e1 = threading.Event ()
e2 = threading.Event ()
e1.clear ()
e2.clear ()

m1 = MonThread (10, e1, "1")     # crée un thread
m1.start ()                      # démarre le thread, 
m2 = MonThread (10, e2, "2")     # crée un second thread
m2.start ()                      # démarre le second thread, 

e1.wait ()
e2.wait ()

print "longueur ", len(message) # affiche 20
print "message = ", message     # affiche quelque chose comme 12212112211212121221

thread et interface graphique

# coding: latin-1
import threading, time, random, copy

# définition du thread
class MonThread (threading.Thread) :
    def __init__ (self, win, res) :
        threading.Thread.__init__ (self)
        self.win = win  # on mémorise une référence sur la fenêtre
        self.res = res
        
    def run (self) :
        for i in range (0, 10) :
            print "thread ", i
            time.sleep (0.1)
            
          # afin que le thread retourne un résultat
          # self.res désigne thread_resultat qui reçoit un nombre de plus
        h = random.randint (0,100)
        self.res.append (h)    
        
          # on lance un événement <<thread_fini>> à la fenêtre principale 
          # pour lui dire que le thread est fini, l'événement est ensuite 
          # géré par la boucle principale de messages
          # on peut transmettre également le résultat lors de l'envoi du message
          # en utilisant un attribut de la classe Event pour son propre compte
        self.win.event_generate ("<<thread_fini>>", x = h)
    
thread_resultat = []

def lance_thread () :
    global thread_resultat
      # fonction appelée lors de la pression du bouton
      # on change la légnde de la zone de texte
    text .config (text = "thread démarré")
    text2.config (text = "thread démarré")
      # on désactive le bouton pour éviter de lancer deux threads en même temps
    bouton.config (state = TK.DISABLED)
      # on lance le thread
    m = MonThread (root, thread_resultat)
    m.start ()
    
def thread_fini_fonction (e) :
    global thread_resultat
      # fonction appelée lorsque le thread est fini
    print "la fenêtre sait que le thread est fini"
      # on change la légende de la zone de texte
    text .config (text = "thread fini + résultat " + str (thread_resultat))
    text2.config (text = "thread fini + résultat (e.x) " + str (e.x))
      # on réactive le bouton de façon à pouvoir lancer un autre thread
    bouton.config (state = TK.NORMAL)

import Tkinter as TK

# on crée la fenêtre
root   = TK.Tk ()
bouton = TK.Button (root, text = "thread départ", command = lance_thread)
text   = TK.Label (root, text = "rien")
text2  = TK.Label (root, text = "rien")
bouton.pack ()
text.pack ()
text2.pack ()

# on associe une fonction à un événement <<thread_fini>> propre au programme
root.bind ("<<thread_fini>>", thread_fini_fonction)

# on active la boucle principale de message
root.mainloop ()

joueurs asynchrones

# coding: latin-1
import threading, time, Queue, random

class Joueur (threading.Thread) :
    
    # initialisation
    def __init__ (self, nom, e, nb = 1000, temps = 0.1) :
        threading.Thread.__init__(self)
        self.nb    = nb
        self.queue = Queue.Queue ()
        self.nom   = nom
        self.event = e
        self.temps = temps  # temps de réflexion
    def Joueur (self, autre_joueur) : self.autre = autre_joueur
        
    # méthodes : l'adversaire m'envoie un message
    def Joue    (self, nombre) : self.queue.put_nowait ( ("essai", nombre) )
    def Dessus  (self, nombre) : self.queue.put_nowait ( ("dessus", nombre) )
    def Dessous (self, nombre) : self.queue.put_nowait ( ("dessous", nombre) )
    def Gagne   (self, nombre) : 
        while not self.queue.empty () :
            try :self.queue.get ()
            except : pass
        self.queue.put ( ("gagne", nombre) )
              
    # je joue
    def run (self) :
        x = random.randint (0,self.nb)
        print self.nom, " : je joue (", x, ")"
        i = 0
        a = 0
        b = self.nb
        while True :
            time.sleep (self.temps)
            
            try : 
                m,n = self.queue.get_nowait ()       # désynchronisé
                #m,n = self.queue.get (timeout = 0.5)# l'un après l'autre
            except Queue.Empty : m,n = None,None
                
            # traitement du message --> réponse à l'adversaire
            if m == "essai" :
                if n == x : 
                    self.autre.Gagne (n)
                    print self.nom, " : j'ai perdu après ", i, " essais"
                    break
                elif n < x : self.autre.Dessus  (n)
                else       : self.autre.Dessous (n)
            elif m == "dessus" :  
                a = max (a, n+1)
                continue  # assure l'équité en mode l'un après l'autre
            elif m == "dessous" : 
                b = min (b, n-1)
                continue  # assure l'équité en mode l'un après l'autre
            elif m == "gagne" :
                print self.nom, " : j'ai gagné en ", i, " essais, solution ", n
                break

            # on fait une tentative
            if a == b : n = a
            else : n = random.randint (a,b)
            self.autre.Joue (n)
            i += 1
            print self.nom, " : je tente ", n, " écart ", b-a, \
                  " à traiter ", self.queue.qsize ()

        # fini
        print self.nom, " : j'arrête"
        self.event.set ()
        
# on crée des verrous pour attendre la fin de la partie        
e1 = threading.Event ()
e2 = threading.Event ()
e1.clear ()
e2.clear ()

# création des joueurs
A = Joueur ("A", e1, 1000, temps = 0.1)
B = Joueur ("B", e2, 1000, temps = 0.3)

# chaque joueur sait qui est l'autre
A.Joueur (B)
B.Joueur (A)

# le jeu commence
A.start ()
B.start ()

# on attend la fin de la partie
e1.wait ()
e2.wait ()

File: chap9_thread.tex, line 274


A  : je joue ( 8 )
B  : je joue ( 569 )
A  : je tente  42  écart  1000  à traiter  0
A  : je tente  791  écart  1000  à traiter  0
...
A  : je tente  528  écart  62  à traiter  0
B  : je tente  20  écart  43  à traiter  57
A  : je tente  508  écart  62  à traiter  0
A  : je tente  548  écart  62  à traiter  0
B  : je tente  8  écart  43  à traiter  59
A  : j'ai perdu après  67  essais
A  : j'arrête
B  : j'ai gagné en  23  essais, solution  8
B  : j'arrête

File: montant_num.tex, line 35


import string
s = "dix-neuf"

l = s.replace ("-", " ")
l = string.replace ("-", " ")

File: montant_num_cor.tex, line 10


# coding: latin-1
def lire_separation(s):
    """divise un nombre littéral en mots"""
    s = s.replace ("-", " ")     # on remplace les tirets par des espaces
                                 # pour découper en mots même
                                 # les mots composés
    return s.split ()

File: montant_num_cor.tex, line 24


import re
def lire_separation(s):
    """divise un nombre littéral en mots avec les expressions régulières"""
    return re.compile ("[- ]").split (s)

File: montant_num_cor.tex, line 35


def valeur_mot (s) :
    """convertit numériquement les nombres inclus entre 0 et 16 inclus,
    20, 30, 40, 50, 60, s est une chaîne de caractères, le résultat est entier"""
    if   s == "zéro"      : return 0
    elif s == "un"        : return 1
    elif s == "deux"      : return 2
    elif s == "trois"     : return 3
    elif s == "quatre"    : return 4
    elif s == "cinq"      : return 5
    elif s == "six"       : return 6
    elif s == "sept"      : return 7
    elif s == "huit"      : return 8
    elif s == "neuf"      : return 9
    elif s == "dix"       : return 10
    elif s == "onze"      : return 11
    elif s == "douze"     : return 12
    elif s == "treize"    : return 13
    elif s == "quatorze"  : return 14
    elif s == "quinze"    : return 15
    elif s == "seize"     : return 16
    elif s == "vingt"     : return 20
    elif s == "trente"    : return 30
    elif s == "quarante"  : return 40
    elif s == "cinquante" : return 50
    elif s == "soixante"  : return 60
    else                  : return 0      # ce cas ne doit normalement pas 
                                          # se produire

File: montant_num_cor.tex, line 69


def valeur_mot (s) :
    dico = {'cinquante': 50, 'quarante': 40, 'onze': 11, 'huit': 8, 'six': 6, \
            'quinze': 15, 'trente': 30, 'douze': 12, 'cinq': 5, 'deux': 2, \
            'quatorze': 14, 'neuf': 9, 'soixante': 60, 'quatre': 4, \
            'zéro': 0, 'treize': 13, 'trois': 3, 'seize': 16, \
            'vingt': 20, 'un': 1, 'dix': 10, 'sept': 7}
    if s not in dico : return 0   # cas imprévu, on peut résumer ces deux lignes
    else : return dico [s]        # par return dico.get (s, 0)

File: montant_num_cor.tex, line 85


def lire_dizaine_liste(s):
    """convertit une liste de chaînes de caractères dont
    juxtaposition forme un nombre littéral compris entre 0 et 99"""
    r       = 0         # contient le résultat final
    dizaine = False     # a-t-on terminé le traitement des dizaines ?
    for mot in s:
        n = lire_unite (mot)
        if n == 20 :
            if not dizaine and r > 0 and r != 60 :
                r       *= n     # cas 80
                dizaine  = True
            else : r += n
        else : r += n
    return r

File: montant_num_cor.tex, line 106


def lire_dizaine(s):
    li = lire_separation (s)
    return lire_dizaine_liste (li)

File: montant_num_cor.tex, line 116


def ecrit_unite (x):
    """convertit un nombre compris inclus entre 0 et 16 inclus,
    20, 30, 40, 50, 60 en une chaîne de caractères"""
    if   x == 0: return "zéro"
    elif x == 1: return "un"
    elif x == 2: return "deux"
    elif x == 3: return "trois"
    elif x == 4: return "quatre"
    elif x == 5: return "cinq"
    elif x == 6: return "six"
    elif x == 7: return "sept"
    elif x == 8: return "huit"
    elif x == 9: return "neuf"
    elif x == 10: return "dix"
    elif x == 11: return "onze"
    elif x == 12: return "douze"
    elif x == 13: return "treize"
    elif x == 14: return "quatorze"
    elif x == 15: return "quinze"
    elif x == 16: return "seize"
    elif x == 20: return "vingt"
    elif x == 30: return "trente"
    elif x == 40: return "quarante"
    elif x == 50: return "cinquante"
    elif x == 60: return "soixante"
    elif x == 70: return "soixante-dix"
    elif x == 80: return "quatre-vingt"
    elif x == 90: return "quatre-vingt-dix"
    else        : return "zéro"

File: montant_num_cor.tex, line 150


def mot_valeur (x):
    """convertit un nombre compris inclus entre 0 et 16 inclus,
    20, 30, 40, 50, 60 en une chaîne de caractères"""
    dico = {'cinquante': 50, 'quarante': 40, 'onze': 11, 'huit': 8, 'six': 6, \
            'quinze': 15, 'trente': 30, 'douze': 12, 'cinq': 5, 'deux': 2, \
            'quatorze': 14, 'neuf': 9, 'soixante': 60, 'quatre': 4, \
            'zéro': 0, 'treize': 13, 'trois': 3, 'seize': 16, \
            'vingt': 20, 'un': 1, 'dix': 10, 'sept': 7}
    inv = {}
    for k,v in dico.iteritems () : inv [v] = k
    inv [70] = "soixante-dix"
    inv [80] = "quatre-vingt"
    inv [90] = "quatre-vingt-dix"
    return inv [x]

File: montant_num_cor.tex, line 171


def ecrit_dizaine(x):
    """convertit un nombre entre 0 et 99 sous sa forme littérale"""

    if x <= 16 : return ecrit_unite(x)

    s       = ""
    dizaine = x / 10
    unite   = x % 10
    s = mot_valeur (dizaine*10)
    s += " "
    s += mot_valeur (unite)
    return s

File: montant_num_cor.tex, line 190


for i in xrange(0,100):
    s = ecrit_dizaine (i)
    j = lire_dizaine (s)
    if i != j : print "erreur ", i, " != ", j, " : ", s

conversion de montant littéral en numérique

# coding: cp1252
import string

def lire_separation(s):
    """divise un nombre littéral en mots"""
    s = string.replace (s, "-", " ")
    return string.split (s)

def lire_separation(s):
    """divise un nombre littéral en mots"""
    return re.compile ("[- ]").split (s)

def valeur_mot (s) :
    """convertit numériquement les nombres inclus entre 0 et 16 inclus,
    20, 30, 40, 50, 60, s est une chaîne de caractères, le résultat est entier"""
    if   s == "zéro"      : return 0
    elif s == "un"        : return 1
    elif s == "deux"      : return 2
    elif s == "trois"     : return 3
    elif s == "quatre"    : return 4
    elif s == "cinq"      : return 5
    elif s == "six"       : return 6
    elif s == "sept"      : return 7
    elif s == "huit"      : return 8
    elif s == "neuf"      : return 9
    elif s == "dix"       : return 10
    elif s == "onze"      : return 11
    elif s == "douze"     : return 12
    elif s == "treize"    : return 13
    elif s == "quatorze"  : return 14
    elif s == "quinze"    : return 15
    elif s == "seize"     : return 16
    elif s == "vingt"     : return 20
    elif s == "trente"    : return 30
    elif s == "quarante"  : return 40
    elif s == "cinquante" : return 50
    elif s == "soixante"  : return 60
    else                  : return 0
        
def valeur_mot (s) :
    """convertit numériquement les nombres inclus entre 0 et 16 inclus,
    20, 30, 40, 50, 60, s est une chaîne de caractères, le résultat est entier"""
    dico = {'cinquante': 50, 'quarante': 40, 'onze': 11, 'huit': 8, 'six': 6, \
            'quinze': 15, 'trente': 30, 'douze': 12, 'cinq': 5, 'deux': 2, \
            'quatorze': 14, 'neuf': 9, 'soixante': 60, 'quatre': 4, \
            'zéro': 0, 'treize': 13, 'trois': 3, 'seize': 16, \
            'vingt': 20, 'un': 1, 'dix': 10, 'sept': 7}
    if s not in dico : return 0
    else : return dico [s]

def lire_dizaine_liste(s):
    """convertit une liste de chaîne de caractères dont
    juxtaposition forme un nombre littéral compris entre
    0 et 99"""
    r       = 0         # contient le résultat final
    dizaine = False     # a-t-on terminé le traitement des dizaines ?
    for mot in s:
        n = valeur_mot (mot)
        if n == 20 :
            if not dizaine and r > 0 and r != 60:
                r       *= n     # cas 80
                dizaine  = True
            else : r += n
        else : r += n
    return r

def lire_dizaine(s):
    s2 = s.replace ("-", " ")
    li = string.split (s2)
    return lire_dizaine_liste (li)

def mot_valeur (x):
    """convertit un nombre compris inclus entre 0 et 16 inclus,
    20, 30, 40, 50, 60 en une chaîne de caractères"""
    if   x == 0: return "zéro"
    elif x == 1: return "un"
    elif x == 2: return "deux"
    elif x == 3: return "trois"
    elif x == 4: return "quatre"
    elif x == 5: return "cinq"
    elif x == 6: return "six"
    elif x == 7: return "sept"
    elif x == 8: return "huit"
    elif x == 9: return "neuf"
    elif x == 10: return "dix"
    elif x == 11: return "onze"
    elif x == 12: return "douze"
    elif x == 13: return "treize"
    elif x == 14: return "quatorze"
    elif x == 15: return "quinze"
    elif x == 16: return "seize"
    elif x == 20: return "vingt"
    elif x == 30: return "trente"
    elif x == 40: return "quarante"
    elif x == 50: return "cinquante"
    elif x == 60: return "soixante"
    elif x == 70: return "soixante-dix"
    elif x == 80: return "quatre-vingt"
    elif x == 90: return "quatre-vingt-dix"
    else        : return "zéro"
        
def mot_valeur (x):
    """convertit un nombre compris inclus entre 0 et 16 inclus,
    20, 30, 40, 50, 60 en une chaîne de caractères"""
    dico = {'cinquante': 50, 'quarante': 40, 'onze': 11, 'huit': 8, 'six': 6, \
            'quinze': 15, 'trente': 30, 'douze': 12, 'cinq': 5, 'deux': 2, \
            'quatorze': 14, 'neuf': 9, 'soixante': 60, 'quatre': 4, \
            'zéro': 0, 'treize': 13, 'trois': 3, 'seize': 16, \
            'vingt': 20, 'un': 1, 'dix': 10, 'sept': 7}
    inv = {}
    for k,v in dico.iteritems () : inv [v] = k
    inv [70] = "soixante-dix"
    inv [80] = "quatre-vingt"
    inv [90] = "quatre-vingt-dix"
    return inv [x]
    
def ecrit_dizaine(x):
    """convertit un nombre entre 0 et 99 sous sa forme littérale"""

    if x <= 16:
        return mot_valeur (x)

    s       = ""
    dizaine = x / 10
    unite   = x % 10
    s = mot_valeur (dizaine*10)
    s += " "
    s += mot_valeur (unite)
    return s
    
for i in xrange(0,100):
    s = ecrit_dizaine (i)
    j = lire_dizaine (s)
    if i != j :
        print "erreur ", i, " != ", j, " : ", s

(1)

def pion_prendre(i,j,damier):
   c = damier [i][j]
   if c == 0: return False  # case vide, impossible de prendre
   c = 3 - c                # couleur de l'adversaire

   if damier [i-1][j-1] == c :     # s'il y a un pion adverse en haut à gauche
       if damier [i-2][j-2] == 0 : # si la case d'après en diagonale est vide
           return True             # on peut prendre     

   # on répète ce test pour les trois autres cases
   if damier [i-1][j+1] == c and damier [i-2][j+2] == 0: return True
   if damier [i+1][j-1] == c and damier [i+2][j-2] == 0: return True
   if damier [i+1][j+1] == c and damier [i+2][j+2] == 0: return True
        
   # si tous les tests ont échoué, on ne peut pas prendre
   return False

(2)

def pion_prendre(i,j,damier):
   c = damier [(i,j)]       # ou encore damier [i,j]
   if c == 0: return False  # case vide, impossible de prendre
   c = 3 - c                # couleur de l'adversaire

   # test pour une prise du pion dans les quatre cases voisines
   if damier [i-1,j-1] == c and damier [i-2,j-2] == 0: return True
   if damier [i-1,j+1] == c and damier [i-2,j+2] == 0: return True
   if damier [i+1,j-1] == c and damier [i+2,j-2] == 0: return True
   if damier [i+1,j+1] == c and damier [i+2,j+2] == 0: return True
        
   # si tous les tests ont échoué, on ne peut pas prendre
   return False

(3)

def pion_prendre(i,j,damier):
   c = damier [10*i+j]
   if c == 0: return False  # case vide, impossible de prendre
   c = 3 - c                # couleur de l'adversaire

   # test pour une prise du pion dans les quatre cases voisines
   if damier [10*(i-1)+j-1] == c and damier [10*(i-2)+j-2] == 0: return True
   if damier [10*(i-1)+j+1] == c and damier [10*(i-2)+j+2] == 0: return True
   if damier [10*(i+1)+j-1] == c and damier [10*(i+2)+j-2] == 0: return True
   if damier [10*(i+1)+j+1] == c and damier [10*(i+2)+j+2] == 0: return True
        
   return False

(4)

def pion_prendre(i,j,damier):
   c = damier [i][j]
   if c == 0: return False  # case vide, impossible de prendre
   c = 3 - c                # couleur de l'adversaire

   # on répète ce test pour les trois autres cases
   if i >= 2                 and j >= 2                  and \
      damier [i-1][j-1] == c and damier [i-2][j-2] == 0: return True
   if i >= 2                 and j < len (damier)-2      and \
      damier [i-1][j+1] == c and damier [i-2][j+2] == 0: return True
      
   if i < len (damier)-2     and j >= 2                  and \
      damier [i+1][j-1] == c and damier [i+2][j-2] == 0: return True
   if i < len (damier)-2     and j < len (damier)-2      and \
      damier [i+1][j+1] == c and damier [i+2][j+2] == 0: return True
        
   return False

File: partie_dames.tex, line 98


if c <= 0 : return False  # au lieu de if c == 0 : return False

File: partie_dames.tex, line 109


damier [(i-1,j-1)]   # est équivalent à    
damier [ i-1,j-1 ]   # cette ligne

File: langue_fa_cor.tex, line 12


def lit_fichier (nom) :
    f = open (nom, "r")                   # ouverture du fichier
    l = f.read ()                         # on récupère le contenu
    f.close ()                            # on ferme le fichier
    return l                              # on retourne le contenu

File: langue_fa_cor.tex, line 22


import urllib                       # import du module urllib
def lit_url (nom) : 
    f = urllib.urlopen (nom)        # on ouvre l'url
    res = f.read ()                 # on lit son contenu
    f.close ()                      # on termine la lecture
    return res                      # on retourne le résultat

File: langue_fa_cor.tex, line 32


def lit (texte) :
    if texte.startswith ("http") : s = lit_url (texte)  # Internet
    else : s = lit_fichier (texte)                      # fichier texte
    return s
    
s = lit ("hugo.txt")

File: langue_fa_cor.tex, line 43


def lit (texte) :
    try :
        s = lit_fichier (texte)            # fichier texte
        return s
    except :                               # si cela ne marche pas,
        s = lit_url (texte)                # on suppose que texte 
        return s                           # est une adresse Internet
    
s = lit ("hugo.txt")

File: langue_fa_cor.tex, line 57


def compte_lettre_count (texte) :
    texte = texte.upper ()             # pour éviter les accents
    res = { }                          # résultat, vide pour le moment
    for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" :  # pour tout l'alphabet
        res [c] = texte.count (c)      # on compte les occurrences de c
    return res

File: langue_fa_cor.tex, line 68


def compte_lettre (texte) :
    texte = texte.upper ()              # pour éviter les accents
    res = { }                           # résultat, vide pour le moment
    for c in texte :                    # pour tous les caractères du texte
        if not("A" <= c <= "Z") : continue # si ce n'est pas une lettre, on passe
        if c not in res : res [c] = 1   # si elle n'est pas là, on lui affecte 1
        else : res [c] += 1        # sinon, on augmente son nombre d'apparitions
    return res    

File: langue_fa_cor.tex, line 83


def comparaison () :
    s = lit_fichier ("hugo.txt")
    compte_lettre_count (s)      # on ne mémorise pas les résultats
    compte_lettre (s)            # car on souhaite mesurer le temps passé

import profile                   # import du module profile
profile.run ("comparaison()")    # mesure du temps passé dans la fonction 
                                 # comparaison et les fonctions qu'elle appelle

File: langue_fa_cor.tex, line 96


ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.160    0.160    0.174    0.174 langue.py:19(compte_lettre)
     1    0.000    0.000    0.017    0.017 langue.py:31(compte_lettre_count)
     1    0.000    0.000    0.190    0.190 langue.py:43(comparaison)

File: langue_fa_cor.tex, line 117


ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.120    0.120    0.133    0.133 langue.py:19(compte_lettre)
     1    0.002    0.002    0.082    0.082 langue.py:32(compte_lettre_count)

File: langue_fa_cor.tex, line 143


def compte_lettre (texte) :
    # ...
    s = sum (res.values ())
    for k in res :
        res [k] = float (res [k]) / s
    return res

File: langue_fa_cor.tex, line 169


# le dernier jour d'un condamné
c1 = compte_lettre (lit_url ("http://www.gutenberg.org/dirs/etext04/8ldrj10.txt"))
# the man who laughs
c2 = compte_lettre (lit_url ("http://www.gutenberg.org/files/12587/12587-8.txt"))

car = c1.keys ()
car.sort ()
for k in car :
    print k, " : ", "% 2.2f" % (c1 [k] * 100), "%", " % 2.2f" % (c2 [k] * 100), "%"

File: langue_fa_cor.tex, line 184


def langue_lettre (texte) :
    if "http" in texte : s = lit_url (texte)   # cas URL
    else : s = lit_fichier (texte)             # cas fichier
    c = compte_lettre (s)                      # on compte les lettres
    return c ["W"], c ["H"]                    # on retourne deux fréquences

File: langue_fa_cor.tex, line 194


def langue_lettre (texte) :
    ...                                        # lignes inchangées
    return c.get ("W", 0.0), c.get ("H", 0.0)  # on retourne deux fréquences

File: langue_fa_cor.tex, line 202


def curve (li) :
    cx,cy = [], []
    for l in li :                 # pour tous les textes de la liste
        x,y = langue_lettre (l)   # coordonnées d'un texte, fréquence W et H
        cx.append (x)             # on ajoute x à la liste des abscisses
        cy.append (y)             # on ajoute y à la liste des ordonnées
    return cx,cy

File: langue_fa_cor.tex, line 215


frcx,frcy = curve (fr)          # on récupère les coordonnées des textes français
encx,ency = curve (en)          # on récupère les coordonnées des textes anglais

import pylab                         # import du module matplotlib
pylab.plot (frcx, frcy, "rx",ms=10,\ 
                            mew=2.5) # on trace la courbe des textes français  
pylab.plot (encx, ency, "bv")        # on trace la courbe des textes anglais
pylab.legend (("francais", "anglais"), loc=2)  # légende (sans accent)
pylab.title ("langue")               # titre
pylab.xlabel ("frequence de W")      # légende de l'axe des abscisses
pylab.ylabel ("frequence de H")      # légende de l'axe des ordonnées
pylab.savefig ("graphe.png")         # enregistrement sous forme d'image
pylab.show ()                        # on fait apparaître le graphique

File: langue_fa_cor.tex, line 244


def est_anglais (texte) :
    w,h = langue_lettre (texte)
    return w > 0.01

File: langue_fa_cor.tex, line 281


<a href="http://...."> texte qui apparaît à l'écran </a>

File: langue_fa_cor.tex, line 289

                  
import urllib       # pour accéder une adresse internet
import re           # pour traiter les expressions régulières
                    
def list_url (site, root, nbpage = 100) :
    
    # expression régulières
    # tous les liens commençant par root et entre guillemets
    # exemple :  "http://www.lemonde.fr/index,0.26.html"
    # on place entre parenthèses la partie intéressante : 
    # c'est-à-dire tout ce qu'il y a entre les guillemets
    s = "\"(" + root + "[-_~a-zA-Z0-9/.?,]*?)\""
    exp  = re.compile (s, re.IGNORECASE)
    
    res    = [ ]         # résultat
    pile   = [ site ]    # page à explorer
    
    while len (pile) > 0 and len (res) < nbpage :
    
        # on bascule toutes les pages de pile vers res    
        for u in pile : 
            if u not in res : res.append (u)
        
        u = pile.pop ()  # on s'intéresse à la prochaine page
            
        try :
            f       = urllib.urlopen (u)      # accès à l'url
            text    = f.read ()               # on lit son contenu
            f.close ()                        # fin de l'accès
            
            liens = exp.findall (text)        # recherche de tous les liens
            for u in liens :
                if u in pile or u in res :    # on passe au suivant si 
                    continue                  # déjà vu
                    
                # on enlève les images et autres fichiers indésirables
                if ".gif" in u or ".png" in u or ".jpg" in u : continue
                if ".cs" in u or ".css" in u or ".js" in u : continue
                
                # on ajoute le liens à la liste des liens à explorer
                pile.append (u)
            
        except IOError, exc:
            print "problème avec url ", u
            continue 
            
    return res

File: langue_fa_cor.tex, line 340

    
url  = "http://www.lemonde.fr/"   # un journal français
res  = list_url (url, url)
for r in res : print r

url  = "http://www.nytimes.com/"  # un journal américain
res  = list_url (url, url)
for r in res : print r

File: langue_fa_cor.tex, line 374

    
import mdp,copy,numpy
nbfr,nben = len (fr), len (en)
all = numpy.array (fr + en)    # construction du nuage de points

node = mdp.nodes.PCANode()     # ACP
node.train (all)               # construction de l'ACP
y    = node (all)              # on peut aussi écrire y = mdp.pca (all)

# obtention des coordonnées des points dans le plan de projection
frcx = [ y [i,0] for i in range (0, nbfr) ]
frcy = [ y [i,1] for i in range (0, nbfr) ]
encx = [ y [i,0] for i in range (nbfr, nbfr + nben) ]
ency = [ y [i,1] for i in range (nbfr, nbfr + nben) ]

# dessin des points dans le plan de projection
# c'est le même code que précédemment
# ...

File: langue_fa_cor.tex, line 405

    
# même début que le programme précédent
allfr = numpy.array (fr)    # points français
allen = numpy.array (en)    # points anglais

node = mdp.nodes.FDANode ()
node.train (allfr, "fr")
node.train (allen, "en")
node.stop_training ()
node.train (allfr, "fr")
node.train (allen, "en")
y    = node (all)

détection automatique de la langue d'un texte

# coding: latin-1

def lit_fichier (nom) :
    """lit un fichier texte et retourne une chaine
    de caracteres incluant tout son contenu"""
    f = open (nom, "r")
    l = f.readlines ()
    f.close ()
    l = [ i.strip (" \n\r") for i in l ]
    return "".join (l)

def lit_url (nom) :
    import urllib
    f = urllib.urlopen (nom) 
    res = f.read ()
    f.close ()
    return res.replace ("\n", "").replace ("\r", "")
    
def compte_lettre1 (texte) :
    texte = texte.upper ()
    res = { }
    for c in texte :
        if not ("A" <= c <= "Z") : continue
        if c not in res : res [c] = 1 
        else : res [c] += 1
    s = sum (res.values ())
    if s > 0 :
        for k in res :
            res [k] = float (res [k]) / float (s)
    return res

def compte_lettre2 (texte) :
    texte = texte.upper ()
    res = { }
    for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" :
    #for i in xrange (32,256) :
    #    c = chr (i)
        res [c] = texte.count (c)
    s = sum (res.values ())
    if s > 0 :
        for k in res :
            res [k] = float (res [k]) / float (s)
    return res
    
def compte_lettre (texte) :
    res = compte_lettre1 (texte)
    res = compte_lettre2 (texte)
    return res
    
if False :
    texte = lit_url ("http://www.gutenberg.org/dirs/etext04/8ldrj10.txt")
    def compteprofile () :
        for i in range (0,100) :
            compte_lettre (texte)
            
    import profile
    profile.run ('compteprofile ()')
    import sys
    sys.exit (0)

def langue_lettre (texte) :
    if "http" in texte : s = lit_url (texte)
    else : s = lit_fichier (texte)
    s = s.replace ("www", "")
    s = s.replace ("http", "").replace (".htm", "")
    s = s.replace ("href", "")
    c = compte_lettre (s)
    return c.get ("W", 0.0), c.get ("H", 0.0)
    
def langue_lettre4 (texte) :
    if "http" in texte : s = lit_url (texte)
    else : s = lit_fichier (texte)
    s = s.replace ("www", "")
    s = s.replace ("http", "").replace (".htm", "")
    s = s.replace ("href", "")
    c = compte_lettre (s)
    return c.get ("H", 0.0), c.get ("U", 0.0), c.get ("W", 0.0), c.get ("Y", 0.0)
    
def curve (li) :
    cx,cy = [], []
    for l in li :
        #print "processing ", l
        x,y = langue_lettre (l)
        print len (cx), "-", x,y,l
        cx.append (x)
        cy.append (y)
    print cx, cy
    return cx,cy
        
def curve4 (li) :
    all = []
    for l in li :
        #print "processing ", l
        x,y,z,t = langue_lettre4 (l)
        all.append ( [x,y,z,t] )
        print len (all), "-", l
    return all
        

if False :
    #s2 = lit_fichier ("hugo_the_man_who_laugh.txt")
    #c2 = compte_lettre (s2)

    #s3 = lit_fichier ("hugo_legend_siecle_francais.txt")
    #c3 = compte_lettre (s3)

    # le dernier jour d'un condamné
    s1 = lit_url ("http://www.gutenberg.org/dirs/etext04/8ldrj10.txt")
    c1 = compte_lettre (s1)

    # the man who laughs
    s2 = lit_url ("http://www.gutenberg.org/files/12587/12587-8.txt")
    c2 = compte_lettre (s2)

    car = c1.keys ()
    car.sort ()
    for k in car :
        print k, " : ", "% 2.2f" % (c1 [k] * 100), "%",
        print "     % 2.2f" % (c2 [k] * 100), "%"
    
if False :
    fr = []
    en = []

    fr.append ("http://www.gutenberg.org/dirs/etext04/8ldrj10.txt")
    en.append ("http://www.gutenberg.org/files/12587/12587-8.txt")
    fr.append ("http://www.gutenberg.org/files/17489/17489-8.txt")
    en.append ("http://www.gutenberg.org/dirs/etext98/2ws2610.txt")
    fr.append ("http://www.gutenberg.org/files/2998/2998-8.txt")
    fr.append ("http://www.gutenberg.org/dirs/etext03/zadig10.txt")
    en.append ("http://www.gutenberg.org/files/4300/4300-8.txt")
    en.append ("http://www.gutenberg.org/files/174/174.txt")
    
if True :
    f = open ("lemonde.txt", "r")
    fr = f.readlines ()
    f.close ()
    fr = [ l.strip (" \n\t") for l in fr ]
    #fr = fr [:100]

    f = open ("nytimes.txt", "r")
    en = f.readlines ()
    f.close ()
    en = [ l.strip (" \n\t") for l in en ]
        
    #en = en [:100]

allfr = curve4 (fr)
allen = curve4 (en)
import pickle
f = open ("data.bin", "wb")
pickle.dump (allfr, f)
pickle.dump (allen, f)
f.close ()
stop

frcx,frcy = curve (fr)
encx,ency = curve (en)

print len (frcx), len (frcy)
print len (encx), len (ency)

f = open ("curve.txt", "w")
f.write (str (frcx) + "\n")
f.write (str (frcy) + "\n")
f.write (str (encx) + "\n")
f.write (str (ency) + "\n")
f.close ()

import pylab
pylab.plot (frcx, frcy, "rx",ms=5)
pylab.plot (encx, ency, "bo")
pylab.legend ((r"francais", "anglais"), loc=2)
pylab.title ("langue")
pylab.xlabel ("frequence de W")
pylab.ylabel ("frequence de H")
pylab.show ()


File: carre_magique.tex, line 23


class CarreMagique :
    def __init__ (self, nb) :
        self.nb = nb
        
m = [ [9, 3, 3], [ 4,5,6] , [3,8,2] ]

File: carre_magique.tex, line 41


def __str__ (self) :
    s = ""
    s += str (self.nb [0][0])
    return s

File: carre_magique.tex, line 68


a = calcul1 (3)
b = calcul2 (a)
c = calcul3 (b) # c résultat souhaité et affiché

File: carre_magique_cor.tex, line 9


cm = CarreMagique (m)

File: carre_magique_cor.tex, line 16


<__main__.CarreMagique instance at 0x01A254E0>

(1)

# coding: latin-1

class CarreMagique :
    
    def __init__ (self, nb) :
        """on place la matrice nb (liste de listes) 
        dans la classe accessible par le mot-clé self"""
        self.nb = nb
        
    # réponse à la question 2
    def __str__ (self) :
        """méthode appelée lorsque on cherche à afficher 
        un carré magique avec l'instruction print"""
        s = ""
        for i in range (0, len (self.nb)) :
            for j in range (0, len (self.nb)) : s += str ( self.nb [i][j]) + " "
            s += "\n" # pour passer à la ligne
        # réponse à la question 4
        s += "somme " + str (self.somme_ligne (0))
        return s
        
    # réponse à la question 3
    def somme_ligne (self, i) :
        s = 0
        for j in range (0, len (self.nb)) : s += self.nb [i][j]
        return s
        
    # réponse à la question 5
    def somme_colonne (self, j) :
        s = 0
        for i in range (0, len (self.nb)) : s += self.nb [i][j]
        return s
        
    # réponse à la question 6
    def est_magique (self) :
        # on stocke toutes les sommes
        l = []
        for i in range (0, len (self.nb)) : l.append ( self.somme_ligne (i) )
        for j in range (0, len (self.nb)) : l.append ( self.somme_colonne (j) )
            
        # réponse à la question 7
        l.append ( self.somme_diagonale (0)) 
        l.append ( self.somme_diagonale (1))

        # on trie la liste
        l.sort ()
        
        # on compare le plus petit et le plus grand, s'il sont égaux, 
        # le carré est magique
        return l [0] == l [ len(l)-1 ]
        
    # réponse à la question 7
    def somme_diagonale (self, d) :
        """d vaut 0 ou 1, première ou seconde diagonale"""
        s = 0
        if d == 0 :
            for i in range (0, len (self.nb)) : s += self.nb [i][i]
        else :
            for i in range (0, len (self.nb)) : 
                s += self.nb [i][len(self.nb)-i-1]
        return s
        
    # réponse à la question 8
    def nombre_differents (self) :
        """retourne True si tous les nombres sont différents,
        on place les nombres un par un dans un dictionnaire,
        dès que l'un d'eux s'y trouve déjà,
        on sait que deux nombres sont identiques, le résultat est False"""
        k = { }
        for i in range (0, len (self.nb)) :
            for j in range (0, len (self.nb)) :
                c = self.nb [i][j]
                if c in k : return False     # pas besoin d'aller plus loin
                                             # il y a deux nombres identiques
                else : k [c] = 0
        return True
        
        
m = [ [9, 3, 7],  [ 4,5,6] , [1,8,2] ]
cm = CarreMagique (m)           # réponse à la question 1
print cm                        # affiche 15
print cm.est_magique ()         # affiche False
print cm.nombre_differents ()   # affiche True

m = [ [9, 9, 9],  [9, 9, 9], [9, 9, 9] ]
cm = CarreMagique (m)
print cm                        # affiche 15
print cm.est_magique ()         # affiche True
print cm.nombre_differents ()   # affiche False

(2)

from carre_magique import CarreMagique
res = []
for a in range (1,10) :
    for b in range (1,10) :
        for c in range (1,10) :
            for d in range (1,10) :
                for e in range (1,10) :
                    for f in range (1,10) :
                        for g in range (1,10) :
                            for h in range (1,10) :
                                for i in range (1,10) :
                                    l  = [ [a,b,c], [d,e,f], [g,h,i] ]
                                    cm = CarreMagique (l)
                                    if cm.nombre_differents () and \
                                                  cm.est_magique () :
                                        res.append (cm)

print len (res)
for r in res :
    print r

(3)

# coding: latin-1
from carre_magique import CarreMagique

dim = 3
nb  = dim*dim
res = []         # contiendra la liste des carrés magiques

# le compteur : neuf nombres 1
ind = [1 for i in range (0,nb) ]

while ind [0] <= nb :
    
    # transformation d'une liste en une liste de listes
    # [1,2,3,4,5,6,7,8,9] --> [[1,2,3],[4,5,6],[7,8,9]]
    l = []
    for i in range (0, dim) :
        l.append ( ind [i*dim:(i+1)*dim] )
    
    # on vérifie que le carré est magique et 
    # a des nombres tous différents
    cm = CarreMagique (l)
    if cm.nombre_differents () and cm.est_magique () :
        res.append (cm)

    # on passe au carré suivant : 
    i        = nb-1      # dernier indice (9 ici)
    ind [i] += 1         # addition de 1 au dernier indice
    while i > 0 and ind [i] > nb :
        ind [i-1] += 1   # un des indices est supérieur à nb (9 ici)
        ind [i]    = 1   # on le remet à 1
        i         -= 1   # et on propage l'information à l'indice inférieur

# résultat final
print len (res)
for r in res : print r

(4)

# coding: latin-1
from carre_magique import CarreMagique

dim = 3
nb  = dim*dim
M   = 9 ** nb    # on va tester 9^9 carrés possibles
res = []         # contiendra la liste des carrés magiques

for n in xrange (0,M) :
    
    # on décompose n en liste
    ind = []
    k   = n
    for t in range (0,nb) :
        dec = k % nb
        k   = k / nb
        ind.append (dec+1)
    
    # transformation d'une liste en une liste de listes
    # [1,2,3,4,5,6,7,8,9] --> [[1,2,3],[4,5,6],[7,8,9]]
    l = []
    for i in range (0, dim) :
        l.append ( ind [i*dim:(i+1)*dim] )
    
    # on vérifie que le carré est magique et 
    # a des nombres tous différents
    cm = CarreMagique (l)
    if cm.nombre_differents () and cm.est_magique () :
        res.append (cm)

# résultat final
print len (res)
for r in res : print r

File: carre_magique_cor.tex, line 47


Traceback (most recent call last):
  File "carre_magique_tous5.py", line 9, in <module>
    for n in range (0,M) :
MemoryError

(5)

# coding: latin-1
from carre_magique import CarreMagique

def echange (p, i, pos) :
    # échange de deux éléments d'indice i et pos du tableau p
    if i != pos :
        e       = p [i]
        p [i]   = p [pos]
        p [pos] = e

def permutation (res, dim, pos = 0, p = None) :
    # parcours des permutations par récurrence
    # pour le premier appel à la fonction permutation
    if p == None : p = range (1, dim*dim+1)
        
    if pos < len (p) :
        # on organise les permutations de l'élément p [pos], p [pos+1], ...
        for i in range (pos, len (p)) :
            echange (p, i, pos)
            permutation (res, dim, pos+1, p)
            echange (p, i, pos)
    else :
        # pos correspond au dernier élément : il n'y a plus de permutation
        # possible avec les éléments qui suivent
        # on teste donc le nouveau carré
        l = []
        for i in range (0, len (p)/dim) :
            l.append ( p [i*dim:(i+1)*dim] )
        cm = CarreMagique (l)
        if cm.est_magique () : res.append (cm)
    
# permutations
res = []
permutation ( res, 3 )
# résultats
print "nombre de carrés ", len (res)
for r in res : print r

File: quicksort.tex, line 46

			
racine = NoeudTri ("un")
racine.insere ("unite")
racine.insere ("deux")
print racine

File: quicksort.tex, line 60


c:\python26\python setup.py install

File: quicksort.tex, line 70


digraph GA {
    2 [label="deux",style=filled,shape=record]
    3 [label="abc" ,style=filled,shape=record]
    2 -> 3 [label="<"]
}

File: quicksort.tex, line 97


g = open ("graph.txt", "w")  #
g.write (graph)              # partie écriture dans un fichier
g.close ()                   #
dot = pydot.graph_from_dot_file ("graph.txt") # partie graphe
dot.write_png ("graph.png", prog="dot")       # avec pydot

File: quicksort_cor.tex, line 10


class NoeudTri (object):
    def __init__(self,s):
        self.mot = s

File: quicksort_cor.tex, line 19


class NoeudTri (object):
    def __init__(self,s): self.mot = s
    def __str__(self)   : return self.mot + "\n"  # \n : passage à la ligne

File: quicksort_cor.tex, line 28


class NoeudTri (object):
    def __init__(self,s): self.mot = s
    def __str__(self)   : return self.mot + "\n"

    def insere (self,s):
        c = cmp (s, self.mot)
        if   c == -1 : self.avant = NoeudTri (s)  # ajout d'un successeur
        elif c ==  1 : self.apres = NoeudTri (s)  # ajout d'un successeur

File: quicksort_cor.tex, line 43


class NoeudTri (object):
    def __init__(self,s): self.mot = s
        
    def __str__(self):
        s = ""
        if "avant" in self.__dict__: s += self.avant.__str__ ()
        s += self.mot + "\n"
        if "apres" in self.__dict__: s += self.apres.__str__()
        return s

    def insere (self,s):
        c = cmp (s, self.mot)
        if   c == -1 : self.avant = NoeudTri (s)
        elif c ==  1 : self.apres = NoeudTri (s)

File: quicksort_cor.tex, line 64


deux
un
unite

(1)

# coding: latin-1
import string

class SecondeInserstion (AttributeError):
    "insertion d'un mot déjà inséré"

class NoeudTri :
    
    def __init__(self,s): self.mot = s
        
    # la création d'un nouveau noeud a été placée dans une méthode
    def nouveau_noeud (self, s) : 
        return self.__class__ (s)
        #return NoeudTri (s)
        
    def __str__(self):
        s = ""
        if "avant" in self.__dict__: s += self.avant.__str__ ()
        s += self.mot + "\n"
        if "apres" in self.__dict__: s += self.apres.__str__()
        return s

    def insere (self,s):
        c = cmp (s, self.mot)
        if c == -1:
            if "avant" in self.__dict__ : self.avant.insere (s) # délégation
            else :  self.avant = self.nouveau_noeud (s)         # création
        elif c == 1:
            if "apres" in self.__dict__ : self.apres.insere (s) # délégation
            else: self.apres = self.nouveau_noeud (s)           # création
        else:
            raise SecondeInsertion, "mot : " + s
        
l = ["un", "deux", "unite", "dizaine", "exception", "dire", \
     "programme", "abc", "xyz", "opera", "quel"]
     
racine = None
for mot in l :
    if racine == None : 
        # premier cas : aucun mot --> on crée le premier noeud
        racine = NoeudTri (mot)
    else : 
        # second cas : il y a déjà un mot, on ajoute le mot suivant 
        # à l'arbre
        racine.insere (mot)

print racine

(2)

# coding: latin-1
import string
import pydot
import quicksort

class NoeudTri2 (quicksort.NoeudTri):

    def chaine_graphe (self):
        # le principe est le même que pour la méthode __str__
        # excepté que le format est différent
        g = str (id (self)) + ' [label="' + self.mot \
                            + '",style=filled,shape=record,fontsize=60]\n'
        if "avant" in self.__dict__:
            h  = self.avant.chaine_graphe ()
            g += h + str (id (self)) + " -> " + str (id (self.avant)) \
                   + ' [label="<",fontsize=60]' + '\n'
        if "apres" in self.__dict__:
            h  = self.apres.chaine_graphe ()
            g += h + str (id (self)) + " -> " + str (id (self.apres)) \
                   + ' [label=">",fontsize=60]' + "\n"
        return g

    #def nouveau_noeud (self, s) : return NoeudTri2 (s)
        
    def image (self, file, im) :
        # on crée un graphe : on récupère le code du graphe
        graph = self.chaine_graphe ()
        # auquel on ajoute un début et une fin
        graph = "digraph GA {\n" + graph + "}\n"
        
        # puis on l'écrit dans le fichier file
        g = open (file, "w")
        g.write (graph)
        g.close ()

        # enfin, on convertit ce fichier en image
        dot = pydot.graph_from_dot_file (file)
        dot.write_png (im, prog="dot")

def construit_arbre () :
    # même code que dans le programme précédent
    # mais inclus dans une fonction
    l = ["un", "deux", "unite", "dizaine", "exception", "dire", \
         "programme", "abc", "xyz", "opera", "quel"]
    racine = None
    for mot in l :
        if racine == None : racine = NoeudTri2 (mot)
        else : racine.insere (mot)
    return racine
    
racine = construit_arbre ()
print racine
racine.image ("graph.txt", "graph.png")

File: quicksort_cor.tex, line 99


Traceback (most recent call last):
  File "quicksort2.py", line 53, in <module>
    racine.image ("graph.txt", "graph.png")
  File "quicksort2.py", line 27, in image
    graph = self.chaine_graphe ()
  File "quicksort2.py", line 14, in chaine_graphe
    h  = self.avant.chaine_graphe ()
AttributeError: NoeudTri instance has no attribute 'chaine_graphe'

File: quicksort_cor.tex, line 112


def nouveau_noeud (self, s) : return self.__class__ (s)

File: quicksort_cor.tex, line 120


digraph GA {
18853120 [label="un",style=filled,shape=record]
28505472 [label="deux",style=filled,shape=record]
28505712 [label="abc",style=filled,shape=record]
28505472 -> 28505712 [label="<"]
28505552 [label="dizaine",style=filled,shape=record]
28505592 [label="dire",style=filled,shape=record]
28505552 -> 28505592 [label="<"]
28505632 [label="exception",style=filled,shape=record]
28505672 [label="programme",style=filled,shape=record]
28505792 [label="opera",style=filled,shape=record]
28505672 -> 28505792 [label="<"]
28505832 [label="quel",style=filled,shape=record]
28505672 -> 28505832 [label=">"]
28505632 -> 28505672 [label=">"]
28505552 -> 28505632 [label=">"]
28505472 -> 28505552 [label=">"]
18853120 -> 28505472 [label="<"]
28505512 [label="unite",style=filled,shape=record]
28505752 [label="xyz",style=filled,shape=record]
28505512 -> 28505752 [label=">"]
18853120 -> 28505512 [label=">"]
}

sortie HTML

# coding: latin-1
import quicksort2

# construction de l'arbre
racine = quicksort2.construit_arbre ()
# construction de l'image du graphe
racine.image ("graph.txt", "graph.png")

# création d'un fichier HTML
f = open ("page.html", "w")
f.write ("<body><html>\n")              # début

f.write ("<H1> liste triée </H1>\n")    # titre pour la liste triée
s = str (racine)                        # on récupère la liste triée
s = s.replace ("\n", "<BR>\n")          # <BR> permet de passer à la ligne
f.write (s)

f.write ("<H1> graphe </H1>\n")         # titre pour l'image
f.write ('<img src="graph.png" width=400/>\n')    # image

f.write ("<H1> code du graphe </H1>\n") # titre pour le code du graphe
s = racine.chaine_graphe ()             # on récupère le code du graphe
f.write ("<pre>\n")                     # on l'affiche tel quel
f.write (s)
f.write ("</pre>\n")

f.write ("</html></body>\n")            # fin
f.close ()

# on lance le navigateur automatiquement pour afficher la page
import os
os.system (r'"C:\Program Files\Mozilla Firefox\firefox" page.html')

File: quicksort_cor.tex, line 158


<body><html>
<H1> liste triée </H1>
abc<BR>
deux<BR>
...
unite<BR>
xyz<BR>
<H1> graphe </H1>
<img src="graph.png" width=400/>
<H1> code du graphe </H1>
<pre>
13697312 [label="un",style=filled,shape=record,fontsize=60]
13697192 [label="deux",style=filled,shape=record,fontsize=60]
34692472 [label="abc",style=filled,shape=record,fontsize=60]
...
13697232 -> 34692592 [label=">",fontsize=60]
13697312 -> 13697232 [label=">",fontsize=60]
</pre>
</html></body>

sortie PDF

# coding: latin-1
import quicksort2

# construction de l'arbre
racine = quicksort2.construit_arbre ()
# construction de l'image du graphe
racine.image ("graph.txt", "graph.png")

# construction du début du fichier tex
package = """a4 amsmath amssymb subfigure float latexsym amsfonts
epic eepic makeidx multido varindex moreverb alltt fancyvrb fancyhdr
color eurosym tabularx placeins url shorttoc""".split ()

header = """\\documentclass[french,11pt]{article}\n\\usepackage[french]{babel}
\\usepackage[usenames]{color}\\usepackage{""" + \
                          "}\n\\usepackage{".join (package) + \
"""}\\usepackage[small,normal]{caption2}\\urlstyle{sf}
\\usepackage[pdftex]{graphicx}\usepackage[T1]{fontenc}
\DefineVerbatimEnvironment{verbatimx}{Verbatim}{frame=single, 
framerule=.1pt, framesep=1.5mm, fontsize=\\footnotesize,xleftmargin=0pt}
\\begin{document}\n"""

# création d'un fichier tex
f = open ("page.tex", "w")
f.write (header)

f.write ("\\title{Tri quicksort}\n")    # définit le titre
f.write ("\\maketitle\n")               # écrit le titre
f.write ("\\tableofcontents\n")         # table des matières

f.write ("\\section{liste triée}\n")    # titre pour la liste triée
s = str (racine)                        # on récupère la liste triée
s = s.replace ("\n", "\\\\  \n")        # \\ passe à la ligne
f.write ("\\begin{tabular}{|l|}\n")
f.write (s)
f.write ("\\end{tabular}\n")

f.write ("\\section{graphe}\n")         # titre pour l'image
f.write ('\\includegraphics[height=5cm]{graph.png}\n')    # image

f.write ("\\section{code du graphe}\n") # titre pour le code du graphe
s = racine.chaine_graphe ()             # on récupère le code du graphe
f.write ("\\begin{verbatimx}\n")        # on l'affiche tel quel
f.write (s)
f.write ("\\end{verbatimx}\n")

f.write ("\\end{document}\n")            # fin
f.close ()

# on compile deux fois le fichier pour que la table des matières
# soit bien prise en compte
import os
os.system (r'"C:\Program Files\MiKTeX 2.7\miktex\bin\pdflatex" page.tex')
os.system (r'"C:\Program Files\MiKTeX 2.7\miktex\bin\pdflatex" page.tex')

# on affiche le résultat avec Adobe Reader
os.system (r'"C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe" page.pdf')

File: cluster.tex, line 28


import random
n = random.gauss (0,1)  # loi normale de moyenne 0, de variance 1
u = random.random ()    # loi uniforme [0,1]
import math
x,y = math.cos (t), math.sin(t)  # cosinus, sinus

File: cluster.tex, line 40


import matplotlib.pyplot as plt
x   = [ ... ]
y   = [ ... ]
fig = plt.figure()
ax  = fig.add_subplot(111)
ax.plot (x,y, 'o')
plt.savefig ("im1.png") # ou plt.show () pour afficher le graphe

File: cluster.tex, line 62


import numpy as np
mat = np.matrix ( [[1,2],[3,4]] ) # crée une matrice 2*2
s   = mat.shape           # égale à (nombre de lignes, nombre de colonnes)
l   = mat [0,:]           # retourne la première ligne
c   = mat [:,0]           # retourne la première colonne
mat [:,0] = mat [:,1]     # la première ligne est égale à la seconde
o   = np.ones ( (10,10) ) # crée un matrice de 1 10x10
d   = np.diag (d)         # extrait la diagonale d'une matrice
dd  = np.matrix (d)       # transforme d en matrice
t   = mat.transpose ()    # obtient la transposée
e   = mat [0,0]           # obtient de première élément
k   = mat * mat           # produit matriciel
m   = mat * 4             # multiplie la matrice par 4
mx  = np.max (mat [0,:])  # obtient le maximum de la première ligne
s   = np.sum (mat [0,:])  # somme de la première ligne
l   = mat.tolist ()       # transformer une matrice en list

File: cluster.tex, line 82


mat = np.diagflat ( np.ones ( (1,4) ) )
print mat  # matrice diagonale
t   =  mat == 0
print t    # matrice de booléens
mat [ mat == 0 ] = 4
print mat  # ...

File: cluster.tex, line 93


def sqrt (x) : return x**0.5 if x >= 0 else 0
func = np.vectorize (sqrt, otypes=[float])
mat  = func (dist)  # dist est une matrice

File: cluster.tex, line 134


import matplotlib.pyplot as plt
x1   = [ ... ]
y1   = [ ... ]
x2   = [ ... ]
y2   = [ ... ]
fig = plt.figure()
ax  = fig.add_subplot(111)
ax.plot (x1,y1, 'o')
ax.plot (x2,y2, 'x')
plt.savefig ("im2.png")

File: cluster.tex, line 198


def download_quotes (code, d1, d2) :
    root = "http://ichart.yahoo.com/table.csv?s=%s&a=%02d&b=%d&c=%d" \
                               "&d=%02d&e=%d&f=%d&g=d&ignore=.csv" % \
              (code, d1.month-1, d1.day, d1.year, d2.month-1, d2.day, d2.year)
    f    = urllib.urlopen (root)
    qu   = f.read ()
    f.close ()
    lines = qu.split ("\n")
    lines = [ l .strip (" \n\r") for l in lines ]
    head  = lines [0]
    lines = lines [1:]
    lines = [ l.split (",") for l in lines if "," in l ]
    lines = [ (get_date (l[0]), l) for l in lines ]
    lines = [ l [1] for l in lines if d1 <= l [0] <= d2 ]
    lines = [ "\t".join (l) for l in lines ]
    
    return "\n".join ([head ] + lines)

File: cluster.tex, line 220


import datetime
import os.path
def telecharge_et_ecrit_dans_un_fichier (code) :
    year  = datetime.datetime (2009,1,1) - datetime.datetime (2008,1,1)
    today = datetime.datetime (2009,1,1).now ()
    lyear = today - year
    file  = code + ".txt"
    if os.path.exists (file) : return  # si le fichier existe déjà, ne le fait pas
    res   = download_quotes (a, lyear, today)
    f     = open (file, "w")
    f.write (res)
    f.close ()

File: cluster_cor.tex, line 9


def random_set (nb = 100) :
    res = []
    for i in range (0, nb) :
        x,y = random.gauss (0,1),random.gauss (0,1)
        res.append ([x,y])
    for i in range (0, nb*2) :
        x,y = random.gauss (0,1),random.gauss (0,1)
        n   = (x**2 + y**2) ** 0.5
        if n == 0 : n == 1.0
        x  *= 5.0 / n
        y  *= 5.0 / n
        x  += random.gauss (0,0.5)
        y  += random.gauss (0,0.5)
        res.append ([x,y])
    return res

classification non supervisée

# coding: latin-1
import sys,random,copy,math
import matplotlib.pyplot as plt
import numpy as np
    
def random_set (nb = 100) :
    """construit un échantillon aléatoire avec deux cercles concentriques, 
    nb pour le premier, nb*2 pour le second"""
    res = []
    for i in range (0, nb) :
        x,y = random.gauss (0,1),random.gauss (0,1)
        res.append ([x,y])
    for i in range (0, nb*2) :
        x,y = random.gauss (0,1),random.gauss (0,1)
        n   = (x**2 + y**2) ** 0.5
        if n == 0 : n == 1.0
        x  *= 5.0 / n
        y  *= 5.0 / n
        x  += random.gauss (0,0.5)
        y  += random.gauss (0,0.5)
        res.append ([x,y])
    res.sort ()
    return res
    
def draw (points, clas = None) :
    """dessine un nuage de points, si clas est une liste, 
    elle contient un indice de clas"""
    
    if clas == None :
        fig = plt.figure()
        ax = fig.add_subplot(111)
        x = [ p [0] for p in points ]
        y = [ p [1] for p in points ]
        ax.plot (x,y, 'o')
        plt.savefig ("im1.png")
    else :
        fig = plt.figure()
        ax = fig.add_subplot(111)
        x = [ p [0] for p,c in zip (points, clas) if c == 0 ]
        y = [ p [1] for p,c in zip (points, clas) if c == 0 ]
        ax.plot (x,y, 'o')
        x = [ p [0] for p,c in zip (points, clas) if c == 1 ]
        y = [ p [1] for p,c in zip (points, clas) if c == 1 ]
        ax.plot (x,y, 'x')
        plt.savefig ("im2.png")
        
def distance_ligne (mat) :
    """retourne une matrice dont chaque case correspond 
    aux distances entre lignes"""
    prod = mat * mat.T
    dist = copy.deepcopy (prod)
    lin  = dist.shape [0]
    
    di = np.diag (prod)
    di = np.matrix (di)
    one  = np.ones ((1,lin))
    ii   = one.transpose () * di
    jj   = di.transpose () * one
    dist = prod * (-2) + ii + jj

    def sqrt (x) : return x**0.5 if x >= 0 else 0.0
    func_sqrt = np.vectorize (sqrt, otypes=[float])
    dist = func_sqrt (dist)

    # autre essai
    #def m (x)    : return x**0.6 if x >= 0 else 0.0 
    #func_m    = np.vectorize (m, otypes=[float])
    #dist = func_m (dist)
    
    #code dont la logique est plus explicite mais il est beaucoup plus lent 
    #for i in xrange (0, lin) :
    #    for j in xrange (0, lin) :
    #        x = (prod [i,i] + prod [j,j] - 2*prod [i,j])
    #        
    #        if x <= 0 : dist [i,j]= 0  #problème d'arrondi numérique
    #        else : dist [i,j]= x**0.5
        
    return dist
    
def iteration (dist) :
    """itération de l'algorithme"""
    dist = distance_ligne (dist)
    lin  = dist.shape [0]
    for i in xrange (0, lin) :
        x = np.max (dist [i,:])
        y = dist [i,:] * (1.0 / x )#* lin)
        dist [i,:] = y
    return dist
        
def algorithme_cluster (points) :
    """algorithme"""
    mat     = np.matrix (points)
    lin,col = mat.shape
    dist    = distance_ligne (mat)
    for i in range (0,50) :
        print "itération i", i, np.min (dist [0,1:]), \
                                np.max (dist), np.sum (dist [0,:])
        dist = iteration (dist)
        
    M    = np.max (dist [0,:])/2
    res  = dist [0,:]
    good = res > M
    bad  = res <= M
    res [good]= 1
    res [bad] = 0
    li   = res.tolist () [0]

    return li

if __name__ == "__main__" :
    
    # construction of the random set (two circles, a line)
    rnd = random_set ()
    #draw (rnd)
    clas = algorithme_cluster (rnd)
    draw (rnd, clas)
    plt.show ()

classification non supervisée d'actions

# coding: latin-1
import sys
import random
import matplotlib.pyplot as plt
import numpy as np
import copy
import math
import os
from cluster import *

import urllib
import datetime
import sys

def get_cac40_quotes () :
    """récupère les cotes du CAC40 depuis un fichier texte
    format : quote \t nom
    """
    file  = "cac40_quote.txt"
    quote = open (file, "r").readlines ()
    quote = [ q.strip (" \n\r") for q in quote ]
    quote = [ q.split ("\t") for q in quote if len (q) > 0 ]
    assert 38 <= len (quote) <= 40
    return quote
    
def get_date (s) :
    """convertit une date depuis une chaîne de caractères vers un format Python"""
    y,m,d = s.split ("-")
    y,m,d = int(y),int(m),int(d)
    d     = datetime.datetime (y,m,d)
    return d

def download_quotes (code, d1, d2) :
    """
    télécharge la cotation d'une action entre deux dates
        - code: cote
        - d1:   première date (format python)
        - d2:   seconde date (format python)
    """
    root = "http://ichart.yahoo.com/table.csv?s=%s&a=%02d&b=%d&c=%d" \
                               "&d=%02d&e=%d&f=%d&g=d&ignore=.csv" % \
              (code, d1.month-1, d1.day, d1.year, d2.month-1, d2.day, d2.year)
              
    f    = urllib.urlopen (root)
    qu   = f.read ()
    f.close ()
    lines = qu.split ("\n")
    lines = [ l .strip (" \n\r") for l in lines ]
    head  = lines [0]
    lines = lines [1:]
    lines = [ l.split (",") for l in lines if "," in l ]
    lines = [ (get_date (l[0]), l) for l in lines ]
    lines = [ l [1] for l in lines if d1 <= l [0] <= d2 ]
    lines = [ "\t".join (l) for l in lines ]
    
    return "\n".join ([head ] + lines)
    
def get_quotes_internet (all) :
    """télécharge toutes les cotations pour les cotes dans all 
       pour les 6 derniers mois
        - all: dictionnaire { cote: nom complet }
        - enregistre le résultat dans un fichier pour éviter de télécharger
            les cours à chaque exécution
    """
    year2  = datetime.datetime (2009,1,1) - datetime.datetime (2008,6,1)
    today = datetime.datetime (2009,1,1).now ()
    lyear = today - year2
    path  = "quotes/"
    for a,nom in all :
        file = path + a + ".txt"
        if os.path.exists (file) : continue
        res = download_quotes (a, lyear, today)
        f = open (file, "w")
        f.write (res)
        f.close ()
        
        print "loading ", a, " from ", lyear , " to ", today, \
              " lines ", len (res.split ("\n"))
                
def get_close_ret (code) :
    """retourne la série des rendements depuis un fichier de cotations
    créé par la fonction get_quotes_internet"""
    file = "quotes/" + code + ".txt"
    lines = open (file, "r").readlines ()
    lines = lines [1:]
    lines = [ l for l in lines if "\t" in l ]
    lines = [l.strip ("\n\r ").split ("\t") [4] for l in lines ]
    lines = [ float (x) for x in lines ]
    lines = [ (lines [x]-lines [x-1])/lines [x-1] for x in xrange (1, len (lines))]
    return lines
    
def get_matrix (all) :
    """retourne la matrice des autocorrélations"""
    colonnes = []
    for a,nom in all :
        close = get_close_ret (a)
        if len (colonnes) != 0 and len (close) != len (colonnes [0]) :
            message = "problème avec %s longueur %d <> %d " % \
                               (nom, len (close), len (colonnes [0]))
            raise Exception ("les données ne sont pas alignées dans le temps, " \
                 "une série ne contient le même nombre d'observations\n" + message)
        colonnes.append (close)
    mat = np.matrix (colonnes)  # s'il y a une erreur ici, cela signifie que les 
                                # actions n'ont pas des cotations aux mêmes dates
    cor = np.corrcoef (mat)
    return cor


if __name__ == "__main__" :
    
    if not os.path.exists ("quotes"): os.mkdir ("quotes")
    quotes = get_cac40_quotes ()
    get_quotes_internet (quotes)
    mat = get_matrix (quotes)
    print mat.shape
    li  = algorithme_cluster (mat)
    print li
    for a,b in zip (quotes,li) :
        print b, a [1], "\t", a [0]
    

, correction 2006

# coding: latin-1
# question 1
def lit_fichier (file) :
    f = open (file, "r")
    mot = []
    for l in f :
        mot.append ( l.replace ("\n", "") )
    f.close ()
    return mot

mot = lit_fichier ("td_note_texte.txt")
print mot

# question 2
def est_trie (mot) :
    for i in range (1, len (mot)) :
        if mot [i-1] > mot [i] :
            return False
    return True
    
tri = est_trie (mot)
print "liste triée ", tri

# question 3
def cherche (mot, m) :
    for i in range (0, len (mot)) :
        if mot [i] == m : 
            return i
    return -1
    
print "mot ACHATS ", cherche (mot, "ACHATS")
print "mot achats ", cherche (mot, "achats")

# question 4
un   = cherche (mot, "UN")
deux = cherche (mot, "DEUX")
print "recherche normale ", un, deux
print "nombre d'itérations", un + deux

# question 5, 6, nbun et nbdeux contiennent le nombre de comparaisons
def cherche_dicho (mot, m) :
    a = 0
    b = len (mot)-1
    nb = 0
    while a < b :
        nb += 1
        p = (a+b)/2
        if   mot [p] == m :  return p,nb
        elif mot [p] >  m :  b = p-1
        else :               a = p+1
    return -1,nb
    
un,nbun     = cherche_dicho (mot, "UN")
deux,nbdeux = cherche_dicho (mot, "DEUX")
print "recherche dichotomique ", un, deux
print "nombre d'itérations ", nbun + nbdeux

# question 7
"""
Lors d'une recherche simple, au pire, l'élément cherche sera 
en dernière position, ce qui signifie n itérations pour le trouver. 
Le coût de la recherche simple est en O(n).
"""

# question 8
"""
Lors de la recherche dichotomique, à chaque itération, on divise par deux 
l'ensemble dans lequel la recherche s'effectue,
au départ n, puis n/2, puis n/4 jusqu'à  ce que n/2^k soit nul 
c'est-à-dire k = partie entière de ln n / ln 2
il y a au plus k itérations donc le coût de l'algorithme est en O (ln n).
"""

File: td_note_2007.tex, line 63


class Date :
    def __init__ (self, jour, mois) :
        ...

, correction 2007

# coding: latin-1
####################################
# exercice 1
####################################

# question 1
def numero (jour, mois, duree = [31, 28, 31,30,31,30,31,31,30,31,30,31] ) :
    s = 0
    for i in range (0,mois-1) :
        s += duree [i]
    s += jour - 1
    return s+1
    
# question 2
def conversion_liste (li) :
    res = []
    for jour,mois in s : res.append ( numero (jour, mois))
    # pareil que 
    # for i in range (0, len (s)) : res.append ( numero (s [i][0], s [i][1]))
    return res
    
def ecart (num) :
    res = []
    for i in range (1, len (num)) :
        d = num [i] - num [i-1]
        res.append (d)
    return res
    

s = [ (1,1), (9,4), (1,5), (8,5), (17,5), (4,6), (14,7), \
        (15,8), (1,11), (11,11), (25,12) ]
r = conversion_liste (s)
ec = ecart (r)

# question 3
pos = ec.index ( max (ec) )
print "position de l'écart le plus grand ", pos
print "jour ", s [pos], " --> ", s [pos+1]

####################################
# exercice 2
####################################

# question 4
class Date :
    def __init__ (self, jour, mois) :
        self.jour = jour
        self.mois = mois
        self.duree = [31, 28, 31,30,31,30,31,31,30,31,30,31]
        
    # question 5
    def numero (self) :
        s = 0
        for i in range (0,self.mois-1) :
            s += self.duree [i]
        s += self.jour - 1
        return s+1
        
    # question 6    
    def difference (self, autre) :
        return self.numero () - autre.numero ()

def conversion_date (s) :
    res = []
    for jour,mois in s :
        res.append ( Date (jour, mois) )
    return res
    
def ecart_date (date) :
    ec = []
    for i in range (1, len (date)) :
        ec.append ( date [i].difference ( date [i-1] ) )
    return ec


# question 7
s = [ (1,1), (9,4), (1,5), (8,5), (17,5), (4,6), \
             (14,7), (15,8), (1,11), (11,11), (25,12) ]

r = conversion_date (s)
ec = ecart_date (r)
pos = ec.index ( max (ec) )
print "position de l'ecart le plus grand ", pos
print "jour ", s [pos], " --> ", s [pos+1]

# question 8
"""
La conversion en Date est faite une fois pour les dates (1,1) et (25,12) 
et 2 fois pour les autres en effet, la méthode difference effectue 
la conversion en numéros des dates self et autre
la fonction ecart_date calcule date [i].difference ( date [i-1] ) et 
                                         date [i+1].difference ( date [i] )
            --> la date [i] est convertie 2 fois
"""

# question 9
"""
On peut par exemple stocker la conversion en numéro 
dans le constructeur comme suit :
"""

class Date :
    def __init__ (self, jour, mois) :
        self.jour = jour
        self.mois = mois
        self.duree = [31, 28, 31,30,31,30,31,31,30,31,30,31]
        self.num = self.numero ()
        
    # question 5
    def numero (self) :
        s = 0
        for i in range (0,self.mois-1) :
            s += self.duree [i]
        s += self.jour - 1
        return s+1
        
    # question 6    
    def difference (self, autre) :
        return self.num - autre.num


r = conversion_date (s)
ec = ecart_date (r)
pos = ec.index ( max (ec) )
print "position de l'écart le plus grand ", pos
print "jour ", s [pos], " --> ", s [pos+1]

File: td_note_2008.tex, line 26


l = [ (1, "un"), (3, "deux",), (2, "deux"), (1, "hun"), (-1, "moinsun") ]
l.sort (reverse = True)
print l

File: td_note_2008.tex, line 34


[(3, 'deux'), (2, 'deux'), (1, 'un'), (1, 'hun'), (-1, 'moinsun')]

, correction 2008

# coding: latin-1
# la première ligne autorise les accents dans un programme Python
# la langue anglaise est la langue de l'informatique, 
# les mots-clés de tous les langages
# sont écrits dans cette langue.

####################################
# exercice 1
####################################
#

# question 1
def lit_fichier (file) :
    f = open (file, "r")
    li = f.readlines ()           # découpage sous forme de lignes
    f.close ()
    res = []
    for l in li :
        s = l.replace ("\n", "")
        s = s.split (" ")         # le séparateur des colonnes est l'espace
        res.append (s)
    return res
    
    
mat = lit_fichier ("logpdf.txt")
for m in mat [0:5] :       # on affiche les 5 premières lignes
    print m                # parce que sinon, c'est trop long
    
# question 2
def compte_date (mat) :
    d = { }
    for m in mat :
        date = m [1]   # clé
        if date in d : d [date] += 1
        else : d [date] = 1
    return d
       
dico_date = compte_date (mat)
print dico_date

# remarque générale : si le fichier logpdf.txt contient des lignes 
# vides à la fin, il se produira une erreur à la ligne 34 (date = m [1])
# car la matrice mat contiendra des lignes avec une seule colonne et non quatre.
# Il suffit soit de supprimer les lignes vides du fichier logpdf.txt
# soit de ne pas les prendre en compte lors de la lecture de ce fichier.

# question 3
# La méthode sort trie la liste mais comment ?
# Il est facile de trier une liste de nombres mais une liste de couples de 
# nombres ? L'exemple montre que la liste est triée selon le premier élément de 
# chaque couple. Pour les cas où deux couples ont un premier élément en commun, 
# les éléments semblent triés selon le second élément. L'exemple suivant le monte :

l = [(1, "un"), (3, "deux",), (2, "deux"), (1, "hun"), (1, "un"), (-1, "moinsun")]
l.sort (reverse = True)
print l  # affiche [(3, 'deux'), (2, 'deux'), (1, 'un'), 
         #          (1, 'un'),   (1, 'hun'), (-1, 'moinsun')]

# question 4
def dix_meilleures (dico) :
    # dans cette fonction on crée une liste de couples (valeur,clé) ou 
    # la clé représente une date et valeur le nombre de téléchargement 
    # pour cette date
    li = []
    for d in dico :
        cle = d
        valeur = dico [cle]
        li.append ( ( valeur, cle ) )
    li.sort (reverse = True)
    return li [0:10]
        
dix = dix_meilleures (dico_date)
print dix # la première date est (283, '26/Sep/2007')

# les quatre premières dates correspondent aux quatre premiers TD en 2007 à l'ENSAE

# question 5
# la date est en colonne 1, le document en colonne 3
# on fait un copier-coller de la fonction compte_date en changeant un paramètre
def compte_document (mat) :
    d = { }
    for m in mat :
        doc = m [3]   # clé, 3 au lieu de 1 à la question 2
        if doc in d : d [doc] += 1
        else : d [doc] = 1
    return d

dix = dix_meilleures ( compte_document (mat) )
print dix   # le premier document est 
            # (323, '/mywiki/Enseignements?.....target=python_cours.pdf'),

# question 6
def heure (s) :
    hs = s [0:2]           # on extrait la partie correspondant à l'heure
    return int (hs)        # on retourne la conversion sous forme d'entiers
    
# question 7
# on recommence avec un copier-coller
def compte_heure (mat) :
    d = { }
    for m in mat :
        h = m [2]   # clé, 2 au lieu de 1 à la question 2
        cle = heure (h)
        if cle in d : d [cle] += 1
        else : d [cle] = 1
    return d

h = compte_heure (mat)
dix = dix_meilleures ( h )
print dix   # la première heure est  (432, 17), ce qui correspond à l'heure des TD

for i in h :
    print i, "h  ", h [i]
    
# Il y a beaucoup plus de téléchargement entre 20h et 2h du matin 
# que le matin avant 10h.
# Le site est plutôt consulté le soir.
# La conclusion ne serait pas aussi évidente avec un site consulté par des gens
# du monde entier puisque 6h du matin est une heure de l'après midi au Japon.
# Il faudrait croiser l'heure avec la position géographique de la personne
# qui consulte le site.

File: td_note_2009.tex, line 22


pieces = [1,2,5,10,20,50]
...

File: td_note_2009.tex, line 45


pieces = [1,2,4,5,10,20,50]

, correction 2009

# coding: latin-1

###################################
# question 1 : retourner un tableau
###################################

pieces = [1,2,5,10,20,50]
pieces.reverse ()
print pieces # affiche [50, 20, 10, 5, 2, 1]

# il existait d'autres solutions
pieces.sort (reverse = True)

# ou encore l'utilisation d'une fonction compare modifiée 
# qui s'inspire de l'exemple 
# http://www.xavierdupre.fr/enseignement/initiation/... 
# ...initiation_via_python_ellipse/chap2_type_tex_-_tri-_3.html

# on encore un tri programmé
# http://www.xavierdupre.fr/enseignement/initiation/...
# ...initiation_via_python_ellipse/chap3_syntaxe_tex_-_tri-_27.html

##################################################################
# question 2 : trouve la plus grande pièce inférieure à un montant
##################################################################

def plus_grande_piece (montant, pieces) :
    # on suppose que les pièces sont triées par ordre décroissant
    
    for p in pieces :
        if p <= montant : return p
    
    # on peut ajouter la ligne
    return 0
    # qui correspond au fait qu'aucune pièce plus petite ou égale au montant
    # n'a été trouvé --> le montant est négatif ou nul

# on vérifie
print "plus_grande_piece (80, pieces) =", plus_grande_piece (80, pieces)  
                  # affiche 50

####################################
# question 3 : décomposer un montant
####################################

def decomposer (montant, pieces) :
    # on suppose que les pièces sont triées par ordre décroissant
    res = [ ]  # contiendra la liste des pièces pour le montant 
    while montant > 0 :
        p = plus_grande_piece (montant, pieces)  # on prend la plus grande pièce 
                                                 # inférieure ou égale au montant
        res.append (p)                           # on l'ajoute à la solution
        montant -= p                             # on ôté p à montant : 
                                       # c'est ce qu'il reste encore à décomposer
    return res
    
print "decomposer (98, pieces) =", decomposer (98, pieces)  
                # affiche [50, 20, 20, 5, 2, 1]
                
print "decomposer (99, pieces) =", decomposer (99, pieces)  
                # affiche [50, 20, 20, 5, 2, 2]
    
######################################################
# question 4 : trouver la décomposition la plus grande
######################################################

def maximum_piece (pieces) :
    # détermine le nombre maximum de pièces à utiliser
    maxi    = 0
    montant = 0
    for m in range (1, 100) :
        r = decomposer (m, pieces)    
        if len (r) >= maxi :    # si on remplace cette ligne par if len (r) > maxi :
            maxi    = len (r)   # on trouve le plus petit montant 
                                # avec la pire décomposition
            montant = m         # et non le plus grand montant 
                                # avec la pire décomposation
    return maxi, montant

print "maximum_piece (pieces) =", maximum_piece (pieces) # affiche (6, 99)

##################################
# question 5 : décomposition de 98
##################################

pieces4 = [1,2,4,5,10,20,50]
pieces4.reverse ()

print "decomposer (98, pieces) = ", decomposer (98, pieces)    # [50, 20, 20, 5, 2, 1]
print "decomposer (98, pieces4) = ", decomposer (98, pieces4)  # [50, 20, 20, 5, 2, 1]

"""
Les deux décompositions sont identiques. 
Or il existe une décomposition plus courte avec la pièce 4 :
98 = 50 + 20 + 20 + 4 + 4 = 5 pièces

L'algorithme fait la même erreur lorsqu'il décompose le montant 8. 
Il cherche toujours la plus grande pièce inférieure au montant qui est 5. 
Il lui est alors impossible d'utiliser la pièce 4  pour décomposer 8. 

Cet algorithme ne fournit pas la bonne solution avec ce nouveau jeu de pièces.
"""

#################################
# question 6 : algorithme optimal
#################################

# version récursive : très longue
def decomposer_optimal (montant, pieces) :
    if montant in pieces : 
        return [ montant ]
    else :
        r = [ 1 for m in range (0, montant) ]
        for p in pieces :
            if montant > p : # si ce test n'est pas fait, la récurrence peut être infinie
                             # car les montants négatifs ne sont pas pris en compte 
                             # par le premier test
                dec = decomposer_optimal (montant - p, pieces) + [p]
                if len (dec) < len (r) :
                    r = dec

        return r
        
# print "decomposer_optimal (98, pieces4) =", decomposer_optimal (98, pieces4)
# trop long
        
# version non récursive 
def decomposer_optimal (montant, pieces) :
    memo = [ [ 1 for l in range (0, m) ] for m in range (0, montant+1) ]
    # memo [i] contient la pire décomposition du montant i (que des pièces de un)
    
    # pour les pièces de pieces, on sait faire plus court
    for p in pieces :
        if p < len (memo) :
            memo [p] = [ p ]
        
    for m in range (1, montant+1) :
        for p in pieces :
            if m > p :
                # on calcule la nouvelle décomposition
                dec = [p] + memo [m-p] 
                # si elle est plus courte, on la garde
                if len (dec) < len (memo [m] ) :
                    memo [m] = dec
                    
    # on retourne la meilleur décomposition pour montant
    return memo [ montant ]

# beaucoup plus rapide
print "decomposer_optimal (98, pieces4) =",  decomposer_optimal (98, pieces4) 
             # affiche [50, 20, 20, 4, 4]


#######################
# question 7 : résultat
#######################


# pour trouver la décomposition la plus longue avec n'importe quel jeu de pièces
# on reprend la fonction maximum_piece et on remplace decomposer par decomposer optimale

def maximum_piece (pieces) :
    # détermine le nombre maximum de pièces à utiliser
    maxi    = 0
    montant = 0
    for m in range (1, 100) :
        r = decomposer_optimal (m, pieces)    
        if len (r) >= maxi :    # si on remplace cette ligne par if len (r) > maxi :
            maxi    = len (r)   # on trouve le plus petit montant 
                                # avec la pire décomposation
            montant = m         # et non le plus grand montant 
                                # avec la pire décomposation
    return maxi, montant

print "maximum_piece (pieces) =", maximum_piece (pieces) # affiche (6, 99)
print "maximum_piece (pieces4) =", maximum_piece (pieces4) # affiche (5, 99)


# on teste pour toutes les pièces [3,4,6,7,8,9] 
# ajoutées au jeu de pièces standard [1,2,5,10,20,50]
ensemble = [3,4,6,7,8,9]

for ajout in [3,4,6,7,8,9] :
    pieces = [1,2,5,10,20,50] + [ ajout ]
    pieces.sort (reverse = True)
    print "maximum_piece (" + str (pieces) + ") = ", maximum_piece (pieces)

# résultat :
"""
maximum_piece ([50, 20, 10, 5, 3, 2, 1]) =  (6, 99) 
maximum_piece ([50, 20, 10, 5, 4, 2, 1]) =  (5, 99)  # 4, ok
maximum_piece ([50, 20, 10, 6, 5, 2, 1]) =  (6, 99)
maximum_piece ([50, 20, 10, 7, 5, 2, 1]) =  (5, 99)  # 7, ok
maximum_piece ([50, 20, 10, 8, 5, 2, 1]) =  (5, 99)  # 8, ok
maximum_piece ([50, 20, 10, 9, 5, 2, 1]) =  (5, 98)  # 9, ok
"""


############################
# question 8 : décomposition
############################

"""
On cherche ici le coût de la fonction decomposer_optimal en fonction du montant.
Il n'y a qu'une seule boucle qui dépend du montant, le coût de la fonction est en O(n).

Dans la version récursive, le coût est le résultat d'une suite récurrente :
u(n) = u(n-1) + ... + u(n-d)
où d est le nombre de pièces.

Le coût est donc en O(a^n) où a est la plus grande des racines du polynôme :

P (x) = x^d - x^(d-1) - ... - 1

P(1) < 0 et lim P(x) = infini lorsque x tend vers infini, 
donc la plus grande des racines est supérieure à 1.
Le coût de la fonction decomposer_optimal récursive est en O(a^n) avec 1,96 < a < 1,97.

Pour des explications plus conséquentes, voir la page 
http://fr.wikipedia.org/wiki/Suite_r%C3%A9currente_lin%C3%A9aire 
sur les suites récurrentes et l'exercice 12.3.3 du livre :
http://www.xavierdupre.fr/enseignement/initiation/...
 ...initiation_via_python_ellipse.pdf
(ou 13.3.3 http://www.xavierdupre.fr/enseignement/...
 ...initiation/initiation_via_python_small.pdf).
"""

File: td_note_2009_rattrape.tex, line 37


N10   P10   gris     corde
N15   P15   rouge    chandelier
N8    P8    marron   fer à cheval

File: td_note_2009_rattrape.tex, line 54


N3    P3    cuisine
N19   P19   bureau
N20   P20   salle à manger

File: td_note_2009_rattrape.tex, line 65


def convertit_fichier_en_matrice (fichier) :
...

File: td_note_2009_rattrape.tex, line 77


def convertit_matrice_en_dictionnaire (matrice) :
...

File: td_note_2009_rattrape.tex, line 89


def fusion_dictionnaire (dico1, dico2) :

File: td_note_2009_rattrape.tex, line 98


def convertit_dictionnaire_en_matrice (dico) :

File: td_note_2009_rattrape.tex, line 106


def convertit_matrice_en_fichier (mat, fichier) :

File: td_note_2009_rattrape.tex, line 114


def fusion_fichier (fichier1, fichier2, fichier_resultat) :

File: td_note_2009_rattrape.tex, line 122


def union_moins_intersection_fichier (fichier1, fichier2, fichier_resultat) :

, correction 2009

# coding: latin-1
# Question 1

def convertit_fichier_en_matrice (file):
    f = open (file, "r") 
    l = f.readlines ()   
    f.close ()           

    mat = list()
    for s in l :
        l = s.strip ("\n\r").split ("\t")
        mat.append (l)
    return mat

# Question 2

def convertit_matrice_en_dictionnaire (matrice) :
    d={}
    for line in matrice :
        d[line[0],line[1]] = line [2:]
    return d

# Question 3

def fusion_dictionnaire (dico1, dico2) :
    dico={}
    for k in dico1 :
        if k in dico2 : dico[k] = dico1[k] + dico2[k]
    return dico

# Question 4

def convertit_dictionnaire_en_matrice (dico) :
    m =[]
    for k,v in dico.iteritems () :
        line = list (k) + v
        m.append (line)
    return m
            
# Question 5

def convertit_matrice_en_fichier (mat,nomfichier):
    f = open (nomfichier, "w")
    for line in mat :
        f.write ( "\t".join ( [ str (x) for x in line ] ) + "\n")
    f.close ()

# Question 6

def fusion_fichier (fichier1, fichier2, fichier_resultat) :
    matrice1    = convertit_fichier_en_matrice(fichier1)
    matrice2    = convertit_fichier_en_matrice(fichier2)
    dico1       = convertit_matrice_en_dictionnaire(matrice1)
    dico2       = convertit_matrice_en_dictionnaire(matrice2)
    dico        = fusion_dictionnaire (dico1,dico2)
    matrice     = convertit_dictionnaire_en_matrice(dico)
    convertit_matrice_en_fichier (matrice,fichier_resultat)

fusion_fichier (    "td_note_2009_cluedo_1.txt", 
                    "td_note_2009_cluedo_2.txt", 
                    "cluedo.txt")

# Question 7

def fusion_dictionnairebis (dico1,dico2) :
    l1=dico1.keys()
    l2=dico2.keys()
    dico={}
    for k in l1 :
        if k not in l2 : dico[k]=[]
    for k in l2 :
        if k not in l1 : dico[k]=[]
    return dico

def union_moins_intersection_fichier (fichier1, fichier2, fichier_resultat):
    matrice1    = convertit_fichier_en_matrice(fichier1)
    matrice2    = convertit_fichier_en_matrice(fichier2)
    dico1       = convertit_matrice_en_dictionnaire(matrice1)
    dico2       = convertit_matrice_en_dictionnaire(matrice2)
    
    dico        = fusion_dictionnairebis (dico1,dico2)
    
    matrice     = convertit_dictionnaire_en_matrice(dico)
    convertit_matrice_en_fichier (matrice,fichier_resultat)

union_moins_intersection_fichier (  "td_note_2009_cluedo_1.txt", 
                                    "td_note_2009_cluedo_2.txt", 
                                    "cluedo2.txt")

# Question 8
"""
Il suffit de fusionner les fichiers deux par deux 
en procédant par récurrence. On fusionne d'abord les
deux premiers, puis on fusionne le troisième 
au résultat de la première fusion...
"""

File: td_note_2010.tex, line 30


def sous_nuage (nb, x, y, v) :  # retourne une liste de 2-uples

File: td_note_2010.tex, line 35


def n_sous_nuages (n, nb) :     # retourne une liste de 2-uples

File: td_note_2010.tex, line 41


import matplotlib.pyplot as plt
x   = [ ... ]
y   = [ ... ]
fig = plt.figure()
ax  = fig.add_subplot(111)
ax.plot (x,y, 'o')
plt.savefig ("im1.png") # ou plt.show () pour afficher le graphe

File: td_note_2010.tex, line 52


def random_class (points, n) :  # retourne une liste d'entiers

File: td_note_2010.tex, line 67


def proche_barycentre (point, barycentres) :   # retourne un entier

File: td_note_2010.tex, line 72


def association_barycentre (points, barycentres) :  # retourne une liste d'entiers

File: td_note_2010.tex, line 82


def barycentre_classe (points, classes, numero_class) :   # retourne un 2-uple
def tous_barycentres  (points, classes) :       # retourne une liste de 2-uples

File: td_note_2010.tex, line 88


def nuees_dynamiques (points, nombre_classes) : # retourne une liste d'entiers

File: td_note_2010.tex, line 98


import matplotlib.pyplot as plt
x1  = [ ... ]
y1  = [ ... ]
x2  = [ ... ]
y2  = [ ... ]
fig = plt.figure()
ax  = fig.add_subplot(111)
ax.plot (x1,y1, 'o')
ax.plot (x2,y2, 'x')     # ligne ajoutée, 'x', 'bo', ...
plt.savefig ("im2.png")  # 'rx', 'go', 'gs', 'bs', ...

File: td_note_2010.tex, line 133


def n_sous_nuages (n, nb):
    m = []
    for i in range (0,n):
        x = 5*random.random()
        y = 5*random.random()
        d = sous_nuage(nb,x,y,1)
        m += d
    return m

File: td_note_2010.tex, line 146


def n_sous_nuages (n, nb):
    m = []
    for i in range (0,n):
        x = random.randint(0,20)
        y = random.randint(0,20)
        d = sous_nuage(nb,x,y,1)
        m += d
    return m

File: td_note_2010.tex, line 168


def n_sous_nuages (n, nb):
    m = []
    for i in range (0,n):
        x = random.gauss(0,1)
        y = random.gauss(0,1)
        d = sous_nuage(nb,x,y,1)
        m += d
    return m

File: td_note_2010.tex, line 191


def n_sous_nuages (n, nb):
    m = []
    for i in range (0,n):
        x = random.gauss(0,1)
        y = random.gauss(0,1)
        d = sous_nuage(nb,x,y,1)
        m +=  [ d ]                
           # le résultat n'est 
           # plus une liste
    return m

File: td_note_2010.tex, line 209


import matplotlib.pyplot as plt
x = [ p [0] for p in n_sous_nuages (3,50) ] 
y = [ p [1] for p in n_sous_nuages (3,50) ] 
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot (x,y, 'o' )
plt.savefig ("im1.png")

File: td_note_2010.tex, line 223


def random_class(l,n):
    l = []
    for i in range(0,len(l)):
        l += [ random.randint (1,n) ]
    return l

File: td_note_2010.tex, line 234


def random_class(l,n):
    l = []
    for i in range(0,len(l)):
        l += [ random.randint (0,n) ]
    return l

File: td_note_2010.tex, line 245


d= (  (p[0]-f[0])**2+(p[1]-f[1])**2 ) ** (1/2)

File: td_note_2010.tex, line 251


def proche_barycentre (point,barycentres):
    d=distance_euclidienne(point,barycentres[0])
    for i in range (0,len(barycentres)):
        if distance_euclidienne(point,barycentres[i])<=d: 
            d=distance_euclidienne(point,barycentres[i])
    return d

File: td_note_2010.tex, line 265


def barycentre_classe (points, classes, numero_class):
    x=0
    y=0
    for i in range (0,len(classes)):
        if classes[i]==numero_class:  # ligne importante
            l=point[i]
            x=x+l[0]
            y=y+l[1]
    c=[x/n,y/n]                       # ligne importante
    return c

File: td_note_2010.tex, line 284


def tous_barycentres (points,classes):
    c=[]
    for i in classes :   # or on a len(classes) == len(points)
        c+=[barycentre_classe (points,classes,i)]
    return c

File: td_note_2010.tex, line 294


def tous_barycentres (points,classes):
    c=[]
    mx=max(classes)        # il faut ajouter +1
    for i in range(0,mx) : 
        c+=[barycentre_classe (points,classes,i)]
    return c

File: td_note_2010.tex, line 309


def nuees_dynamiques (points,nombre_classes):
    l = random_class (points,nombre_classes)
    for j in range (0,10):
        c = tous_barycentres (points, l)
        a = association_barycentre (points,c)
                        # il faut ajouter ici l = a pour corriger la fonction
    return a

File: td_note_2010.tex, line 321


def nuees_dynamiques (points,nombre_classes):
    for j in range (0,10):
        l = random_class (points,nombre_classes)
        c = tous_barycentres (points, l)
        a = association_barycentre (points,c)
        l = a
    return a

File: td_note_2010.tex, line 333


def nuees_dynamiques (n,nb):
    for j in range (0,10):
        points = n_sous_nuage (n,nb)
        l = random_class (points,nombre_classes)
        c = tous_barycentres (points, l)
        a = association_barycentre (points,c)
        l = a
    return a

, correction 2010

# coding: latin-1
import random
import numpy

def dessin (nuage, image = None) :
    """dessine un nuage de points
    @param      nuage       le nuage de points
    @param      image       si None, on affiche le nuage au travers d'une fenêtre,
                            sinon, image correspond à un nom d'image 
                            sur disque dur qui contiendra le graphique final"""
    import matplotlib.pyplot as plt
    x = [ p[0] for p in nuage ]
    y = [ p[1] for p in nuage ]
    plt.clf ()
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot (x,y, 'o')
    if image == None :  plt.show ()
    else :              plt.savefig (image)
    
def dessin_classes (nuage, classes, image = None) :
    """dessine un nuage, donne des couleurs différentes
    selon que le point appartient à telle ou telle classes
    @param      nuage           nuage[i], c'est le point i
    @param      classes         classes [i] est la classe associée au point i
    @param      image           voir la fonction précédente
    """
    import matplotlib.pyplot as plt
    x = {}
    y = {}
    for i in range (0, len (nuage)) :
        cl = classes [i]
        if cl not in x : 
            x [cl] = []
            y [cl] = []
        x [cl].append ( nuage [i][0] )
        y [cl].append ( nuage [i][1] )
    plt.clf ()
    fig = plt.figure()
    ax = fig.add_subplot(111)
    for cl in x :
        ax.plot (x [cl], y [cl], "+")
    if image == None :  plt.show ()
    else :              plt.savefig (image)
        
def sous_nuage (nb, x, y) :
    """retourne un ensemble de points tirés aléatoirement selon
    une loi normale centrée autour du point x,y
    @param      nb              nombre de points
    @param      x               abscisse du centre
    @param      y               ordonnée du centre
    @return                     une liste de points ou matrice de deux colonnes
                                - la première correspond aux abscisses, 
                                - la seconde aux ordonnées
    """
    res = []
    for i in xrange (0, nb) :
        xx = random.gauss (0,1)
        yy = random.gauss (0,1)
        res.append ( [x+xx, y+yy] )
    return res
    
def n_sous_nuages (nb_class, nb_point) :
    """crée un nuage de points aléatoires 
    @param      nb_class        nombre de sous nuages
    @param      nb_point        nombre de points dans chaque sous nuage
    @return                     une liste de points ou matrice de deux colonnes
                                - la première correspond aux abscisses, 
                                - la seconde aux ordonnées"""
    res = []
    for c in xrange (0, nb_class) :
        x = random.gauss (0,1) * 5
        y = random.gauss (0,1) * 5
        res += sous_nuage (nb_point, x,y)
    return res
    
def random_class ( nuage, n) :  
    """choisis aléatoirement un entier pour chaque point du nuage
    @param      nuage           un nuage de points (matrice de deux colonnes)
    @param      n               nombre de classes
    @return                     une liste d'entiers
    """
    res = [ ]
    for p in nuage :
        c = random.randint (0, n-1)
        res.append (c)
    return res
    
def proche_barycentre (point, barycentres) :
    """détermine le barycentre le plus d'un point 
    @param      point           liste de 2 réels : [x,y]
    @param      barycentres     liste de n points = matrice de deux colonnes,
                                chaque ligne correspond à un barycentre
    @return                     un entier qui correspond à l'index
                                du barycentre le plus proche"""
    dmax = 1e6
    for i in range (0, len (barycentres)) :
        b  = barycentres [i]
        dx = point [0] - b [0]
        dy = point [1] - b [1]
        d  = (dx**2 + dy**2) ** 0.5
        if d < dmax :
            dmax = d
            m    = i
    return m
    
def association_barycentre (points, barycentres) :
    """détermine pour chaque point le barycentre le plus proche
    @param      points          nuage (matrice de deux colonnes)
    @param      barycentres     c'est aussi une matrice de deux colonnes mais
                                avec moins de lignes
    @return                     liste d'entiers, chaque entier
                                correspond à la classe du point points[i],
                                c'est-à-dire l'index du barycentre le plus proche
                                ici: 
                                point:      points [i]
                                classe:     res[i]
                                barycentre: barycentres[ res[i] ]
    """
    res = []
    for p in nuage :
        m = proche_barycentre (p, barycentres)
        res.append (m)
    return res
    
def barycentre_classe (points, classes, numero_class) :
    """calcule le barycentre d'une classe
    @param      points          ensemble de points (matrice de deux colonnes)
    @param      classes         liste d'entiers de même longueur, 
                                chaque élément classes[i] est la classe de point[i]
    @param      numero_class    classe pour laquelle on doit calculer le barycentre
    @return                     résultat barycentre x,y
    
    dans cette fonction, on doit calculer le barycentre d'une classe
    c'est-à-dire le barycentre des points points[i] 
    pour lesquelles classes[i] == numero_class
    """
    mx,my = 0.0,0.0
    nb    = 0
    for i in range (0, len (points)) :
        p = points [i]
        c = classes [i]
        if c != numero_class : continue
        nb += 1
        mx += p [0]
        my += p [1]
    return mx/nb, my/nb
    
def tous_barycentres (points, classes) :
    """calcule les barycentres pour toutes les classes
    @param      points      points, nuage, matrice de deux colonnes
    @param      classes     liste d'entiers
    @return                 liste de barycentre = matrice de deux colonnes 
    """
    mx          = max (classes)+1
    barycentre  = []
    for m in range (0,mx) :
        b = barycentre_classe (points, classes, m)
        barycentre.append (b)
    return barycentre
    
def numpy_tous_barycentres (points, classes) :
    """écriture de barycentre_classe et tous_barycentres
    en une seule fonction avec numpy
    """
    nbcl = max (classes)+1
    mat  = numpy.matrix (points)
    vec  = numpy.array ( classes )
    clas = numpy.zeros ( (len (points), nbcl) )
    for i in range (0, nbcl) : 
        clas [ vec == i, i ] = 1.0 
    nb   = clas.sum (axis = 0)
    for i in range (0, nbcl) : 
        clas [ vec == i, i ] = 1.0 / nb [i]
    ba = mat.transpose () * clas
    ba = ba.transpose ()
    ba = ba.tolist ()
    barycentre = [ b for b in ba ]
    return barycentre
    
def numpy_tous_barycentres2 (points, classes) :
    """écriture de barycentre_classe et tous_barycentres
    en une seule fonction avec numpy
    """
    nbcl        = max (classes)+1
    mat         = numpy.matrix (points)
    matt        = mat.transpose ()
    matcl       = numpy.matrix (classes).transpose ()
    barycentre  = []
    for c in xrange (0, nbcl) :
        w  = numpy.matrix (matcl)
        w [matcl==c] = 1
        w [matcl!=c] = 0
        wt = w.transpose ()
        r  = matt * w
        n  = wt * w
        r /= n [0,0]
        barycentre += [ [ r [0,0], r [1,0] ] ]
        
    return barycentre
    
def nuees_dynamiques (points, nbcl) :
    """algorithme des nuées dynamiques
    @param      points          ensemble points = matrice de deux colonnes
    @param      nbcl            nombre de classes demandées
    @return                     un tableau incluant la liste d'entiers
    """
    classes = random_class (points, nbcl)
    
    # on a le choix entre la version sans numpy
    for i in range (0,10) :
        print "iteration",i, max (classes)+1
        barycentres = tous_barycentres (points, classes)        # ou l'un
        classes     = association_barycentre (points, barycentres)
    cl1 = classes
    
    # ou la première version avec numpy
    for i in range (0,10) :
        print "iteration",i, max (classes)+1
        barycentres = numpy_tous_barycentres (points, classes)  # ou l'autre
        classes     = association_barycentre (points, barycentres)
    cl2 = classes
    
    # ou la seconde version avec numpy
    for i in range (0,10) :
        print "iteration",i, max (classes)+1
        barycentres = numpy_tous_barycentres2 (points, classes)  # ou l'autre
        classes     = association_barycentre (points, barycentres)
    cl3 = classes
    
    # on doit trouver cl1 == cl2 == cl3
    if cl1 != cl2 or cl1 != cl3 :
        print "erreur de calculs dans l'une des trois fonctions"
    return classes
            
# début du programme : on construit un nuage de points
nuage = n_sous_nuages (3, 50)
# on appelle l'algorithme
classes = nuees_dynamiques (nuage, 3)
# on dessine le résultat
dessin_classes (nuage, classes)

File: td_note_2010_rattrape.tex, line 73


[['Auxerre', 3.537309885, 47.767200469999999], 
 ['Bastia', 9.4343004229999998, 42.661758419999998], 
 ...         

File: td_note_2010_rattrape.tex, line 81


def get_tour () :
    stour = """Auxerre	3,537309885	47,76720047
Bastia	9,434300423	42,66175842
Bordeaux	-0,643329978	44,80820084"""
    ...
    return tour

File: td_note_2010_rattrape.tex, line 93


def distance (tour, i,j) :
    ...
    return d

File: td_note_2010_rattrape.tex, line 101


def longueur_tour (tour) :
    ...
    return d

File: td_note_2010_rattrape.tex, line 109


import pylab
def graph (tour) :
    x = [ t[1] for t in tour ]
    y = [ t[2] for t in tour ]
    ....
    ....
    pylab.plot (x,y)
    for ville,x,y in tour :
        pylab.text (x,y,ville)
    pylab.show ()

File: td_note_2010_rattrape.tex, line 132


def permutation (tour) :

File: td_note_2010_rattrape.tex, line 164


def retourne (tour, i,j) :

File: td_note_2010_rattrape.tex, line 171


def croisement (tour) :

File: td_note_2010_rattrape.tex, line 177


def resoud_et_dessine (tour) :

, correction 2010

# coding: latin-1
import random, numpy, math, pylab, copy

###
### réponse à la question 1
###

def get_tour () :
    tour = """Auxerre	3,537309885	47,76720047
Bastia	9,434300423	42,66175842
Bordeaux	-0,643329978	44,80820084
Boulogne	1,579570055	50,70875168
Caen	-0,418989986	49,14748001
Le Havre	0,037500001	49,45898819
Lens	2,786649942	50,40549088
Lille	2,957109928	50,57350159
Lyon	4,768929958	45,70447922
Paris	2,086790085	48,65829086
Lyon	4,768929958	45,70447922
Marseille	5,290060043	43,1927681
Lille	2,957109928	50,57350159
Nantes	-1,650889993	47,16867065
Rennes	-1,759150028	48,05683136
Toulouse	1,356109977	43,5388298
Strasbourg	7,687339783	48,49562836
Nancy	6,134119987	48,66695023
Nice	7,19904995	43,6578598
Saint-Etienne	4,355700016	45,39992905
Brest	-4,552110195	48,36014938
Metz	6,11729002	49,0734787
Sedan	4,896070004	49,68407059
Grenoble	5,684440136	45,13940048
Annecy	6,082499981	45,8782196""".replace (",", ".").split ("\n")
    # ligne d'avant : on découpe l'unique chaîne de caractères
    
    # ligne suivant : on découpe chaque ligne en colonne
    tour = [ t.strip ("\r\n ").split ("\t") for t in tour ]
    # puis on convertit les deux dernières colonnes
    tour = [ t [:1] + [ float (x) for x in t [1:] ] for t in tour ]
    return tour

###
### réponse à la question 2
###

def distance (tour, i,j) :
    dx = tour [i][1] - tour [j][1]
    dy = tour [i][2] - tour [j][2]
    return (dx**2 + dy**2) ** 0.5
    
###
### réponse à la question 3
###

def longueur_tour (tour) :
    # n villes = n segments
    d = 0
    for i in xrange (0,len(tour)-1) :
        d += distance (tour, i,i+1)
    # il ne faut pas oublier de boucler pour le dernier segment
    d += distance (tour, 0,-1)       
    return d
    
###
### réponse à la question 4
###

def graph (tour) :
    x = [ t[1] for t in tour ]
    y = [ t[2] for t in tour ]
    x += [ x [0] ]   # on ajoute la dernière ville pour boucler
    y += [ y [0] ]   #
    pylab.plot (x,y)
    for ville,x,y in tour :
        pylab.text (x,y,ville)
    pylab.show ()
    
###
### réponse à la question 5
###

def permutation (tour) :
    
    # on calcule la longueur du tour actuelle
    best  = longueur_tour (tour)
    
    # variable fix : dit combien d'échanges ont eu lieu depuis la 
    # dernière amélioration
    fix   = 0
    while True :
        # on tire deux villes au hasard
        i = random.randint (0, len(tour)-1)
        j = random.randint (0, len(tour)-1)
        if i == j : continue
            
        # on les échanges si i != j
        e = tour [i]
        tour [i] = tour [j]
        tour [j] = e
        
        # on calcule la nouvelle longueur
        d = longueur_tour (tour)
        
        if d >= best :
            # si le résultat est plus long --> retour en arrière
            # ce qui consiste à échanger à nouveau les deux villes
            fix += 1
            e = tour [i]
            tour [i] = tour [j]
            tour [j] = e
        else :
            # sinon, on garde le tableau tel quel
            best = d
            # et on met fix à 0 pour signifier qu'une modification a eu lieu
            fix = 0
            
        # si aucune modification n'a eu lieu durant les dernières 10000 itérations,
        # on s'arrête
        if fix > 10000 : break
            
###
### réponse à la question 6
###

def retourne (tour, i,j) :
    """
    on échange les éléments i et j
    puis i+1 et j-1
    puis i+2 et j-2
    tant que i+k < j-k 
    """
    while i <= j :
        e = tour [i]
        tour [i] = tour [j]
        tour [j] = e
        i += 1
        j -= 1

###
### réponse à la question 7
###

def croisement (tour) :
    """
    cette fonction reprend le même schéma que la fonction permutation
    on annule une modification en appelant à nouveau la fonction retourne
    """
    best  = longueur_tour (tour)
    fix   = 0
    while True :
        i = random.randint (0, len(tour)-2)
        j = random.randint (i+1, len(tour)-1)
        retourne (tour, i,j)
        d = longueur_tour (tour)
        if d >= best :
            # retour en arrière
            fix += 1
            retourne (tour, i,j)
        else :
            fix = 0
            best = d
        if fix > 10000 : break
            
###
### réponse à la question 8
###

def enchaine (tour) :
    """
    cette fonction est plus complexe que le résultat demandé pour cette question
    on enchaîne les deux fonctions (croisement, permutation) tant que
    la longueur du circuit diminue
    
    et si jamais cette longueur ne diminue plus, on perturbe le circuit 
    au plus deux fois
    en échangeant trois couples de villes choisies au hasard,
    cette dernière partie n'était pas prévue dans l'énoncé
    """
    best = longueur_tour (tour)
    tttt = copy.deepcopy (tour)
    print "debut", best
    nom  = 0
    while True :
        
        croisement (tour)
        d = longueur_tour (tour)
        print "croisement", d, best
        
        permutation (tour)
        d = longueur_tour (tour)
        print "permutation", d, best
        
        if d < best :
            best = d
            tttt = copy.deepcopy (tour)
            nom  = 0
        elif nom > 2 :
            break
        else :
            nom += 1
            for k in range (0,3) :
                i = random.randint (0, len(tour)-2)
                j = random.randint (i+1, len(tour)-1)
                e = tour [i]
                tour [i] = tour [j]
                tour [j] = e
            
    return tttt
            
if __name__ == "__main__" :
    tour = get_tour ()
    tour = enchaine (tour)
    graph (tour)

File: td_note_2011.tex, line 45


75002    2.407478    48.930141         75010    2.405963    48.921033
75002    2.400573    48.913487         75018    2.391144    48.934509

, correction 2011

# coding: latin-1
import urllib2, math

# question 1
def lit_fichier () :
    # le principe est le même que pour le chargement d'un fichier
    # le programme lit directement les informations depuis Internet
    f = urllib2.urlopen ("http://www.xavierdupre.fr/enseignement"\
                         "/examen_python/restaurant_paris.txt")
    s = f.read ()
    f.close ()
    lines = s.split ("\n")  # on découpe en lignes
    # on découpe en colonnes
    lines = [ _.strip ("\n\r ").split ("\t") for _ in lines if len (_) > 0 ]  
    lines = [ _ for _ in lines if len (_) == 3 ]  # on supprime les lignes vides
    # on convertit les coordonnées en réel
    lines = [ (a [3:], float (b), float (c)) for a,b,c in lines ]
    return lines
    
# question 2
def compte_restaurant (mat) :
    # simple comptage, voir le chapitre 3...
    compte = { }
    for cp,x,y in mat :
        if cp not in compte : compte [cp] = 0
        compte [cp] += 1
    return compte
    
# question 3
def barycentre (mat) :
    # un barycentre est un point (X,Y)
    # où X et Y sont respectivement la moyenne des X et des Y
    barycentre = { }
    # boucle sur la matrice
    for cp,x,y in mat :
        if cp not in barycentre : barycentre [cp] = [ 0, 0.0, 0.0 ]
        a,b,c           = barycentre [cp]
        barycentre [cp] = [a+1, b+x, c+y]
    # boucle sur les barycentres
    for cp in barycentre :
        a,b,c = barycentre [cp]
        barycentre [cp] = [b/a, c/a]
        
    # le coût de cette fonction est en O (n log k)
    # où k est le nombre de barycentre
    # de nombreux élèves ont deux boucles imbriquées, 
    # d'abord sur la matrice, ensuite sur les barycentres
    # ce qui donne un coût en O (nk), beaucoup plus grand
    return barycentre
    
# question 4 
def distance (x1, y1, x2, y2) :
    return ((x1-x2)**2 + (y1-y2)**2)**0.5

# question 5
def plus_proche_restaurant (x,y, arr, mat) :
    m,mx,my = None, None, None
    for cp,a,b in mat :
        if cp != arr and (m == None or distance (a,b,x,y) < m) :
            mx,my = a,b
            m     = distance (a,b,x,y)
    return mx,my
    
# question 6
def densite_approchee (mat) :
    g      = barycentre (mat)
    compte = compte_restaurant (mat)
    res    = { }
    
    for cp in g :
        out  = plus_proche_restaurant (g [cp][0], g [cp][1], cp, mat)
        r    = distance (g [cp][0], g [cp][1], out [0], out [1])
        aire = math.pi * r ** 2
        res [cp] = compte [cp] / aire
        
    return res
    
if __name__ == "__main__" :
    
    if False :  #mettre à vrai pour remplacer la fonction plus_proche_restaurant
        # ajout par rapport à l'énoncé
        # en réponse à la dernière question
        # plutôt que de prendre le premier point à hors de l'arrondissement
        # on considère celui correspondant à un quantile (5%)
        # ce qui évite les quelques restaurants dont les données
        #sont erronées
        def plus_proche_restaurant_avec_amelioration (x,y, arr, mat) :
            all     = []
            for cp,a,b in mat :
                if cp != arr :
                    m = distance (a,b,x,y)
                    all.append ( (m,a,b))
            all.sort ()
            a,b = all [len(all)/20][1:]
            return a,b
            
        # ajout par rapport à l'énoncé
        plus_proche_restaurant = plus_proche_restaurant_avec_amelioration
    
    mat = lit_fichier ()
    com = densite_approchee (mat)
    ret = [ (v,k) for k,v in com.iteritems () ]
    ret.sort ()
    for a,b in ret : print "%d\t%s" % (a,b)
        
    # ajout par rapport à l'énoncé
    # permet de dessiner les restaurants, une couleur par arrondissement
    # on observe que certains points sont aberrants, ce qui réduit d'autant 
    # l'estimation du rayon d'un arrondissement (il suffit qu'un restaurant 
    # étiquetés dans le 15ème soit situé près du barycentre du 14ème.)
    import matplotlib
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.mlab as mlab
    import matplotlib.cbook as cboo

    fig = plt.figure()
    ax = fig.add_subplot(111)
    colors = [  'red', 'blue', 'yellow', 'orange', 'black', 'green', 
                'purple', 'brown', 'gray', 'magenta', 'cyan', 'pink', 'burlywood',
                'chartreuse', '#ee0055']
    for cp in barycentre (mat) :
        lx = [ m[1] for m in mat if m [0] == cp ]
        ly = [ m[2] for m in mat if m [0] == cp ]
        c  = colors [ int(cp) % len (colors) ]
        #if cp not in ["02", "20"] : continue
        ax.scatter(lx,ly, s = 5., c=c,edgecolors = 'none'  )
    plt.show ()
        
        
        
    

, énoncé 2012

#coding:latin-1
import urllib, os, os.path, numpy
def charge_donnees (nom = "donnees_enquete_2003_television.txt") :
    if os.path.exists (nom) :
        # si le fichier existe (il a déjà été téléchargé une fois)
        f = open (nom, "r")
        text = f.read ()
        f.close ()
    else :
        # si le fichier n'existe pas
        link = "http://www.xavierdupre.fr/enseignement/td_python/" + \
                 "python_td_minute/data/examen/" + nom
        url = urllib.urlopen (link)
        text = url.read ()
        # on enregistre les données pour éviter de les télécharger une seconde fois
        f = open (nom, "w")
        f.write (text)
        f.close ()
        
    lines = text.split ("\n")
    lines = [ l.split("\t") for l in lines if len(l) > 3 ]
    lines = [ [ "0" if s.strip() == "" else s for s in l ] for l in lines ]
    return lines
    
donnees = charge_donnees ()

colonne = donnees [0]
matrice = numpy.array (donnees [1:], dtype=float)
 
# quelques exemples d'utilisation du module numpy
petite_matrice = matrice [0:5,2:4]
print petite_matrice

# dimension d'une matrice
print petite_matrice.shape

# multiplication terme à terme
vecteur = petite_matrice [:,0] * petite_matrice [:,1]
print vecteur

# sum
print vecteur.sum ()

# changer une valeur selon une condition
petite_matrice [ petite_matrice [:,1] == 1, 1] = 5
print petite_matrice

# ne conserver que certaines lignes de la matrice
m = petite_matrice [ petite_matrice[:,1] == 5,: ]
print m

# créer une matrice 10x2 avec des zéros
m = numpy.zeros( (10,2) )

# trier les lignes selon la première colonne
tr = numpy.sort (petite_matrice, 0)


# dessiner deux courbes
def dessin_temperature (temperature) :
    import pylab
    u = [ t[3] for t in temperature ]
    v = [ t[4] for t in temperature ]
    pylab.plot (u)
    pylab.plot (v)
    pylab.show()   

File: td_note_2012.tex, line 41


POIDLOG       POIDSF         cLT1FREQ  cLT2FREQ
0.8894218317  4766.8652013   2         1
2.740069772   14685.431344   6         2

File: td_note_2012.tex, line 106


temperature = charge_donnees("cannes_charleville_2010_max_t.txt")

File: td_note_2012.tex, line 119


def dessin_temperature (temperature) :
    import pylab
    u = [ t[3] for t in temperature ]
    v = [ t[4] for t in temperature ]
    pylab.plot (u)
    pylab.plot (v)
    pylab.show()

, correction 2012

# coding: latin-1
# ce fichier contient le programme fournit au début de l'examen
# http://www.xavierdupre.fr/enseignement/examen_python/python_examen_2011_2012.py
from td_note_2012_enonce import *
import numpy, pylab

########################################################################
# exercice 1
########################################################################

# question 1 (+1=1p)
donnees = charge_donnees ()
colonne = donnees [0]
matrice = numpy.array (donnees [1:], dtype=float)

mat     = matrice
mat     = mat [ mat [:,3] > 0, : ]

# question 2 (+1=2p)
mat [ mat[:,3] == 1, 3 ] = 24
mat [ mat[:,3] == 2, 3 ] = 24*7
mat [ mat[:,3] == 3, 3 ] = 24*30

# question 3 (+1=3p)
res = mat [:,2] / mat [:,3]
print res.sum() / res.shape [0]       # 0.111 ~ 11,1% du temps passé devant la télévision
print res.sum() / res.shape [0] * 24  # soit 2h40min

# question 4 (+2=5p)
m = mat[:,1] * mat[:,2] / mat[:,3]
print m.sum() / mat[:,1].sum()        # 0.108 ~ 10,8%

# question 5 (+1=6p)
m = mat[ mat[:,2] > mat[:,3], : ]
print m  # il y a deux personnes et la raison la plus probable est une erreur dans l'unité de temps

# question 6 (+2=8p)
res = numpy.sort (res, 0)
print res[res.shape[0]/2]   # 0.083 ~ 8.3% = 2h

# question 7 (+2=10p)
pr = numpy.zeros ((mat.shape[0],4)) 
pr [:,0] = mat[:,2] / mat[:,3]
pr [:,1] = mat[:,1]
pr [:,2] = pr[:,0] * pr[:,1]
pr = numpy.sort (pr, 0)
total = pr[:,2].sum()
pr[0,3] = pr [0,2] 
for i in xrange (1, pr.shape[0]) :
    pr[i,3] = pr[i-1,3] + pr[i,2]
    if pr[i,3]/total > 0.5 :
        fin = i
        break
print pr[fin,3] / pr[:fin+1,1].sum()  # 0.0895 ~ 8.95%
    
########################################################################
# exercice 2
########################################################################

# question 1 (+1=1p)
temperature = charge_donnees("cannes_charleville_2010_max_t.txt")

def conversion_reel (temperature) :
    return [ [ float (x) for x in l ] for l in temperature [1:] ]

temperature = conversion_reel(temperature)

#question 2  (+2=3p)
def valeur_manquante (temperature, c) :
    for i in xrange (1, len (temperature)-1) :
        if temperature [i][c] == -1000 :
            temperature [i][c] = (temperature [i-1][c] + temperature [i+1][c]) / 2

valeur_manquante(temperature, 3)
valeur_manquante(temperature, 4)

def dessin_temperature (temperature) :
    import pylab
    u = [ t[3] for t in temperature ]
    v = [ t[4] for t in temperature ]
    pylab.plot (u)
    pylab.plot (v)
    pylab.show()

# on met en commentaire pour éviter de l'exécuter à chaque fois
# dessin_temperature(temperature)

# question 3 (+1=4p)

def distance (u,t) :
    return (u-t)**2
    
# question 4 (+3=7p)

def somme_ecart (temperature, t1, t2, T) :
    s = 0
    for i in xrange (0, len(temperature)) :
        if t1 < i < t2 :
            s += distance (temperature[i][3], T) # charleville
        else :
            s += distance (temperature[i][4], T) # cannes
    return s

# question 5 (+3=10p)

def minimisation (temperature, T) :
    best = 1e10
    t1t2 = None
    for t1 in xrange (0,len(temperature)) :
        for t2 in xrange (t1+1,len(temperature)) :
            d = somme_ecart(temperature,t1,t2,T)
            if best == None or d < best :
                best = d
                t1t2 = t1,t2
    return t1t2, best
    
#for i in range (300,363) : print "*",somme_ecart (temperature, i, i+2, 20)
print temperature [191]
print temperature [266]
for T in range (15, 25) :
    print T, "**",minimisation (temperature,T) # (191 = 11/7, 266 = 24/9)  (attendre 2 minutes)

# question 6
# Le coût de l'algorithme est on O(n^2) car l'optimisation est une double boucle sur les températures.
# Passer des jours aux semaines, c'est utiliser des séries 7 fois plus courtes, 
# l'optimisation sera 7^2 fois plus rapide.

, correction 2012

# coding: latin-1
# question 1
def frequence_lettre (mot) :
    res = { }
    for c in mot :
        if c in res : res[c] += 1
        else : res [c] = 1
    return res
    
print frequence_lettre ("aviateur")
# affiche {'a': 2, 'e': 1, 'i': 1, 'r': 1, 'u': 1, 't': 1, 'v': 1}

# Deux autres écritures de la fonction
def frequence_lettre (mot) :
    res = { c:0 for c in mot }
    for c in mot : res[c] += 1
    return res
    
def frequence_lettre (mot) :
    res = { }
    for c in mot : 
        # la méthode get retourne res[c] si cette valeur existe, 0 sinon
        res[c] = res.get( c, 0 ) + 1
    return res
    
# question 2

def anagramme (mot1, mot2) :
    h1 = frequence_lettre(mot1)
    h2 = frequence_lettre(mot2)
    
    # il fallait éviter d'écrire la ligne suivante bien qu'elle retourne le résultat cherché :
    # return h1 == h2
    
    for c in h1 :
        if c not in h2 or h1[c] != h2[c] : return False
    # il ne faut pas oublier cette seconde partie
    for c in h2 :
        if c not in h1 : return False
    return True
    
a,b = "anagramme", "agrammane"
print anagramme (a,b), anagramme (b,a) # affiche True, True

# on vérifie que la fonctionne marche aussi dans l'autre cas
a,b = "anagramme", "agrummane"
print anagramme (a,b), anagramme (b,a) # affiche False, False

# on pouvait faire plus rapide en éliminant les cas évidents
def anagramme (mot1, mot2) :
    if len(mot1) != len(mot2) : return False
    h1 = frequence_lettre(mot1)
    h2 = frequence_lettre(mot2)
    if len(h1) != len(h2) : return False

    for c in h1 :
        if h1[c] != h2.get(c, 0) : return False
    return True

, correction 2012

# coding: latin-1

# question 1

def factorielle (n) :
    res = 1
    while n > 1 : 
        res *= n
        n -= 1
    return res
    
print factorielle (3)
    
# voici la version récursive qui n'était pas demandée :    
def factorielle_recursive (n) :
    return n*factorielle_recursive (n-1) if n > 1 else 1
        
# question 2

def f(a,b) :
    
    # f(a,b) = f(a-1,b) + f(a,b-1)
    # la formule implique de calculer toutes les valeurs f(i,j)
    # avec (i,j) dans [[0,a]] x [[0,b]]
    # un moyen afin d'éviter de trop nombreux calculs est de 
    # stocker les valeurs intermédiaires de f dans une matrice
    # il faut ensuite s'assurer que f(a-1,b) et f(a,b-1) 
    # ont déjà été calculées avant de calculer f(a,b)
    # pour cela, on parcourt la matrice dans le sens des i et j croissants
    # il ne faut pas oublier les a+1,b+1 car range (a) est égal à [ 0,1, ..., a-1 ]
    
    mat = [ [ 0 for i in range (b+1) ] for j in range (a+1) ]
    for i in range (a+1) :
        for j in range (b+1) :
                if i == 0 or j == 0 :
                    mat [i][j] = max (i,j)
                else :
                    mat [i][j] = mat [i-1][j] + mat[i][j-1]
    return mat [a][b]

# on teste pour des valeurs simples
print f(0,5) # affiche 5
print f(1,1) # affiche 2
# on vérifie en suite que cela marche pour a < b et b > a
print f (4,5)  # affiche 210
print f (5,4)  # affiche 210

# autres variantes

# la version récursive ci-dessous est juste beaucoup plus longue, elle appelle
# la fonction f_recursive autant de fois que la valeur retournée 
# par la fonction cout_recursive alors que la fonction précédente 
# effectue de l'ordre de O(a*b) calculs
def f_recursive(a,b) :
    return f_recursive(a-1,b) + f_recursive(a,b-1) if a > 0 and b > 0 else max(a,b)

def cout_recursive(a,b) :
    return cout_recursive(a-1,b) + cout_recursive(a,b-1) if a > 0 and b > 0 else 1

# une autre version non récursive
def f(a,b) :
    mat = { }
    for i in range (a+1) :
        for j in range (b+1) :
                mat [i,j] = mat [i-1,j] + mat[i,j-1] if i > 0 and j > 0 else max (i,j)
    return mat [a,b]

, correction 2012

def f_recursive(a,b, memoire) :
    if (a,b) in memoire : return memoire [a,b]
    else : 
        res = f_recursive(a-1,b, memoire) + f_recursive(a,b-1, memoire) \
                    if a > 0 and b > 0 else max(a,b)
        memoire [a,b] = res
        return res

, correction 2012

# coding: latin-1

# question 1

def somme_partielle (li, i, j) :
    r = 0
    for a in range (i,j) :
        r += li [a]
    return r
    
# question 2

def plus_grande_sous_liste (li) :
    meilleur = min(li)               # ligne A
    im,jm = -1,-1
    for i in range (0,len(li)) :
        for j in range (i+1, len(li)+1) :   # ne pas oublier +1 car sinon
                        # le dernier élément n'est jamais pris en compte
            s = somme_partielle(li, i,j)
            if s > meilleur :
                meilleur = s
                im,jm = i,j
    return li [im:jm]
    
# si li ne contient que des valeurs positives, la solution est évidemment la liste entière
# c'est pourquoi il faut tester cette fonction avec des valeurs négatives
li = [ 4,-6,7,-1,8,-50,3]
m  = plus_grande_sous_liste(li)
print(m)   # affiche [7, -1, 8]

li = [1,2,3,4,5,-98,78,9,7,7]
m  = plus_grande_sous_liste(li)
print(m)   # affiche [79, 9, 7, 7]

# autre version plus courte

def plus_grande_sous_liste (li) :
    solution = [ (somme_partielle(li,i,j), i, j) \
                    for i in range (0,len(li)) \
                    for j in range (i+1, len(li)+1) ]
    m = max(solution)
    return li [m[1]:m[2]]

, correction 2012

def plus_grande_sous_liste_n2 (li) :
    meilleur = 0
    im,jm = -1,-1
    for i in range (0,len(li)) :
        s = 0
        for j in range (i, len(li)) :
            s += li[j]
            if s > meilleur :
                meilleur = s
                im,jm = i,j+1
    return li [im:jm]
    
li = [ 4,-6,7,-1,8,-50,3]
m  = plus_grande_sous_liste_n2(li)
print(m)   # affiche [7, -1, 8]

li = [1,2,3,4,5,-98,78,9,7,7]
m  = plus_grande_sous_liste_n2(li)
print(m)   # affiche [79, 9, 7, 7]    

, correction 2012

#coding:latin-1
def plus_grande_sous_liste_rapide_r (li, i,j) :
    if i == j : return 0
    elif i+1 == j : return li[i],i,i+1
    
    milieu = (i+j)//2
    
    # on coupe le problème deux
    ma,ia,ja = plus_grande_sous_liste_rapide_r (li, i, milieu)
    mb,ib,jb = plus_grande_sous_liste_rapide_r (li, milieu, j)
    
    # pour aller encore plus vite dans un cas précis
    if ja == ib :
        total = ma+mb
        im,jm = ia,jb
    else :
        # on étudie la jonction
        im,jm = milieu,milieu+1
        meilleur = li[milieu]
        s = meilleur
        for k in range (milieu+1, j) :
            s += li[k]
            if s > meilleur :
                meilleur = s
                jm = k+1
                
        total = meilleur
        meilleur = li[milieu]
        s = meilleur
        for k in range (milieu-1, i-1, -1) :
            s += li[k]
            if s > meilleur :
                meilleur = s
                im = k
        
        total += meilleur - li[milieu]
            
    if   ma >= max(mb,total) : return ma,ia,ja
    elif mb >= max(ma,total) : return mb,ib,jb
    else : return total,im,jm
        
def plus_grande_sous_liste_rapide (li) :
    m,i,j = plus_grande_sous_liste_rapide_r (li,0,len(li))
    return li[i:j]
        
li = [ 4,-6,7,-1,8,-50,3]
m  = plus_grande_sous_liste_rapide(li)
print(m)   # affiche [7, -1, 8]

li = [1,2,3,4,5,-98,78,9,7,7]
m  = plus_grande_sous_liste_rapide(li)
print(m)   # affiche [79, 9, 7, 7]    

, correction 2012

#-*- coding: latin-1 -*-
def plus_grande_sous_liste_n (li) :
    meilleur = [ None for i in li ]
    somme    = [ None for i in li ]
    best     = None
        
    for i,el in enumerate(li):
        if i == 0 or meilleur[i-1] is None:
            meilleur[i] = i
            somme[i] = el
            if best is None or somme[i] > somme[best]:
                best = i
        else:
            if el >= 0 or somme[i-1] > -el :
                meilleur[i] = meilleur[i-1] 
                somme[i] = somme[i-1] + el
                if best is None or somme[i] > somme[best]:
                    best = i
                
    i,j = meilleur[best], best+1
    return li [i:j]
    
li = [ 4,-6,7,-1,8,-50,3]
m  = plus_grande_sous_liste_n(li)
print(m)   # affiche [7, -1, 8]

li = [1,2,3,4,5,-98,78,9,7,7]
m  = plus_grande_sous_liste_n(li)
print(m)   # affiche [79, 9, 7, 7]    

File: td_note_2013_preparation.tex, line 25


import random
i = random.randint(0,5)

, correction 2013

#coding:latin-1
import random

# question 1
def sequence () :
    res = [ ]
    nb = 1
    while nb > 0 :
        i = random.randint(0,2)
        nb += i - 1
        res.append (i)
    return res

# question 2
def moyenne (nb_tirage) :
    somme = 0.0
    for i in range(nb_tirage) :
        s = sequence()
        somme += len(s)
    return somme / nb_tirage
    
s = sequence ()
print len(s),s
m = moyenne (100)
print m

, correction 2013

#coding:latin-1
import random

def randomint (a,b,c) :
    x = random.random()
    if x <= a : return 0
    elif x <= a+b : return 1
    else : return 2

def sequence (a,b,c) :
    res = [  ]
    nb = 1
    while nb > 0 :
        i = randomint(a,b,c)
        nb += i - 1
        res.append (i)
    return res

def moyenne (nb_tirage,a,b,c) :
    somme = 0.0
    for i in range(nb_tirage) :
        s = sequence(a,b,c)
        somme += len(s)
    return somme / nb_tirage
    
a,c = 0.3, 0.2
b = 1-a-c

moy = 1.0 / (a-c)
print "calcul",moy

m1 = moyenne (100000, a,b,c)
print "simulée", m1

, correction 2013

#coding:latin-1
import random, math

# question 1
def calcul_suite_a (n, e, a,b,c) :
    p = {}
    p [0,0]  = 1
    for u in range (1,n+1) :
        for k in range (e,u+2) :
            if   k == e   : p [u,k] = a * p.get ( (u-1,k+1), 0 )
            elif k == e+1 : p [u,k] = a * p.get ( (u-1,k+1), 0 ) + \
                                      b * p.get ( (u-1,k  ), 0 )
            elif k >  e+1 : p [u,k] = a * p.get ( (u-1,k+1), 0 ) + \
                                      b * p.get ( (u-1,k  ), 0 ) + \
                                      c * p.get ( (u-1,k-1), 0 )
    return p
    
def affiche_proba (ps, e) :
    n     = max ( [ k[1] for k,z in ps.iteritems () ] )
    moy = 0.0
    logru = []
    logu  = []
    for u in range (1, n+1) :
        p = ps.get((u,e),0)*1.0 
        moy += p * u
        mes = "u % 3d P(U=u) %1.6g r_u %1.6g" % (u, p, moy)
        if u < 3 or u %50 == 0 : print mes
        logru.append(math.log(moy))
        logu.append(math.log(u))
        
    import pylab
    pylab.plot ( logu, logru, "o")
    pylab.show()
    
a,c = 1.0/3, 1.0/3
b = 1-a-c
e = -1

su = calcul_suite_a(600,e,a,b,c)
affiche_proba(su, e)

File: td_note_2013_preparation.tex, line 186


u    1 P(U=u) 0.333333    r_u  0.333333
u    2 P(U=u) 0.111111    r_u  0.555556
u   50 P(U=u) 0.0013566   r_u  5.57241
u  100 P(U=u) 0.00048407  r_u  8.38753
u  150 P(U=u) 0.000264311 r_u 10.5627
u  200 P(U=u) 0.000171942 r_u 12.4016
u  250 P(U=u) 0.000123146 r_u 14.0242
u  300 P(U=u) 9.37388e-05 r_u 15.4926
u  350 P(U=u) 7.44204e-05 r_u 16.8438
u  400 P(U=u) 6.09325e-05 r_u 18.1021
u  450 P(U=u) 5.10779e-05 r_u 19.2843
u  500 P(U=u) 4.36202e-05 r_u 20.4028
u  550 P(U=u) 3.78157e-05 r_u 21.4669
u  600 P(U=u) 3.31933e-05 r_u 22.4839

File: td_note_2013_preparation.tex, line 311


import random
N = 10
M = [ [  1 if random.randint(1,5) == 1 else 0 for i in range (N) ] for j in range(N) ]
for l in M : print l
    
nb = 0
for i in range(N) :
    for j in range (N) :
        if   i > 0   and M[i-1][j] == 1 : nb += 1
        elif i < N-1 and M[i+1][j] == 1 : nb += 1
        elif j > 0   and M[i][j-1] == 1 : nb += 1
        elif j < N-1 and M[i][j+1] == 1 : nb += 1
print nb

File: td_note_2013_preparation.tex, line 329


[0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 1, 0, 1, 1]
[0, 0, 0, 0, 1, 0, 1, 1, 0, 1]
[0, 0, 1, 0, 1, 0, 0, 1, 1, 1]
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
46

File: td_note_2013_preparation.tex, line 345


[0, 1, 0]
[0, 0, 1]
[0, 0, 0]
4

File: td_note_2013_preparation.tex, line 391


import random, numpy
N  = 10
M  = [ [  1.0 if random.randint(1,5) == 1 else 0.0 for i in range (N) ] for j in range(N) ]
M  = numpy.matrix(M)
MM = numpy.matrix(M)
for i in range (N) : 
    s = numpy.sum(M[i,:])  # ou M[i,:].sum()
    if s > 0 : MM [i,:] = M [i,:] / s
print MM

File: td_note_2013_preparation.tex, line 406


import random, numpy
N  = 5
M  = [ [  1 if random.randint(1,5) == 1 else 0 for i in range (N) ] for j in range(N) ]
M  = numpy.matrix (M)
MM = numpy.matrix(M)
for i in range (N) : 
    s = numpy.sum(M[i,:])
    if s > 0 : MM [i,:] = M [i,:]*1.0 / s   # multiplication par 1.0
print MM

File: td_note_2013_exoS.tex, line 14


#coding:latin-1
import exoS
matrice = exoS.construit_matrice(100)

File: td_note_2013_exoS.tex, line 21


exoS.dessin_matrice(matrice)   # cette fonction place un point bleu pour une case contenant 1,
                               # rouge pour une case contenant 2,
                               # rien si elle contient 0

File: td_note_2013_exoS.tex, line 31


def voisins_a_valeur_nulle ( matrice, i, j ) :
    resultat = [ ]
    # ...
    return resultat

File: td_note_2013_exoS.tex, line 41


def tous_voisins_a_valeur_nulle ( matrice, liste_points ) :
    resultat = [ ]
    # ...
    return resultat

File: td_note_2013_exoS.tex, line 57


def fonction_coloriage( matrice, i0, j0) :
    # ...

File: td_note_2013.tex, line 20


def surface_coloriee ( matrice ) :
    # ...
    return surface

File: td_note_2013.tex, line 27


def fonction_coloriage_environ_1000 ( matrice, i0, j0 ) :
    # ...
    return surface

, énoncé 2013

#coding:latin-1
import math

# cette fonction construit deux spirales imbriquées dans une matrice nb x nb
# le résultat est retourné sous forme de liste de listes
def construit_matrice (nb) :
    mat = [ [ 0 for x in range (0,nb) ] for y in range(0,nb) ]

    def pointij (nb,r,th,mat,c,phase) :
        i,j = r*th * math.cos(th+phase), r*th*math.sin(th+phase)
        i,j = int(i*100/nb), int(j*100/nb)
        i,j = (i+nb)/2, (j+nb)/2
        if 0 <= i < nb and 0 <= j < nb :
            mat[i][j] = c
        return i,j

    r = 3.5
    t = 0
    for tinc in range (nb*100000) :
        t  += 1.0 * nb / 100000
        th  = t * math.pi * 2
        i,j = pointij (nb,r,th,mat,1, 0)
        i,j = pointij (nb,r,th,mat,1, math.pi)
        if i >= nb and j >= nb : break
        
    return mat
    
# cette fonction reçoit une matrice sous forme de liste de listes contenant des entiers : 0,1,2
# à chaque valeur est associée une couleur :
# 0 pour blanc, 1 pour bleu, 2 pour rouge
def dessin_matrice (matrice) :
    import pylab
    colors = { 1: "blue", 2:"red"  }
    for i in range(0,len(matrice)) :
        for j in range (0, len(matrice[i])) :
            if matrice [i][j] in colors : 
                pylab.plot ([i-0.5,i-0.5,i+0.5,i+0.5,i-0.5,i+0.5,i-0.5,i+0.5], 
                            [j-0.5,j+0.5,j+0.5,j-0.5,j-0.5,j+0.5,j+0.5,j-0.5], 
                        colors [ matrice[i][j] ])
    pylab.show()
    
if __name__ == "__main__" :
    matrice = construit_matrice(100)
    dessin_matrice(matrice)

, correction 2013

#coding:latin-1
import td_note_2013_novembre_2012_exoS as exoS

# question 1, exo S (1 ou 4)
def voisins_a_valeurs_nulle (matrice,i,j) :
    res = []
    if i > 0                 and matrice[i-1][j] == 0 : res.append ( (i-1,j) )
    if i < len(matrice)-1    and matrice[i+1][j] == 0 : res.append ( (i+1,j) )
    if j > 0                 and matrice[i][j-1] == 0 : res.append ( (i,  j-1) )
    if j < len(matrice[i])-1 and matrice[i][j+1] == 0 : res.append ( (i,  j+1) )
    return res
    
# question 2, exo S (1 ou 4)
def tous_voisins_a_valeurs_nulle (matrice, liste_points) :
    res = []
    for i,j in liste_points :
        res += voisins_a_valeurs_nulle (matrice, i,j) 
    return res
    
# question 3, exo S (1 ou 4)
def fonction_coloriage ( matrice, i0, j0) :
    # étage 1
    acolorier = [ ( i0, j0 ) ]
    while len (acolorier) > 0 :
        # étape 2
        for i,j in acolorier : 
            matrice [i][j] = 2
        # étape 3
        acolorier = tous_voisins_a_valeurs_nulle ( matrice, acolorier )
        # on enlève les doublons car sinon cela prend trop de temps
        d = { }
        for i,j in acolorier : d [i,j] = 0
        acolorier = [ (i,j) for i,j in d ]
        
# question 5, exo S (version 1)
def surface_coloriee (matrice) :
    surface = 0
    for line in matrice : 
        for c in line : 
            if c == 2 : surface += 1
    return surface
    
# question 5, exo S (version 4)
def fonction_coloriage_1000 ( matrice, i0, j0) :
    acolorier = [ ( i0, j0 ) ]
    nb = 0                                 # ligne ajoutée
    while len (acolorier) > 0 :
        for i,j in acolorier : 
            matrice [i][j] = 2
            nb += 1                        # ligne ajoutée
        if nb > 1000 : break               # ligne ajoutée
        acolorier = tous_voisins_a_valeurs_nulle ( matrice, acolorier )
        d = { }
        for i,j in acolorier : d [i,j] = 0
        acolorier = [ (i,j) for i,j in d ]

# question 4, exo S (1 ou 4)
matrice = exoS.construit_matrice(100)
fonction_coloriage  (matrice, 53, 53)
exoS.dessin_matrice(matrice)
print surface_coloriee (matrice) # retourne 3258

# question 5, exo S (version 4) vérification
matrice = exoS.construit_matrice(100)
fonction_coloriage_1000  (matrice, 53, 53)
exoS.dessin_matrice(matrice)
print surface_coloriee (matrice) # retourne 1002

File: td_note_2013_exoM.tex, line 4


#coding:latin-1
import exoM
fichier_zip   = exoM.import_module_or_file_from_web_site ("equipements_sportif_2011.zip")
fichier_texte = exoM.unzip_fichier (fichier_zip)
# enlever le dernier paramètre 500 pour avoir le tableau complet
colonne, intitule, variables = exoM.construit_matrice (fichier_texte, 500)  
    # colonne   : contient le nom des colonnes
    # intitule  : contient les deux premières colonnes du fichier textes avec du texte
    # variables : contient les autres colonnes avec des valeurs numériques 

File: td_note_2013_exoM.tex, line 18


import numpy
intitule  = numpy.array(intitule)  # array et non matrix
variables = numpy.array(variables) # array et non matrix

# utilisation de numpy pour sélectionner des lignes spécifiques
print intitule [ intitule[:,1] == "Chevroux", : ]  # affiche [['01102' 'Chevroux']]
print variables[ intitule[:,1] == "Chevroux", : ]  # affiche [[  82.    1.   12 ...

File: td_note_2013_exoM.tex, line 29


print tab.shape                     # si tab est une matrice ou un tableau numpy à deux dimensions,
                                    # tab.shape est un couple (nb_lignes, nb_colonnes)
a = numpy.column_stack ( ( m, e ) ) # coller deux matrices, tableaux ayant le même nombre de lignes

File: td_note_2013_exoM.tex, line 51


# crée une matrice de dimension nb_lignes x nb_colonnes initialisés à zéro
mvide = numpy.zeros ( ( nb_lignes, nb_colonnes) )

File: td_note_2013_exoM.tex, line 64


li = list ( mat [:,i] )           # convertit une colonne d'un tableau numpy en une liste
print colonne[0][i+2]             # affiche le label de la colonne i
gini = exoM.coefficient_gini (li) # retourne le coefficient de Gini
                                  # pour la liste li

, énoncé 2013

#coding:latin-1
import math, sys

# extrait les données depuis un site internet, puis les écrit à côté du programme
# ne fait rien si le fichier a déjà été téléchargé
def import_module_or_file_from_web_site (module) :
    import os
    if os.path.exists ("data\\equipement_sportifs_2011\\" + module) :
        return "data\\equipement_sportifs_2011\\" + module
    if not os.path.exists (module) :
        url = "http://www.xavierdupre.fr/enseignement/complements/" + module
        import urllib2
        if module.lower().endswith("zip") :
            f = urllib2.urlopen (url, "rb")
            t = f.read()
            f.close()
            f = open(module, "wb")
            f.write(t)
            f.close()
        else :
            f = urllib2.urlopen (url)
            t = f.read()
            f.close()
            f = open(module, "w")
            f.write(t)
            f.close()
    return module

# extrait le fichier texte contenu dans le fichier zip
# et l'enregistre à côté du programme
# ne fait rien si cela est déjà fait
def unzip_fichier (fichier_zip) :
    import zipfile, os
    file = zipfile.ZipFile (fichier_zip, "r")
    res = None
    for info in file.infolist () :
        filename = info.filename
        res = filename
        if not os.path.exists (filename) :
            data = file.read(filename)
            f = open (filename,"w")
            if sys.version.startswith("3.") :
                data = str (data, encoding="iso-8859-1")
                data = data.replace("\r","").split("\n")
                data = [ _ for _ in data if len (_) > 1 ]
                data = "\n".join(data)
            f.write (data)
            f.close()
    file.close ()
    return res
    
# construit le tableau extrait du fichier précédent
# les deux premières lignes contiennent la description des colonnes
# les autres lignes contiennent les données elles-même
# pour aller plus vite à chaque exécution, on peut limiter le nombre de lignes
# il faudra toutes les utiliser pour l'exécution final
def construit_matrice (fichier, stop_apres = -1) :
    def float_except(x) :
        try : return float(x)
        except : return -1
    f = open (fichier, "r")
    lines = [ line.replace("\n","").split("\t")[:107] \
            for line in f.readlines()[:stop_apres] ]
    f.close ()
    colonne = lines [:2]
    lines = lines [2: ]
    lines = [ line [:2] + [ float_except(x) for x in line [2:] ] \
            for line in lines if len(line)>5 ]
    intitule = [ line[:2] for line in lines ]
    lines = [ line[2:] for line in lines ]
    return colonne, intitule, lines
    
def coefficient_gini (valeurs) :
    #voir http://fr.wikipedia.org/wiki/Coefficient_de_Gini
    valeurs.sort()
    gini = 0
    s = 0
    for (i,v) in enumerate (valeurs) :
        gini += (i+1)*v
        s += v
    gini = 2*gini / (len(valeurs)*s) - (len(valeurs)+1.0)/len(valeurs)
    return gini

if __name__ == "__main__" :
    fichier_zip   = import_module_or_file_from_web_site ("equipements_sportif_2011.zip")
    fichier_texte = unzip_fichier (fichier_zip)

    # enlever le dernier paramètre 500 pour avoir le tableau complet
    colonne, intitule, variables = construit_matrice (fichier_texte, 500)  

    import numpy
    intitule  = numpy.array(intitule)
    variables = numpy.array(variables)

    # affichage des colonnes
    for i in range (len(colonne[0])) : print (i,colonne[0][i], " --- ", colonne[1][i])
        
    # utilisation de numpy pour sélectionner des lignes spécifiques
    print (intitule  [ intitule[:,1] == "Chevroux", : ])
    print (variables [ intitule[:,1] == "Chevroux", : ])

, correction 2013

#coding:latin-1
import numpy
import td_note_2013_novembre_2012_exoM as exoM

fichier_zip   = exoM.import_module_or_file_from_web_site ("equipements_sportif_2011.zip")
fichier_texte = exoM.unzip_fichier (fichier_zip)

# enlever le dernier paramètre 500 pour avoir le tableau complet
colonne, intitule, variables = exoM.construit_matrice (fichier_texte)  

import numpy
intitule  = numpy.array(intitule)
variables = numpy.array(variables)

# question 1, exo M (2 ou 3)
code_postaux = [ intitule[i,0] [:2] for i in range (intitule.shape[0] ) ]
intitule3    = numpy.column_stack ( (intitule, code_postaux) )

# question 2, exo M (2 ou 3)
comptage = {}
for i in range (intitule3.shape[0]) :
    comptage [intitule3 [i,2] ] = 0
departements = [ k for k in comptage ]
departements.sort()

# question 3, exo M (2 ou 3)
D = numpy.zeros ( (len(departements), variables.shape[1] ) )
for i in range (len (departements)) :
    d = departements [i]
    for j in range (variables.shape[1]) :
        D [i,j] = variables [ intitule3 [:,2] == d, j ].sum()
    
# question 4, exo M (2 ou 3)
E = numpy.zeros ( D.shape )
for i in range (E.shape[0]) :
    E [i,:] = D[i,:] / D[i,5]
    
# question 5, exo M (2 ou 3)
ginis = []
for j in range (E.shape[1]) :
    li = list ( E [:,j] )
    gini = exoM.coefficient_gini (li)
    ginis.append ( (gini, colonne[0][j+2]) )
ginis.sort ()
for line in ginis : print line

# les dernières lignes du tableau sont :
#(0.86910090569180598, 'Domaine skiable')
#(0.88139092467853186, 'Sports nautiques avec au moins une aire de pratique couverte')
#(0.89326137963164931, 'Domaine skiable - nombre de pistes')
#(0.9348918282098031,  'Parcours sportif avec au moins un parcours couvert')
#(0.93902978850018792, 'Domaine skiable avec au moins une piste \xe9clair\xe9e')
#(0.94625459043715754, '\xc9quipement de cyclisme avec au moins une piste couverte')
#(0.95743849241598267, 'Sports nautiques - nombre de places en tribune')
#(0.97248425032547758, 'Domaine skiable avec au moins une piste couverte')
#(0.97718065858676906, 'Parcours sportif - nombre de places en tribune')
#(0.98637386313881081, 'Terrain de golf - nombre de places en tribune')
#(0.98969072164948457, 'Domaine skiable - nombre de places en tribune')

File: td_note_2013_rattrape.tex, line 25


def lit_fichier (file) :
    """
    0 Séance 	
    1 Référence	
    2 Entité dépositaire	
    3 Elu dépositaire	
    4 Objet	
    5 Type	
    6 Rapporteur
    """
    f = open(file,"r")
    lines = f.readlines ()
    f.close ()
    lines = [ _ for _ in lines if len(_) > 0 ]
    lines = [ _.split("\t") for _ in lines ] [1:]
    lines = [ (_[0], _[4] ) for _ in lines if len(_) > 5 ]
    return lines

File: td_note_2013_rattrape.tex, line 58


import re
def extrait_montant (objet) :
    exp = re.compile ("[ (]([0-9.,]+) {0,3}euros")
    res = exp.search (objet)
    if res :
        montant = res.groups() [0]
        return montant
    else :
        print ("problème ", objet)
        return None

File: td_note_2013_rattrape.tex, line 87


exp = re.compile ("association(.*)[(]([0-9]+e)[)]")

, correction 2013

#coding:latin-1
import numpy
import td_note_2013_novembre_2012_exoM as exoM

fichier_zip   = exoM.import_module_or_file_from_web_site ("equipements_sportif_2011.zip")
fichier_texte = exoM.unzip_fichier (fichier_zip)

# enlever le dernier paramètre 500 pour avoir le tableau complet
colonne, intitule, variables = exoM.construit_matrice (fichier_texte)  

import numpy
intitule  = numpy.array(intitule)
variables = numpy.array(variables)

# question 1, exo M (2 ou 3)
code_postaux = [ intitule[i,0] [:2] for i in range (intitule.shape[0] ) ]
intitule3    = numpy.column_stack ( (intitule, code_postaux) )

# question 2, exo M (2 ou 3)
comptage = {}
for i in range (intitule3.shape[0]) :
    comptage [intitule3 [i,2] ] = 0
departements = [ k for k in comptage ]
departements.sort()

# question 3, exo M (2 ou 3)
D = numpy.zeros ( (len(departements), variables.shape[1] ) )
for i in range (len (departements)) :
    d = departements [i]
    for j in range (variables.shape[1]) :
        D [i,j] = variables [ intitule3 [:,2] == d, j ].sum()
    
# question 4, exo M (2 ou 3)
E = numpy.zeros ( D.shape )
for i in range (E.shape[0]) :
    E [i,:] = D[i,:] / D[i,5]
    
# question 5, exo M (2 ou 3)
ginis = []
for j in range (E.shape[1]) :
    li = list ( E [:,j] )
    gini = exoM.coefficient_gini (li)
    ginis.append ( (gini, colonne[0][j+2]) )
ginis.sort ()
for line in ginis : print line

# les dernières lignes du tableau sont :
#(0.86910090569180598, 'Domaine skiable')
#(0.88139092467853186, 'Sports nautiques avec au moins une aire de pratique couverte')
#(0.89326137963164931, 'Domaine skiable - nombre de pistes')
#(0.9348918282098031,  'Parcours sportif avec au moins un parcours couvert')
#(0.93902978850018792, 'Domaine skiable avec au moins une piste \xe9clair\xe9e')
#(0.94625459043715754, '\xc9quipement de cyclisme avec au moins une piste couverte')
#(0.95743849241598267, 'Sports nautiques - nombre de places en tribune')
#(0.97248425032547758, 'Domaine skiable avec au moins une piste couverte')
#(0.97718065858676906, 'Parcours sportif - nombre de places en tribune')
#(0.98637386313881081, 'Terrain de golf - nombre de places en tribune')
#(0.98969072164948457, 'Domaine skiable - nombre de places en tribune')

extrait 1 à copier pour l'énoncé de décembre 2013


def deux_recherches(element, liste_impaire, liste_paire) :
    # ....
    return position_dans_liste_impaire, position_dans_liste_paire

vérifier que tous les éléments de la liste sont bien retrouvés


l = [ 0, 2, 4, 6, 8, 100, 1000 ]
for i in l :
    print (i,recherche_dichotomique(i, l)) 

, énoncé 2014

#coding: latin-1

######### énoncé 1, exercice 1, recherche dichotomique

## question 1 

def recherche_dichotomique( element, liste_triee ):
    """
    premier code: http://www.xavierdupre.fr/blog/2013-12-01_nojs.html    
    """
    a = 0
    b = len(liste_triee)-1
    m = (a+b)//2
    while a < b :
        if liste_triee[m] == element :
            return m
        elif liste_triee[m] > element :
            b = m-1
        else :
            a = m+1
        m = (a+b)//2
    return a
    
l = [ 0, 2, 4, 6, 8, 100, 1000 ]
print (recherche_dichotomique(100, l))  # affiche 5

## question 2

def deux_recherches(element,liste_impair,liste_pair) :
    if element % 2 == 0 :
        return recherche_dichotomique(element, liste_pair), -1
    else :
        return -1, recherche_dichotomique(element, liste_impair)

lp = [ 0, 2, 4, 6, 8, 100, 1000 ]
li = [ 1, 3, 5 ]
print (deux_recherches(100, li, lp))  # affiche (5, -1)

## question 3
"""       
                            liste coupée       liste non coupée (2n)
recherche simple                1 + n                 2n
recherche dichotomique          1 + ln n             ln(2n) = 1 + ln(n)

coût équivalent
"""

## question 4 

def recherche_dichotomique( element, liste_triee ):
    a = 0
    b = len(liste_triee)-1
    m = (a+b)//2
    while a < b :
        if liste_triee[m] == element :
            return m
        elif liste_triee[m] > element :
            b = m-1
        else :
            a = m+1
        m = (a+b)//2
    if liste_triee[a] != element :  return -1       # ligne ajoutée
    else : return m                                 # ligne ajoutée
    
l = [ 0, 2, 4, 6, 8, 100, 1000 ]
for i in l :
    print (i,recherche_dichotomique(i, l))  
    # vérifier qu'on retrouve tous les éléments existant
print (recherche_dichotomique(1, l))   # affiche -1

## question  5

def deux_recherches(element,liste_impair,liste_pair) :
    i = recherche_dichotomique(element, liste_impair)
    if i == -1 : return recherche_dichotomique(element, liste_pair)
    else : return i
    
##question 6 

"""
Les logarithmes sont en base 2.

coût fonction question 2 : 1001 ( 1 + ln(n) )      = C1
coût fonction question 5 : 1000 ln(n)  + 2 ln(n)   = C2
C2 - C1 = ln(n) - 1001 > 0
    
La fonction 5 est plus rapide dans ce cas.
"""

cas où la recherche n'est plus dichotomique


def recherche_dichotomique( element, liste_triee ):
    if element not in list_triee : return -1 # ligne A
    a = 0
    b = len(liste_triee)-1
    m = (a+b)//2
    while a < b :
        if liste_triee[m] == element :
            return m
        elif liste_triee[m] > element :
            b = m-1
        else :
            a = m+1
        m = (a+b)//2
    return a

File: td_note_2014.tex, line 110


def deux_recherches(element,liste_impair,liste_pair) :
    if recherche_dichotomique(element, liste_impair) == -1 : 
       return recherche_dichotomique(element, liste_pair)
    else : return recherche_dichotomique(element, liste_impair)

, énoncé 2014

#coding: latin-1

######### énoncé 1, exercice 2 distance de Levenstein

## question 1 

def distance_edition(mot1, mot2):
    """
    première fonction retrouvée à : http://www.xavierdupre.fr/blog/2013-12-02_nojs.html
    """
    dist = { (-1,-1): 0 }
    for i,c in enumerate(mot1) :
        dist[i,-1] = dist[i-1,-1] + 1
        dist[-1,i] = dist[-1,i-1] + 1
        for j,d in enumerate(mot2) :
            opt = [ ]
            if (i-1,j) in dist :
                x = dist[i-1,j] + 1
                opt.append(x)
            if (i,j-1) in dist :
                x = dist[i,j-1] + 1
                opt.append(x)
            if (i-1,j-1) in dist :
                x = dist[i-1,j-1] + (1 if c != d else 0)
                opt.append(x)
            dist[i,j] = min(opt)
    return dist[len(mot1)-1,len(mot2)-1]

print ("****1*")
print (distance_edition("levenstein","levenshtein"))    # 1
print (distance_edition("bonbon","bonbom"))             # 1
print (distance_edition("example","exemples"))          # 2
print (distance_edition("esche","eche"))                # 1

## question 2

print ("****2*")
print (distance_edition("levenshtein","levenstein"))    # 1
print (distance_edition("bonbom","bonbon"))             # 1
print (distance_edition("exemples","example"))          # 2
print (distance_edition("eche","esche"))                # 1

## question 3

def distance_edition(mot1, mot2):
    dist = { (-1,-1): 0 }
    for i,c in enumerate(mot1) :
        dist[i,-1] = dist[i-1,-1] + 1
        dist[-1,i] = dist[-1,i-1] + 1
        for j,d in enumerate(mot2) :
            opt = [ ]
            if (i-1,j) in dist :
                x = dist[i-1,j] + 1
                opt.append(x)
            if (i,j-1) in dist :
                x = dist[i,j-1] + 1
                opt.append(x)
            if (i-1,j-1) in dist :
                if c == d : x = dist[i-1,j-1]                                       ##
                elif c in ['n','m'] and d in ['n','m'] : x = dist[i-1,j-1] + 0.5    ##
                else : x = dist[i-1,j-1] + 1                                        ## 
                opt.append(x)
            dist[i,j] = min(opt)
    return dist[len(mot1)-1,len(mot2)-1]

print ("****3*")
print (distance_edition("levenstein","levenshtein"))    # 1
print (distance_edition("bonbon","bonbom"))             # 0.5
print (distance_edition("example","exemples"))          # 2
print (distance_edition("esche","eche"))                # 1
print (distance_edition("levenshtein","levenstein"))    # 1
print (distance_edition("bonbom","bonbon"))             # 0.5
print (distance_edition("exemples","example"))          # 2
print (distance_edition("eche","esche"))                # 1

## question 4

def distance_edition(mot1, mot2):
    dist = { (-1,-1): 0 }
    for i,c in enumerate(mot1) :
        dist[i,-1] = dist[i-1,-1] + 1
        dist[-1,i] = dist[-1,i-1] + 1
        for j,d in enumerate(mot2) :
            opt = [ ]
            if (i-1,j) in dist :
                if c == "s" :  x = dist[i-1,j] + 0.5    ## 
                else : x = dist[i-1,j] + 1              ## 
                opt.append(x)
            if (i,j-1) in dist :
                if d == "s" : x = dist[i,j-1] + 0.5     ##
                else : x = dist[i,j-1] + 1              ##
                opt.append(x)
            if (i-1,j-1) in dist :
                if c == d : x = dist[i-1,j-1] 
                elif c in ['n','m'] and d in ['n','m'] : x = dist[i-1,j-1] + 0.5
                else : x = dist[i-1,j-1] + 1
                opt.append(x)
            dist[i,j] = min(opt)
    return dist[len(mot1)-1,len(mot2)-1]

print ("****4*")
print (distance_edition("levenstein","levenshtein"))    # 1
print (distance_edition("bonbon","bonbom"))             # 0.5
print (distance_edition("example","exemples"))          # 1.5
print (distance_edition("esche","eche"))                # 0.5
print (distance_edition("levenshtein","levenstein"))    # 1
print (distance_edition("bonbom","bonbon"))             # 0.5
print (distance_edition("exemples","example"))          # 1.5
print (distance_edition("eche","esche"))                # 0.5

## question 5

def distance_edition(mot1, mot2):
    dist = { (-1,-1): 0 }
    for i,c in enumerate(mot1) :
        dist[i,-1] = dist[i-1,-1] + 1
        dist[-1,i] = dist[-1,i-1] + 1
        for j,d in enumerate(mot2) :
            opt = [ ]
            if (i-1,j) in dist :
                if c == "s" :  
                    if i == len(mot1)-1 : x = dist[i-1,j] + 0.2 ##
                    else : x = dist[i-1,j] + 0.5                ##
                else : x = dist[i-1,j] + 1
                opt.append(x)
            if (i,j-1) in dist :
                if d == "s" : 
                    if j == len(mot2)-1 : x = dist[i,j-1] + 0.2 ##
                    else : x = dist[i,j-1] + 0.5                ##
                else : x = dist[i,j-1] + 1                      
                opt.append(x)
            if (i-1,j-1) in dist :
                if c == d : x = dist[i-1,j-1] 
                elif c in ['n','m'] and d in ['n','m'] : x = dist[i-1,j-1] + 0.5
                else : x = dist[i-1,j-1] + 1
                opt.append(x)
            dist[i,j] = min(opt)
    return dist[len(mot1)-1,len(mot2)-1]

print ("****5*")
print (distance_edition("levenstein","levenshtein"))    # 1
print (distance_edition("bonbon","bonbom"))             # 0.5
print (distance_edition("example","exemples"))          # 1.2
print (distance_edition("esche","eche"))                # 0.5
print (distance_edition("levenshtein","levenstein"))    # 1
print (distance_edition("bonbom","bonbon"))             # 0.5
print (distance_edition("exemples","example"))          # 1.2
print (distance_edition("eche","esche"))                # 0.5

File: td_note_2014.tex, line 176


if (i-1,j-1) in dist :
    x = dist[i-1,j-1] + (0.5 if c != d else 0)  # 1 --> 0.5

, énoncé 2014

#coding: latin-1

######### énoncé 2, exercice 3 distance de Levenstein

## question 1 

def distance_edition(mot1, mot2):
    """
    première fonction retrouvée à : http://www.xavierdupre.fr/blog/2013-12-02_nojs.html
    """
    dist = { (-1,-1): 0 }
    for i,c in enumerate(mot1) :
        dist[i,-1] = dist[i-1,-1] + 1
        dist[-1,i] = dist[-1,i-1] + 1
        for j,d in enumerate(mot2) :
            opt = [ ]
            if (i-1,j) in dist :
                x = dist[i-1,j] + 1
                opt.append(x)
            if (i,j-1) in dist :
                x = dist[i,j-1] + 1
                opt.append(x)
            if (i-1,j-1) in dist :
                x = dist[i-1,j-1] + (1 if c != d else 0)
                opt.append(x)
            dist[i,j] = min(opt)
    return dist[len(mot1)-1,len(mot2)-1]

print ("****1*")
print (distance_edition("levenstein","levenstien"))     # 2
print (distance_edition("bonbbon","bonbon"))            # 1
print (distance_edition("example","exemples"))          # 2

## question 2

print ("****2*")
print (distance_edition("levenstien","levenstein"))     # 2
print (distance_edition("bonbon","bonbbon"))            # 1
print (distance_edition("exemples","example"))          # 2

## question 3

def distance_edition(mot1, mot2):
    """
    première fonction retrouvée à : http://www.xavierdupre.fr/blog/2013-12-02_nojs.html
    """
    dist = { (-1,-1): 0 }
    for i,c in enumerate(mot1) :
        dist[i,-1] = dist[i-1,-1] + 1
        dist[-1,i] = dist[-1,i-1] + 1
        for j,d in enumerate(mot2) :
            opt = [ ]
            if (i-1,j) in dist :
                x = dist[i-1,j] + 1
                opt.append(x)
            if (i,j-1) in dist :
                x = dist[i,j-1] + 1
                opt.append(x)
            if (i-1,j-1) in dist :
                x = dist[i-1,j-1] + (1 if c != d else 0)
                opt.append(x)
            if (i-2,j-2) in dist :                          ##
                if c == mot2[j-1] and d == mot1[i-1] :      ##
                    x = dist[i-2,j-2] + 1                   ##
                    opt.append(x)                           ##
            dist[i,j] = min(opt)
    return dist[len(mot1)-1,len(mot2)-1]

print ("****3*")
print (distance_edition("levenstein","levenstien"))     # 1
print (distance_edition("bonbbon","bonbon"))            # 1
print (distance_edition("example","exemples"))          # 2
print (distance_edition("levenstien","levenstein"))     # 1
print (distance_edition("bonbon","bonbbon"))            # 1
print (distance_edition("exemples","example"))          # 2

## question 4

def distance_edition(mot1, mot2):
    """
    première fonction retrouvée à : http://www.xavierdupre.fr/blog/2013-12-02_nojs.html
    """
    dist = { (-1,-1): 0 }
    for i,c in enumerate(mot1) :
        dist[i,-1] = dist[i-1,-1] + 1
        dist[-1,i] = dist[-1,i-1] + 1
        for j,d in enumerate(mot2) :
            opt = [ ]
            if (i-1,j) in dist :
                x = dist[i-1,j] + 1
                opt.append(x)
            if (i,j-1) in dist :
                x = dist[i,j-1] + 1
                opt.append(x)
            if (i-1,j-1) in dist :
                x = dist[i-1,j-1] + (1 if c != d else 0)
                opt.append(x)
            if (i-2,j-2) in dist :                          
                if c == mot2[j-1] and d == mot1[i-1] :      
                    x = dist[i-2,j-2] + 1                   
                    opt.append(x)
            if (i-2,j-1) in dist and c == d == mot1[i-1] :  ##
                    x = dist[i-2,j-1] + 0.45                ##
                    opt.append(x)                           ##
            if (i-1,j-2) in dist and c == d == mot2[j-1] :  ##
                    x = dist[i-1,j-2] + 0.45                ##
                    opt.append(x)                           ##
            dist[i,j] = min(opt)
    return dist[len(mot1)-1,len(mot2)-1]

print ("****4*")
print (distance_edition("levenstein","levenstien"))     # 1
print (distance_edition("bonbbon","bonbon"))            # 0.45
print (distance_edition("example","exemples"))          # 2
print (distance_edition("levenstien","levenstein"))     # 1
print (distance_edition("bonbon","bonbbon"))            # 0.45
print (distance_edition("exemples","example"))          # 2

File: td_note_2014.tex, line 252


if abs(i-j)==1 and mot1[i]==mot2[j] and (mot1[i+1]==mot2[j-1] or mot1[i-1]==mot2[j+1]):

File: td_note_2014.tex, line 260


if abs(j-i)==1 and mot1[i]==mot2[j] and (mot1[i+1]==mot2[j-1] or mot1[i-1]==mot2[j+1]):
	dist[i,j] = min(opt)-1
else:
	dist[i,j]=min(opt)

vérifier que tous les éléments de la liste sont bien retrouvés


l = [ 0, 2, 4, 6, 8, 100, 1000 ]
for i in l :
    print (i,recherche_dichotomique(i, l)) 

extrait 2 à copier pour l'énoncé de décembre 2013


def deux_recherches(element, liste1, liste2) :
    # ....
    return position_dans_liste1, position_dans_liste2

, énoncé 2014

#coding: latin-1

######### énoncé 1, exercice 1, recherche dichotomique

## question 1 

def recherche_dichotomique( element, liste_triee ):
    """
    premier code: http://www.xavierdupre.fr/blog/2013-12-01_nojs.html    
    """
    a = 0
    b = len(liste_triee)-1
    m = (a+b)//2
    while a < b :
        if liste_triee[m] == element :
            return m
        elif liste_triee[m] > element :
            b = m-1
        else :
            a = m+1
        m = (a+b)//2
    return a
    
l =  [ 0, 2, 3, 5, 10, 100, 340 ]
print (recherche_dichotomique(100, l))  # affiche 5

## question 2

def recherche_dichotomique( element, liste_triee ):
    a = 0
    b = len(liste_triee)-1
    m = (a+b)//2
    while a < b :
        if liste_triee[m] == element :
            return m
        elif liste_triee[m] > element :
            b = m-1
        else :
            a = m+1
        m = (a+b)//2
    if liste_triee[a] != element :  return -1       # ligne ajoutée
    else : return m    
    
    
l = [ 0, 2, 4, 6, 8, 100, 1000 ]
for i in l :
    print (i,recherche_dichotomique(i, l))  
    # vérifier qu'on retrouve tous les éléments existant
print (recherche_dichotomique(1, l))   # affiche -1


## question 3

def deux_recherches(element,liste1,liste2) :
    return recherche_dichotomique(element, liste1) ,  \
            recherche_dichotomique(element,liste2)
            
l1 = [ 0, 2, 4, 6, 8, 100, 1000 ]
l2 = [ 1200, 3000, 4000, 5555 ]
print (deux_recherches(100,l1,l2) )    # affiche (5,-1)

## question 4 

"""
Les logarithmes sont en base 2.

cas 1 : 1000 ln(n) + 10 (ln(n) + ln(10n)) = 1020 ln(n) + 10 ln(10) = C1
cas 2 : 1010 ln(n + 10n) = 1010 ln(n) + 1010 ln(11)                = C2
delta = C2 - C1 = -10 ln(n) + 1010 ln(11) - 10 ln(10)

Conclusion : pour n petit, le cas C1 est préférable, pour les n grands, c'est le cas 2.
"""

## question 5

def deux_recherches(element,liste1,liste2) :
    if element > liste1[-1] :
        return -1, recherche_dichotomique(element, liste2) 
    else :
        return recherche_dichotomique(element,liste1), -1
            
l1 = [ 0, 2, 4, 6, 8, 100, 1000 ]
l2 = [ 1200, 3000, 4000, 5555 ]
print (deux_recherches(100,l1,l2) )    # affiche (5,-1)

File: td_note_2015.tex, line 51


suites_chemin( [ 0, 1 ], dico ) --> [ [ 0, 1, 2 ] ]
suites_chemin( [ 0, 1, 2 ], dico ) --> [  ]   # il n'y pas de suite possible

vérifier que tous les éléments de la liste sont bien retrouvés


%l = [ 0, 2, 4, 6, 8, 100, 1000 ]
%for i in l :
%    print (i,recherche_dichotomique(i, l)) 
%

File: td_note_2015.tex, line 150


dictionnaire [  i,j  ]
dictionnaire [ (i,j) ]

File: td_note_2015.tex, line 157


mot --> { 0:'', 1:'m', 2:'mo', 3:'mot' }

File: td_note_2015.tex, line 166


vertices = {  (i,j): (d1[i],d2[j]) }

File: td_note_2015.tex, line 184


edges = { (i1,j1),(i2,j2) : valeur }

File: td_note_2015.tex, line 190


edges [ (i1,j1),(i2,j2) ] = 1 si  (i2-i1 == 1 et j1 == j2) ou (j2-j1 == 1 et i1 == i2)

File: td_note_2016.tex, line 26


def rendement(x, n, r):
    # ....
    return

File: td_note_2016.tex, line 34


def decompose_mensualite(K,M,p):
    # ...
    return capital, interet

File: td_note_2016.tex, line 43


def mensualites(K,M,p):
    # ....
    return [ liste de mensualités ]

File: td_note_2016.tex, line 52


def somme_maximale(M,p,Y):
    # ....
    return K max

File: td_note_2016.tex, line 61


def economie(A,S,L,r,Y):
    # ....
    return economie

File: td_note_2016.tex, line 81


def bascule(A,S,L,r,Y,C,p):
    # ....
    return nombre d'années

File: td_note_2016.tex, line 90


def surface_max(A,L,r,Y,C,p,delay=20):
    # ....
    return surface

File: td_note_2016.tex, line 116


adele   06 64 34 22 67 --> 06 46 34 22 67  lettres 06 aa dd ee ll  
gerard  06 64 34 22 68 --> 06 64 43 22 86  lettres 06 gg ee rr aa

File: td_note_2016.tex, line 124


def transforme_numero(prenom, numero):
    # ....
    return 

File: td_note_2016.tex, line 158


Adèle   06 64 34 22 67 --> 06 60 34 24 67  lettres 06 aa dd ee ll  
Gérard  06 64 34 22 68 --> 06 64 37 22 64  lettres 06 gg ee rr aa

File: td_note_2016.tex, line 166


def transforme_numero(prenom, numero):
    # ....
		return 

File: td_note_2016.tex, line 198


def rendement(x, n, r):
    # ....
    return

File: td_note_2016.tex, line 206


def mensualites(K,M,p):
    # ....
    return [ liste de mensualités ]

File: td_note_2016.tex, line 215


def somme_maximale(M,p,Y):
    # ....
    return K max

File: td_note_2016.tex, line 224


def economie(A,S,L,r,Y):
    # ....
    return economie

File: td_note_2016.tex, line 233


def bascule(A,S,L,r,Y,C,p):
    # ....
    return nombre d'années

File: td_note_2016.tex, line 256


def A40a30(L,r,Y,C,p):
    # ....
    return surface

, correction 2012

# coding: latin-1
# question 1
def frequence_lettre (mot) :
    res = { }
    for c in mot :
        if c in res : res[c] += 1
        else : res [c] = 1
    return res
    
print frequence_lettre ("aviateur")
# affiche {'a': 2, 'e': 1, 'i': 1, 'r': 1, 'u': 1, 't': 1, 'v': 1}

# Deux autres écritures de la fonction
def frequence_lettre (mot) :
    res = { c:0 for c in mot }
    for c in mot : res[c] += 1
    return res
    
def frequence_lettre (mot) :
    res = { }
    for c in mot : 
        # la méthode get retourne res[c] si cette valeur existe, 0 sinon
        res[c] = res.get( c, 0 ) + 1
    return res
    
# question 2

def anagramme (mot1, mot2) :
    h1 = frequence_lettre(mot1)
    h2 = frequence_lettre(mot2)
    
    # il fallait éviter d'écrire la ligne suivante bien qu'elle retourne le résultat cherché :
    # return h1 == h2
    
    for c in h1 :
        if c not in h2 or h1[c] != h2[c] : return False
    # il ne faut pas oublier cette seconde partie
    for c in h2 :
        if c not in h1 : return False
    return True
    
a,b = "anagramme", "agrammane"
print anagramme (a,b), anagramme (b,a) # affiche True, True

# on vérifie que la fonctionne marche aussi dans l'autre cas
a,b = "anagramme", "agrummane"
print anagramme (a,b), anagramme (b,a) # affiche False, False

# on pouvait faire plus rapide en éliminant les cas évidents
def anagramme (mot1, mot2) :
    if len(mot1) != len(mot2) : return False
    h1 = frequence_lettre(mot1)
    h2 = frequence_lettre(mot2)
    if len(h1) != len(h2) : return False

    for c in h1 :
        if h1[c] != h2.get(c, 0) : return False
    return True

, correction 2012

# coding: latin-1

# question 1

def factorielle (n) :
    res = 1
    while n > 1 : 
        res *= n
        n -= 1
    return res
    
print factorielle (3)
    
# voici la version récursive qui n'était pas demandée :    
def factorielle_recursive (n) :
    return n*factorielle_recursive (n-1) if n > 1 else 1
        
# question 2

def f(a,b) :
    
    # f(a,b) = f(a-1,b) + f(a,b-1)
    # la formule implique de calculer toutes les valeurs f(i,j)
    # avec (i,j) dans [[0,a]] x [[0,b]]
    # un moyen afin d'éviter de trop nombreux calculs est de 
    # stocker les valeurs intermédiaires de f dans une matrice
    # il faut ensuite s'assurer que f(a-1,b) et f(a,b-1) 
    # ont déjà été calculées avant de calculer f(a,b)
    # pour cela, on parcourt la matrice dans le sens des i et j croissants
    # il ne faut pas oublier les a+1,b+1 car range (a) est égal à [ 0,1, ..., a-1 ]
    
    mat = [ [ 0 for i in range (b+1) ] for j in range (a+1) ]
    for i in range (a+1) :
        for j in range (b+1) :
                if i == 0 or j == 0 :
                    mat [i][j] = max (i,j)
                else :
                    mat [i][j] = mat [i-1][j] + mat[i][j-1]
    return mat [a][b]

# on teste pour des valeurs simples
print f(0,5) # affiche 5
print f(1,1) # affiche 2
# on vérifie en suite que cela marche pour a < b et b > a
print f (4,5)  # affiche 210
print f (5,4)  # affiche 210

# autres variantes

# la version récursive ci-dessous est juste beaucoup plus longue, elle appelle
# la fonction f_recursive autant de fois que la valeur retournée 
# par la fonction cout_recursive alors que la fonction précédente 
# effectue de l'ordre de O(a*b) calculs
def f_recursive(a,b) :
    return f_recursive(a-1,b) + f_recursive(a,b-1) if a > 0 and b > 0 else max(a,b)

def cout_recursive(a,b) :
    return cout_recursive(a-1,b) + cout_recursive(a,b-1) if a > 0 and b > 0 else 1

# une autre version non récursive
def f(a,b) :
    mat = { }
    for i in range (a+1) :
        for j in range (b+1) :
                mat [i,j] = mat [i-1,j] + mat[i,j-1] if i > 0 and j > 0 else max (i,j)
    return mat [a,b]

, correction 2012

def f_recursive(a,b, memoire) :
    if (a,b) in memoire : return memoire [a,b]
    else : 
        res = f_recursive(a-1,b, memoire) + f_recursive(a,b-1, memoire) \
                    if a > 0 and b > 0 else max(a,b)
        memoire [a,b] = res
        return res

, correction 2012

# coding: latin-1

# question 1

def somme_partielle (li, i, j) :
    r = 0
    for a in range (i,j) :
        r += li [a]
    return r
    
# question 2

def plus_grande_sous_liste (li) :
    meilleur = min(li)               # ligne A
    im,jm = -1,-1
    for i in range (0,len(li)) :
        for j in range (i+1, len(li)+1) :   # ne pas oublier +1 car sinon
                        # le dernier élément n'est jamais pris en compte
            s = somme_partielle(li, i,j)
            if s > meilleur :
                meilleur = s
                im,jm = i,j
    return li [im:jm]
    
# si li ne contient que des valeurs positives, la solution est évidemment la liste entière
# c'est pourquoi il faut tester cette fonction avec des valeurs négatives
li = [ 4,-6,7,-1,8,-50,3]
m  = plus_grande_sous_liste(li)
print(m)   # affiche [7, -1, 8]

li = [1,2,3,4,5,-98,78,9,7,7]
m  = plus_grande_sous_liste(li)
print(m)   # affiche [79, 9, 7, 7]

# autre version plus courte

def plus_grande_sous_liste (li) :
    solution = [ (somme_partielle(li,i,j), i, j) \
                    for i in range (0,len(li)) \
                    for j in range (i+1, len(li)+1) ]
    m = max(solution)
    return li [m[1]:m[2]]

, correction 2012

def plus_grande_sous_liste_n2 (li) :
    meilleur = 0
    im,jm = -1,-1
    for i in range (0,len(li)) :
        s = 0
        for j in range (i, len(li)) :
            s += li[j]
            if s > meilleur :
                meilleur = s
                im,jm = i,j+1
    return li [im:jm]
    
li = [ 4,-6,7,-1,8,-50,3]
m  = plus_grande_sous_liste_n2(li)
print(m)   # affiche [7, -1, 8]

li = [1,2,3,4,5,-98,78,9,7,7]
m  = plus_grande_sous_liste_n2(li)
print(m)   # affiche [79, 9, 7, 7]    

, correction 2012

#coding:latin-1
def plus_grande_sous_liste_rapide_r (li, i,j) :
    if i == j : return 0
    elif i+1 == j : return li[i],i,i+1
    
    milieu = (i+j)//2
    
    # on coupe le problème deux
    ma,ia,ja = plus_grande_sous_liste_rapide_r (li, i, milieu)
    mb,ib,jb = plus_grande_sous_liste_rapide_r (li, milieu, j)
    
    # pour aller encore plus vite dans un cas précis
    if ja == ib :
        total = ma+mb
        im,jm = ia,jb
    else :
        # on étudie la jonction
        im,jm = milieu,milieu+1
        meilleur = li[milieu]
        s = meilleur
        for k in range (milieu+1, j) :
            s += li[k]
            if s > meilleur :
                meilleur = s
                jm = k+1
                
        total = meilleur
        meilleur = li[milieu]
        s = meilleur
        for k in range (milieu-1, i-1, -1) :
            s += li[k]
            if s > meilleur :
                meilleur = s
                im = k
        
        total += meilleur - li[milieu]
            
    if   ma >= max(mb,total) : return ma,ia,ja
    elif mb >= max(ma,total) : return mb,ib,jb
    else : return total,im,jm
        
def plus_grande_sous_liste_rapide (li) :
    m,i,j = plus_grande_sous_liste_rapide_r (li,0,len(li))
    return li[i:j]
        
li = [ 4,-6,7,-1,8,-50,3]
m  = plus_grande_sous_liste_rapide(li)
print(m)   # affiche [7, -1, 8]

li = [1,2,3,4,5,-98,78,9,7,7]
m  = plus_grande_sous_liste_rapide(li)
print(m)   # affiche [79, 9, 7, 7]    

, correction 2012

#-*- coding: latin-1 -*-
def plus_grande_sous_liste_n (li) :
    meilleur = [ None for i in li ]
    somme    = [ None for i in li ]
    best     = None
        
    for i,el in enumerate(li):
        if i == 0 or meilleur[i-1] is None:
            meilleur[i] = i
            somme[i] = el
            if best is None or somme[i] > somme[best]:
                best = i
        else:
            if el >= 0 or somme[i-1] > -el :
                meilleur[i] = meilleur[i-1] 
                somme[i] = somme[i-1] + el
                if best is None or somme[i] > somme[best]:
                    best = i
                
    i,j = meilleur[best], best+1
    return li [i:j]
    
li = [ 4,-6,7,-1,8,-50,3]
m  = plus_grande_sous_liste_n(li)
print(m)   # affiche [7, -1, 8]

li = [1,2,3,4,5,-98,78,9,7,7]
m  = plus_grande_sous_liste_n(li)
print(m)   # affiche [79, 9, 7, 7]    

File: interro_rapide_45_minutes_2012_12.tex, line 24


s = [ random.randint(0,20) for i in range(0,10000) ]

, correction 2012

#coding:latin-1
# correction exerice 1
import random

# question 1, version 1 (version abrégée)
def ecart_moyen (s) :
    positions = [ j for j,e in enumerate(s) if e == 0 ]
    dd = [ positions[j] - positions[j-1] for j in range(1,len(positions)) ]
    # une division entière retourne 0, il faut multiplier par 1.0
    return 1.0*sum(dd) / len(dd)
    
s = [ random.randint(0,20) for i in range(0,10000) ]
print ecart_moyen(s)
    
# question 1, version 2 (version plus longue)
def ecart_moyen (s) :
    positions = [ ]
    for j in range(len(s)) :
        if s[j] == 0 : positions.append (j)
    ecart = 0
    for j in range(len(positions)-1) :
        ecart += positions[j+1] - positions[j]
    # on 
    return ecart*1.0 / (len(positions)-1)

# question 1, version 3 (version courte + astuce)
def ecart_moyen (s) :
    # moyenne des écarts = (dernière position - première position) / (nombre de positions - 1)
    positions = [ j for j,e in enumerate(s) if e == 0 ]
    return (positions [-1] - positions [0])*1.0 / (len(positions)-1)

# question 2, version 1
def tirage_sans_remise () :
    l = [ random.randint(0,20) ]
    while len(l) < 4 :
        x = random.randint(0,20)
        if x not in l : l.append (x)
    return l

def moyenne () :
    s = 0
    for i in range(0,10000) :
        l = tirage_sans_remise ()
        l.sort()
        s1 = l[0]+l[1]
        s2 = l[2]+l[3]
        if s1*2 >= s2 : s+=1
    return s*1.0/10000
    
print "v1", moyenne()

# question 2, version 2
def tirage_sans_remise () :
    l = range(0,20)
    random.shuffle(l)
    return l[:4]

def moyenne () :
    s = 0
    for i in range(0,10000) :
        l = tirage_sans_remise ()
        l.sort()
        s1 = l[0]+l[1]
        s2 = l[2]+l[3]
        if s1*2 >= s2 : s+=1
    return s*1.0/10000
    
print "v2",moyenne()

# question 3
def combinaison (N = 100) :
    # res [ n,p ]
    res = { }
    res [0,0] = res [1,0] = res[1,1] = 1.0
    for n in range (2, N) :
        res [n,0] = 1.0
        res [n,n] = 1.0
        for p in range (1,n/2+1) :
            res [n,p]   = res [n-1,p] + res[n-1,p-1]
            res [n,n-p] = res [n,p]
    return res
    
if False :  #  pour éviter des affichages trop longs
    d = combinaison (100)
    for n,p in sorted(d) :
        print "c(n=%d,p=%s)=%f" % (n,p,d[n,p])

# question 4
def ordonne (mat) :
    # on concatène toutes les lignes
    suml = [ ]
    for l in mat : suml += l
    # on trie
    suml.sort()
    # et on crée une autre matrice
    nc = len(mat[0])  #nombre de colonne
    res = [ suml[ i*nc: i*nc+nc] for i in range (0, len(mat)) ]
    return res
    
l = [[4,5], [3, 7], [1,2] ]
print ordonne(l) # affiche [[1, 2], [3, 4], [5, 7]]

File: interro_rapide_45_minutes_2012_12.tex, line 81


li = [[0, 1, 2, 4], [4, 5, 6, 8], [8, 9, 10, 12], [12, 13, 14, 16]]
random.shuffle(li)
print li  # example : [[8, 9, 10, 12], [12, 13, 14, 16], [4, 5, 6, 8], [0, 1, 2, 4]]

File: interro_rapide_45_minutes_2012_12.tex, line 92


l = ["chat", "chats", "chien", "chiens", "cheval", "chevaux" ]
def nombre_moyen_voyelles (l) :
   ...

File: interro_rapide_45_minutes_2012_12.tex, line 108


mots  = ["paris", "texas", "montmartre", "wim", "wenders", "france"]
texte = "paris texas est un film de wim wenders ce paris n'est pas en france mais au texas"]

, correction 2012

#coding:latin-1
# correction exerice 2
import random

# question 1, version 1
# l'astuce consiste à transposer la matrice
def shuffle_colonne (li) :
    tr  = [ [ li [j][i] for j in range(len(li[0])) ] for i in range(len(li))] 
    random.shuffle(tr)
    res = [ [ tr [j][i] for j in range(len(tr[0])) ] for i in range(len(tr))] 
    return res
    
li = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
print shuffle_colonne (li)

# question 2 
def nombre_moyen_voyelle (l) :
    s = 0   # nombre total de voyelles
    ts = 0  # nombre total de lettres
    for m in l :
        ts += len(m)
        for c in m :
            if c in "aeiouy" : s += 1
    return s * 1.0 / ts

l = ["chat", "chats", "chien", "chiens", "cheval", "chevaux" ]
print "voyelle", nombre_moyen_voyelle (l)  #  0.3333

# question 3
def tirage_avec_remise () :
    l = [ random.randint(0,20) for i in range(0,4) ]
    l.sort()
    return l
    
def moyenne () :
    s = 0
    for i in range(0,10000) :
        l = tirage_avec_remise ()
        l.sort()
        s1 = l[0]+l[1]
        s2 = l[2]+l[3]
        if s1*2 >= s2 : s+=1
    return s*1.0/10000
    
print "v1", moyenne()

# question 4, version 1
def compte_pairs (mots, texte) :
    p = 0
    for m in mots :
        for mm in mots :
            t = m + " " + mm
            if t in texte :
                p += 1
    return p

mots = ["paris", "texas", "montmartre", "wim", "wenders", "france"]
texte = "paris texas est un film de wim wenders ce paris n'est pas en france mais au texas"
print compte_pairs(mots, texte)  # affiche 2

# question 4, version 2
def compte_pairs (mots, texte) :
    dec = texte.split()
    p = 0
    for i in range(1,len(dec)) :
        if dec[i-1] in mots and dec[i] in mots :
            p += 1
    return p

mots = ["paris", "texas", "montmartre", "wim", "wenders", "france"]
texte = "paris texas est un film de wim wenders ce paris n'est pas en france mais au texas"
print compte_pairs(mots, texte)  # affiche 2

File: exercice_2013_leftover.tex, line 25


l = ["par", "parti", "pas", "pars"]
t = "parpasparspasparti"

File: exercice_2013_leftover.tex, line 31


s.startswith(d) # retourne True si la chaîne de caractères s
                # commence par d
s [i:j]         # extrait la sous-chaîne de caractère entre les positions i et j (exclu)

File: exercice_2013_leftover.tex, line 49


l = ["a", "aa"]
t = "aaa"

, correction 2012

#coding:latin-1

def decoupage (mots, texte) :
    res = [ ]
    
    # si le texte est vide, le résultat l'est aussi
    if len(texte) == 0 :
        return res
    
    # on parcourt tous les mots de la liste
    for m in mots :
        if texte.startswith (m) :
            # si un mot commence la chaîne de caractères texte
            # on ajoute ce mot au résultat
            res.append (m)
            # on soustrait ce mot au texte
            texte = texte [ len(m) : ]
            # on appelle la fonction decoupage sur le reste du texte
            res += decoupage (mots, texte)
            return res
    
    # si aucun mot de la liste ne commence texte
    res.append (texte[0])
    texte = texte [ 1 : ]
    res += decoupage (mots, texte)
    return res
    
l = ["par", "parti", "pas", "pars"]
t = "parpasparspasparti"
d = decoupage (l, t)    
print d             # ['par', 'pas', 'par', 's', 'pas', 'par', 't', 'i']
print " ".join (d)  # par pas par s pas par t i

File: exercice_2013_leftover.tex, line 60


# on trie les mots par ordre décroissant de taille
l = [ (len(m), m) for m in l ]
l.sort(reverse = True)
l = [ c[1] for c in l ]
d = decoupage (l, t)    
print " ".join (d)   # par pas pars pas parti

, correction 2012

#coding:latin-1

def decoupage (mots, texte) :
    res = [ ]
    
    # on parcourt tous les mots de la liste
    while len(texte) > 0 :
        # on a besoin de cette variable pour dire si on a trouvé un mot
        # de la liste qui commence texte
        motliste = False
        for m in mots :
            if texte.startswith (m) :
                res.append (m)
                texte = texte [ len(m) : ]
                motliste = True
                break
                
        if not motliste :
            res.append (texte[0])
            texte = texte [ 1 : ]

    return res
    
l = ["par", "parti", "pas", "pars"]
t = "parpasparspasparti"
d = decoupage (l, t)    
print " ".join (d)  # par pas par s pas par t i

, correction 2012

#coding:latin-1

def decoupages (mots, texte) :
    res = [ ]
    
    if len(texte) == 0 :
        return res
    
    trouve = False
    for m in mots :
        if texte.startswith (m) :
            trouve = True
            fin = texte [ len(m) : ]
            ds  = decoupages (mots, fin)
            if len(ds) == 0 :
                # dans ce cas, cela veut dire fin est vide
                # le seul découpage possible est [ m ]
                res.append ( [ m ] )
            else :
                # dans ce cas, l'ensemble des découpages possibles 
                # est construit selon le schéma suivant :
                #    m + un découpage de ds
                for d in ds :
                    td = [ m ] + d
                    res.append ( td )
    
    if not trouve :
        # ici, on retrouve le même code que précédemment
        # mais pour un seul caractère
        m   = texte [0]
        fin = texte [ 1 : ]
        ds  = decoupages (mots, fin)
        if len(ds) == 0 :
            res.append ( [ m ] )
        else :
            for d in ds :
                td = [ m ] + d
                res.append ( td )

    return res
    
l  = ["par", "parti", "pas", "pars"]
t  = "parpasparspasparti"
ds = decoupages (l, t)    
for d in ds : print " ".join (d)

l  = ["a", "aa"]
t  = "aaa"
ds = decoupages (l, t)    
for d in ds : print " ".join (d)

File: exercice_2013_leftover.tex, line 80


par pas par s pas par t i
par pas par s pas parti
par pas pars pas par t i
par pas pars pas parti
a a a
a aa
aa a

File: exercice_2013_leftover.tex, line 92


l  = ["a", "aa", "b", "bb"]
t  = "aaabbb"
ds = decoupages (l, t)    
for d in ds : print " ".join (d)

File: exercice_2013_leftover.tex, line 102


a a a b b b
a a a b bb
a a a bb b
a aa b b b
a aa b bb
a aa bb b
aa a b b b
aa a b bb
aa a bb b

File: exercice_2013_leftover.tex, line 116


1 aaabbb
2 aabbb
3 abbb
4 bbb
5 bb
6 b
7 b
8 bbb
9 bb
10 b
11 b
12 abbb
13 bbb
14 bb
15 b
16 b

, correction 2012

#coding:latin-1

def decoupage (mots, texte) :
    res = [ ]
    
    # si le texte est vide, le résultat l'est aussi
    if len(texte) == 0 :
        return res
    
    # on parcourt tous les mots de la liste
    for m in mots :
        if texte.startswith (m) :
            # si un mot commence la chaîne de caractères texte
            # on ajoute ce mot au résultat
            res.append (m)
            # on soustrait ce mot au texte
            texte = texte [ len(m) : ]
            # on appelle la fonction decoupage sur le reste du texte
            res += decoupage (mots, texte)
            return res
    
    # si aucun mot de la liste ne commence texte
    res.append (texte[0])
    texte = texte [ 1 : ]
    res += decoupage (mots, texte)
    return res
    
l = ["par", "parti", "pas", "pars"]
t = "parpasparspasparti"
d = decoupage (l, t)    
print d             # ['par', 'pas', 'par', 's', 'pas', 'par', 't', 'i']
print " ".join (d)  # par pas par s pas par t i

File: exercice_2013_leftover.tex, line 142


1 aaabbb
2 aabbb
3 abbb
4 bbb
5 bb
6 b

File: exercice_2013_leftover.tex, line 176


a = 10.**i/3
c = 10.**(-i)/4*3
b = 1

File: exercice_2013_leftover.tex, line 189


import time, math
debut = time.clock()


y = 0
N = 1000000

for i in range (1,N+1) :
    s  = i*1.0/N
    x  = math.log(s)
    y += x

fin   = time.clock()
print "integ ",y/N
print "temps ",fin - debut

File: exercice_2013_leftover.tex, line 209


import time, math
debut = time.clock()


y = 0
N = 1000000
z = math.log(N)
for i in range (1,N+1) :

    x  = math.log(i*1.0)
    y += x
y -= z*N
fin   = time.clock()
print "integ ",y/N
print "temps ",fin - debut

File: exercice_2013_leftover.tex, line 229


import time, math
debut = time.clock()
def monlog (i) : 
    return math.log(i)
y = 0
N = 1000000
z = math.log(N)
for i in range (1,N+1) :

    x  = monlog(i*1.0)
    y += x
y -= z*N
fin   = time.clock()
print "integ ",y/N
print "temps ",fin - debut

File: exercice_2013_leftover.tex, line 249


integ -0.999992173306
temps  0.780309832669

File: exercice_2013_leftover.tex, line 256


integ -0.999992173306
temps 0.5965760959

File: exercice_2013_leftover.tex, line 263


integ -0.999992173306
temps 0.698039702544

File: exercice_2013_leftover.tex, line 281


import time, math



debut = time.clock()


y = 0
N = 1000000
z = math.log(N)
for i in range (1,N+1) :
    x  = math.log(i*1.0)
    y += x
y -= z*N
fin   = time.clock()
print "integ ",y/N
print "temps ",fin - debut

File: exercice_2013_leftover.tex, line 303


import time, math



debut = time.clock()
def monlog (i) : 
    return math.log(i)
y = 0
N = 1000000
z = math.log(N)
for i in range (1,N+1) :
    x  = monlog(i*1.0)
    y += x
y -= z*N
fin   = time.clock()
print "integ ",y/N
print "temps ",fin - debut

File: exercice_2013_leftover.tex, line 325


import time, math
memolog = { }                   
for i in range(1,N+1) :         
    memolog [i] = math.log(i)   
debut = time.clock()


y = 0
N = 1000000
z = math.log(N)
for i in range (1,N+1) :
    x  = memolog[i]             
    y += x
y -= z*N
fin   = time.clock()
print "integ ",y/N
print "temps ",fin - debut

File: exercice_2013_leftover.tex, line 347


integ -0.999992173306
temps 0.6014340817

File: exercice_2013_leftover.tex, line 354


integ -0.999992173306
temps 0.68944518564

File: exercice_2013_leftover.tex, line 361


integ -0.999992173306
temps 0.424331883008

File: exercice_2013_leftover.tex, line 387


l = ["par", "parti", "pas", "pars"]
t = "parpasparspasparti"

File: exercice_2013_leftover.tex, line 393


s.startswith(d) # retourne True si la chaîne de caractères s
                # commence par d
s [i:j]         # extrait la sous-chaîne de caractère entre les positions i et j (exclu)

File: exercice_2013_leftover.tex, line 410


a = 10.0**i/3        # ne pas changer 10.0 en 10 pour éviter 
c = 10.0**(-i)/4*3   # les problèmes de calculs avec des entiers
b = 1                # ** est l'opérateur puissance

, correction 2012

# coding: latin-1
# question 1
def frequence_lettre (mot) :
    res = { }
    for c in mot :
        if c in res : res[c] += 1
        else : res [c] = 1
    return res
    
print frequence_lettre ("aviateur")
# affiche {'a': 2, 'e': 1, 'i': 1, 'r': 1, 'u': 1, 't': 1, 'v': 1}

# Deux autres écritures de la fonction
def frequence_lettre (mot) :
    res = { c:0 for c in mot }
    for c in mot : res[c] += 1
    return res
    
def frequence_lettre (mot) :
    res = { }
    for c in mot : 
        # la méthode get retourne res[c] si cette valeur existe, 0 sinon
        res[c] = res.get( c, 0 ) + 1
    return res
    
# question 2

def anagramme (mot1, mot2) :
    h1 = frequence_lettre(mot1)
    h2 = frequence_lettre(mot2)
    
    # il fallait éviter d'écrire la ligne suivante bien qu'elle retourne le résultat cherché :
    # return h1 == h2
    
    for c in h1 :
        if c not in h2 or h1[c] != h2[c] : return False
    # il ne faut pas oublier cette seconde partie
    for c in h2 :
        if c not in h1 : return False
    return True
    
a,b = "anagramme", "agrammane"
print anagramme (a,b), anagramme (b,a) # affiche True, True

# on vérifie que la fonctionne marche aussi dans l'autre cas
a,b = "anagramme", "agrummane"
print anagramme (a,b), anagramme (b,a) # affiche False, False

# on pouvait faire plus rapide en éliminant les cas évidents
def anagramme (mot1, mot2) :
    if len(mot1) != len(mot2) : return False
    h1 = frequence_lettre(mot1)
    h2 = frequence_lettre(mot2)
    if len(h1) != len(h2) : return False

    for c in h1 :
        if h1[c] != h2.get(c, 0) : return False
    return True

programme non corrigé


def fonction_mystere(a,b) :
    am = a.split()
    bm = b.split()
    r = 0
    for c in am :
        if c in bm :
            r += 1
    return r / (len(am)-r+len(bm)
    
print ( fonction_mystere ("deux mots", "et trois mots"))

File: interro_rapide_30_minutes_2013_10.tex, line 39


  File "interro_rapide_30_minutes_2013_10_1.py", line 10
    print ( fonction_mystere ("deux mots", "et trois mots"))
        ^
SyntaxError: invalid syntax

même fonction gérant le cas des mots vides


def fonction_mystere(a,b) :
    am = a.split()
    bm = b.split()
    if len(am) == 0 and len(bm) == 0 : return 0.0
    r = 0
    for c in am :
        if c in bm :
            r += 1
    return r / (len(am)-r+len(bm))

triangle de Pascal


pascal = { }
for i in range(1,100) :                                   # A
    pascal[i,0] = 1                                       
    pascal[i,i] = 1                                       # B
    for j in range(0,i) :                                 # C
        pascal [i,j] = pascal [i-1,j-1] + pascal[i-1,j]  (ligne 10 mentionnée dans l'erreur)
print (pascal[5,4])				

File: interro_rapide_45_minutes_2013_12.tex, line 43


Traceback (most recent call last):
  File "interro_rapide_45_minutes_2013_12_1.py", line 10, in <module>
    pascal [i,j] = pascal [i-1,j-1] + pascal[i-1,j]
KeyError: (0, -1)

calcul de la somme des chiffres d'un entier positif (1)


def somme_chiffre (i) :
    return sum ( [ int(c) for c in str(i) ] )

print (somme_chiffre(199))

calcul de la somme des chiffres d'un entier positif (2)


def somme_chiffre (i) :
    s = 0
    while i > 0 :
        s += i % 10
        i //= 10
    return s

divisible par 11


def division_11 (i) :    
    spair = 0
    simpair = 0
    pos = 1  # la première position est 1
    while i > 0 :
        if pos % 2 == 0 : spair += i % 10
        else : simpair += i % 10
        i //= 10
        pos += 1
    
    diff = abs(spair - simpair)
    
    if diff == 0 : return True 
    elif diff < 11 : return False
    elif diff == 11 : return True
    else : return division_11(diff)

for i in [7,11,55,100,121,1001,3003,4000] :
    print (i,division_11(i))

suite de Fibonacci


n = 100
fibo = [ 0 ] * (n+1)                    # A
fibo[0] = 1 
for i in range(2,n) :                   # B
    fibo[i] = fibo[i-1] + fibo[i-2]     # C
print (fibo[n])  #affiche zéro          

diviseurs d'un nombre entier


def diviseur (i) :
    div = [ ]
    for d in range (1, i//2+1) :
        if i % d == 0 : div.append(d)
    return div
    
print (diviseur (11))
print (diviseur (512))

nombre parfait


def nombre_parfait (i) :
    div = diviseur(i)
    return sum(div) == 2*i

for i in range(115,125) :
    print (i, nombre_parfait(i), diviseur(i))

question 1.1 : remplacer des accents

		

File: interro_rapide_20_minutes_2014_10.tex, line 31


from math import log
s = 0
N = 100
while N > 1 :
    for i in range(1, N):
        s += log(i)
    N //= 2
print(s)

question 1.1 : remplacer des accents

		

File: interro_rapide_20_minutes_2014_10.tex, line 83


s = 0
ii = 1
N = 7
for i in range(1,N):
    ii *= 2
    for k in range(1,ii):
        s += log(k)
print(s)

File: interro_rapide_20_minutes_2014_11.tex, line 23


nbs = [ 1, 5, 4, 7 ]
for n in nbs:
    s += n

----> 3     s += n
NameError: name 's' is not defined

File: interro_rapide_20_minutes_2014_11.tex, line 35


def f(x) : return x%2
nbs = { i:f(i) for i in range(0,5) }

File: interro_rapide_20_minutes_2014_11.tex, line 42


def ma_fonction(x1,y1,x2,y2):
    d = (x1-x2)**2 +(y1-y2)**2
    print(d)
d = ma_fonction(0,0,1,1)
print(d)
-----
2
None

File: interro_rapide_20_minutes_2014_11.tex, line 55


n = 0
N = 100
for i in range(0,N):
    for k in range(0,i):
        n += N

File: interro_rapide_20_minutes_2014_11.tex, line 66


a = 3
b = "6"
a+b
a*b

File: interro_rapide_20_minutes_2014_11.tex, line 91


nbs = ( 1, 5, 4, 7 )
nbs[0] = 0

----> 2 nbs[0] = 0
TypeError: 'tuple' object does not support item assignment

File: interro_rapide_20_minutes_2014_11.tex, line 102


d = {4: 'quatre'}
c = d.get('4', None)

File: interro_rapide_20_minutes_2014_11.tex, line 109


N = 8
s = 0
while N > 0 :
    for i in range(N):
        s += 1
    N //= 2
x = (s+1)//2

File: interro_rapide_20_minutes_2014_11.tex, line 121


l = ['a', 'b', 'c']
c = l[1]

File: interro_rapide_20_minutes_2014_11.tex, line 128


def fonction(N):
    l = None
    for i in range(N):
        if l is None : l = [ ]
        l.append(i)
    return l
ma_liste = fonction(???)
ma_liste.append(-1)
----
----> 8 ma_liste.append(-1)
AttributeError: 'NoneType' object has no attribute 'append'

File: interro_rapide_20_minutes_2014_11.tex, line 171


l = [ 0, 1,2,3]
for i in range(len(l)):
    print(i)
    del l[i]
----
0
1
2
----
----> 4     del l[i]
IndexError: list assignment index out of range

File: interro_rapide_20_minutes_2014_11.tex, line 187


a = 2
for i in range(1,5):
    a += a

File: interro_rapide_20_minutes_2014_11.tex, line 198


x = 2.67
y = int ( x * 2 ) / 2

File: interro_rapide_20_minutes_2014_11.tex, line 206


def moyenne(l):
    s = 0 
    for x in l : 
        print("*")
        s += x
    return s / len(l)
def variance(l):
    return sum ( [ (x - moyenne(l))**2 for x in l  ] ) / len(l)
l = [ random.random() for i in range(0,100) ]
print(variance(l)**0.5)

File: interro_rapide_20_minutes_2014_11.tex, line 221


import random
x = random.randint(0,100)
while x != 50: x = random.randint(0,100)

File: interro_rapide_20_minutes_2015_09.tex, line 23


tab = [1, 3]
for i in range(0, len(tab)):
    print(tab[i] + tab[i+1])

File: interro_rapide_20_minutes_2015_09.tex, line 32


n = 1
if n = 1:
    y = 0
else:
    y = 1

File: interro_rapide_20_minutes_2015_09.tex, line 61


y = "a" * 3 + 1
z = 3 * "a" + 1
print(y,z)

File: interro_rapide_20_minutes_2015_09.tex, line 70


l = []
for i in range(0, 10):
    l.append([i])
print(l)

File: interro_rapide_20_minutes_2015_10.tex, line 23


import random
l = [0, 1, 2, 3, 4]
i = random.randint(0, 5)
del l[i]

File: interro_rapide_20_minutes_2015_10.tex, line 33


mat = {}
for i in range(0,3) and j in range(0,3):
    mat[i,j] = 0

File: interro_rapide_20_minutes_2015_10.tex, line 60


i = 2
if i == 2:
    i = 1
else:
    i = 2

File: interro_rapide_20_minutes_2015_10.tex, line 71


l = {{}}
for i,j in zip(range(0,3), range(0,3)):
    l[i,j] = 1

File: interro_rapide_20_minutes_2015_10.tex, line 79


----> 1 l = {{}}
      2 for i,j in zip(range(0,3), range(0,3)):
      3     l[i,j] = 1
      4 l

TypeError: unhashable type: 'dict'

File: ecrit_2006.tex, line 28


l = [ 0,1,2,3,4,6,5,8,9,10]
res = True
for i in range (1,len (l)) :
    if l[i-1] > l[i] :
        res = False 

File: ecrit_2006.tex, line 58


def somme (n) :
    return sum ( [ int (c) for c in str (n) ] )

File: ecrit_2006.tex, line 66


def somme (n) :
    l = str (n)           # il ne faut pas confondre l=str (n) avec l = "n"
    s = 0
    for c in l :          # ou   for i in range (0, len (c)) :
        s += int (c)      # ou       s += int (c [i])
    return s

File: ecrit_2006.tex, line 78


def somme (n) :
    s = 0
    while n > 0 :
        s += n % 10
        n /= 10    # ici, c'est une division entière, si vous n'êtes pas sûr :  
                   #       n = int (n/10)
    return n

File: ecrit_2006.tex, line 91


def somme (n) :
    if n <= 0 : return 0
    else : return (n % 10) + somme ( n / 10 )

File: ecrit_2006.tex, line 100


import math
def somme (n) :
    k = int (math.log (n) / math.log (10) + 1)
    s = 0
    for i in range (1,k+1) :
        d = 10 ** i   # ou encore d = int (exp ( k * log (10) ) )
        c = n / d
        e = n - c * d
        f = e / (d / 10)
        s += f
    return s

File: ecrit_2006.tex, line 128


n = 0
for i in range (0,10) :
    if (n + i) % 3 == 0 :
        n += 1

File: ecrit_2006.tex, line 177


def grenouille (n) :
    if   n == 2 : return 2
    elif n == 1 : return 1 
    else :        return grenouille (n-1) + grenouille (n-2)
print grenouille (13)

File: ecrit_2006.tex, line 191


def grenouille (fin, n = 2, u1 = 1, u2 = 2) :
    if   fin == 1   : return u1
    elif fin == 2   : return u2
    elif n   == fin : return u2
    u = u1 + u2
    return grenouille (fin, n+1, u2, u)
print grenouille (13)

File: ecrit_2006.tex, line 205


def grenouille (n) :
    if n == 1 : return 1
    u1 = 1
    u2 = 2
    for i in range (3,n+1) :
        u  = u1 + u2   # il est impossible de 
        u1 = u2        # résumer ces trois lignes
        u2 = u         # en deux
    return u2
print grenouille (13)

File: ecrit_2006.tex, line 222


def grenouille (n) :
    if n == 1 : return 1
    u = [1,2]
    for i in range (2,n) :
        u.append (u [i-1] + u [i-2])
    return u [n-1]
print grenouille (12)

File: ecrit_2006.tex, line 236


def grenouille (n) :
    if n == 1 : return 1
    u = range (0, n)  # il ne faut pas oublier de créer le tableau
                      # avec autant de cases que nécessaire
                      # ici 13
    u [0] = 1
    u [1] = 2
    for i in range (2,n) :
        u [i] = u [i-1] + u [i-2]
    return u [n-1]
print grenouille (12)

File: ecrit_2006.tex, line 261


a = "abcdefghijklmnopqrstuvwxyz"
print len (a)
d = {}
for i in range (0,len (a)) :
    d [ a [ i ] ] = i

print d ["M"]

File: ecrit_2006.tex, line 274


examen.py:14:  KeyError: 'M'

File: ecrit_2006.tex, line 288


a = "abcdefghijklmnopqrstuvwxyz"
print len (a)
d = {}
for i in range (0,len (a)) :
    d [ a [ i ] ] = i
    
print d ["m"]         ######   ligne modifiée

File: ecrit_2006.tex, line 301


a = "abcdefghijklmnopqrstuvwxyz"
a = a.upper ()        #######   ligne ajoutée
print len (a)
d = {}
for i in range (0,len (a)) :
    d [ a [ i ] ] = i
    
print d ["M"]

File: ecrit_2006.tex, line 324


def somme (tab) :
    l = tab[0]
    for i in range (1, len (tab)) :
        l += tab [i]
    return l
ens = [[0,1],[2,3]] 
print somme ( ens )   # affiche [0,1,2,3]
print ens             # affiche [ [0,1,2,3], [2,3] ]

File: ecrit_2006.tex, line 345


import copy                      ###### ligne ajoutée
def somme (tab) :
    l = copy.copy (tab[0])       ###### ligne modifiée
    for i in range (1, len (tab)) :
        l += tab [i]
    return l
ens = [[0,1],[2,3]] 
print somme ( ens )   # affiche [0,1,2,3]
print ens             # affiche [ [0,1,2,3], [2,3] ]

File: ecrit_2006.tex, line 360


def somme (tab) :
    l = []                            ###### ligne modifiée
    for i in range (0, len (tab)) :   ###### ligne modifiée
        l += tab [i]
    return l
ens = [[0,1],[2,3]] 
print somme ( ens )   # affiche [0,1,2,3]
print ens             # affiche [ [0,1,2,3], [2,3] ]

File: ecrit_2006.tex, line 382


li  = range (0,10)
sup = [0,9]
for i in sup :
    del li [i]
print li

File: ecrit_2006.tex, line 393


examen.py:44:  IndexError: list assignment index out of range

File: ecrit_2006.tex, line 406


[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

File: ecrit_2006.tex, line 410


[ 1, 2, 3, 4, 5, 6, 7, 8, 9]

File: ecrit_2006.tex, line 416


li  = range (0,10)
sup = [9,0]      ####### ligne modifiée
for i in sup :
    del li [i]
print li

File: ecrit_2006.tex, line 439


l = ["un", "deux", "trois", "quatre", "cinq"]
for i in range (0,len (l)) :
    mi = i
    for j in range (i, len (l)) :
        if l[mi] < l [j] : mi = j
    e      = l [i]
    l [mi] = l [i]
    l [i]  = e
print l

File: ecrit_2006.tex, line 455


['un', 'deux', 'deux', 'deux', 'cinq']

File: ecrit_2006.tex, line 470


l = ["un", "deux", "trois", "quatre", "cinq"]
for i in range (0,len (l)) :
    mi = i
    for j in range (i, len (l)) :
        if l[mi] < l [j] : mi = j
    e      = l [mi]       ######## ligne modifiée
    l [mi] = l [i]
    l [i]  = e
print l

File: ecrit_2006.tex, line 499


def moyenne (tab) :
    s = 0.0
    for x in tab : 
        s += x
    return s / len (tab)
    
def variance (tab) :
    s = 0.0
    for x in tab :
        t  = x - moyenne (tab)
        s += t * t
    return s / len (tab)
    
l = [ 0,1,2, 2,3,1,3,0]
print moyenne (l)
print variance (l)

File: ecrit_2006.tex, line 529


def variance (tab) :
    s = 0.0
    m = moyenne (tab)
    for x in tab :
        t  = x - m
        s += t * t
    return s / len (tab)

File: ecrit_2006.tex, line 563


class carre :
    def __init__ (self, a) :
        self.a = a
    def surface (self) :
        return self.a ** 2

class rectangle (carre) :
    def __init__ (self, a,b) :
        carre.__init__(self,a)
        self.b = b
    def surface (self) :
        return self.a * self.b

File: ecrit_2006.tex, line 582


class rectangle :
    def __init__ (self, a,b) :
        self.a = a
        self.b = b
    def surface (self) :
        return self.a * self.b

class carre (rectangle) :
    def __init__ (self, a) :
        rectangle.__init__ (self, a,a)
    def surface (self) :
        return self.a ** 2

File: ecrit_2006.tex, line 616


class carre :
    def __init__ (self, a) :
        self.a = a
    def surface (self) :
        return self.a ** 2

class rectangle (carre) :
    def __init__ (self, a,b) :
        carre.__init__(self,a)
        self.b = b
    def surface (self) :
        return self.a * self.b

class losange (carre) :
    def __init__ (self, a,theta) :
        carre.__init__(self,a)
        self.theta = theta
    def surface (self) :
        return self.a * math.cos (self.theta) * self.a * math.sin (self.theta) * 2

File: ecrit_2006.tex, line 654


x = 1.0
for i in range (0,15) :
    x = x / 10
    print i, "\t", 1.0 - x, "\t", x, "\t", x **(0.5)

File: ecrit_2006.tex, line 664


0    0.90000000000000002220     0.1              0.316227766017
1    0.98999999999999999112     0.01             0.1
2    0.99899999999999999911     0.001            0.0316227766017
3    0.99990000000000001101     0.0001           0.01
4    0.99999000000000004551     1e-05            0.00316227766017
5    0.99999899999999997124     1e-06            0.001
6    0.99999990000000005264     1e-07            0.000316227766017
7    0.99999998999999994975     1e-08            0.0001
8    0.99999999900000002828     1e-09            3.16227766017e-05
9    0.99999999989999999173     1e-10            1e-05
10   0.99999999998999999917     1e-11            3.16227766017e-06
11   0.99999999999900002212     1e-12            1e-06
12   0.99999999999989996891     1e-13            3.16227766017e-07
13   0.99999999999999000799     1e-14            1e-07
14   0.99999999999999900080     1e-15            3.16227766017e-08
15   0.99999999999999988898     1e-16            1e-08
16   1.00000000000000000000     1e-17            3.16227766017e-09
17   1.00000000000000000000     1e-18            1e-09
18   1.00000000000000000000     1e-19            3.16227766017e-10
19   1.00000000000000000000     1e-20            1e-10

File: ecrit_2006.tex, line 691


class matrice_carree_2 :
    def __init__ (self, a,b,c,d) :
        self.a, self.b, self.c, self.d = a,b,c,d
        
    def determinant (self) :
        return self.a * self.d - self.b * self.c
        
m1 = matrice_carree_2 (1.0,1e-6,1e-6,1.0)
m2 = matrice_carree_2 (1.0,1e-9,1e-9,1.0)
print m1.determinant ()
print m2.determinant ()

File: ecrit_2006.tex, line 729


def valeurs_propres (self) :
    det   = self.determinant ()
    trace = self.a + self.d
    delta = trace ** 2 - 4 * det
    l1    = 0.5 * (trace - (delta ** (0.5)) )
    l2    = 0.5 * (trace + (delta ** (0.5)) )
    return l1,l2

File: ecrit_2006.tex, line 768


0.99999999999900002212
1.00000000000000000000

File: ecrit_2006.tex, line 777


l1    = 0.5 * (trace - ((trace ** 2 - 4 * det) ** (0.5)) )
l2    = 0.5 * (trace + ((trace ** 2 - 4 * det) ** (0.5)) )

File: ecrit_2006.tex, line 785


l1 = 1,000001
l2 = 0.99999899999999997124  # égale à 1 - 1e-6

File: ecrit_2006.tex, line 793


l1 = 1
l2 = 1

File: ecrit_2006.tex, line 801


l1    = 0.5 * (trace - ((trace ** 2 - 4 * det) ** (0.5)) ) = - det ** 0.5 = -1e-9
l2    = 0.5 * (trace + ((trace ** 2 - 4 * det) ** (0.5)) ) = det ** 0.5 = 1e-9

File: ecrit_2006.tex, line 809


l1    = 1-1e-9  = 0.99999999900000002828
l2    = 1+ 1e-9 = 1.000000001

File: ecrit_2007.tex, line 28


def fonction_log2 (k) :
    n = 0
    while 2**n < k :
        n += 1
    return n

File: ecrit_2007.tex, line 38


def fonction_log2 (k) :
    for i in range (0,1000) :
        if 2**i >= k :
            return i

File: ecrit_2007.tex, line 47


def fonction_log2 (k) :
    if k <= 1 : return 0
    else : return fonction_log2 ((k+1)/2)+1

File: ecrit_2007.tex, line 63


def parcours (n) :
    i = 1
    j = 1
    while i+j < n :
        print (i,j)
        i += 1
        j -= 1
        if j < 1 :
            j = i+j
            i = 1

File: ecrit_2007.tex, line 101


(1,1)
(1,2)
(2,1)
(1,3)
(2,2)
(3,1)



File: ecrit_2007.tex, line 115


(1,4)
(2,3)
(3,2)
(4,1)
(1,5)
(2,4)
(3,3)
...

File: ecrit_2007.tex, line 130


i += 1
j -= 1

File: ecrit_2007.tex, line 137


if j < 1 :
    j = i+j
    i = 1

File: ecrit_2007.tex, line 155


def suite (n) :
    n = n ** 2 / 2 + 1
    return n
            
n = 3
for i in range (0,10) :
    n = suite (n) % 17
print n

File: ecrit_2007.tex, line 198


def ensemble_lettre (s) :
    ens = []
    for i in range (0, len (s)) :
        c = s [i]
        if c in ens :
            ens.append (c)
    return ens
        
print lettre ("baaa")

File: ecrit_2007.tex, line 225


def compte_lettre (s) :
    nombre = {}
    for c in s :
        nombre [c] += 1
    return nombre
    
print compte_lettre ( "mysteres" )

File: ecrit_2007.tex, line 237


KeyError: 'm'

File: ecrit_2007.tex, line 261


def compteur (s) :
    nombre = {}
    for c in s : nombre [c] = 0        # ligne ajoutée
    for c in s :
        nombre [c] += 1
    return nombre

File: ecrit_2007.tex, line 273


def compteur (s) :
    nombre = {}
    for c in s : 
        if c not in nombre : nombre [c] = 0       # ligne ajoutée
        nombre [c] += 1
    return nombre

File: ecrit_2007.tex, line 285


{'e': 2, 'm': 1, 's': 2, 'r': 1, 't': 1, 'y': 1}

File: ecrit_2007.tex, line 292


def compteur (s) :
    alpha = "abcdefghijklmnopqrstuvwxyz"
    nombre = [ 0 for c in alpha ]
    for c in s :
        i = alpha.index (c)
        nombre [i] += 1
    return nombre

File: ecrit_2007.tex, line 305


[0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 1, 0]

File: ecrit_2007.tex, line 313


print compteur ( "mysteres" )
print compteur ( compteur ("mysteres") )
print compteur ( [0,1,1,4,-1, (6,0), 5.5, "ch"] )
print compteur ( { 1:1, 2:2, 1:[] } )

File: ecrit_2007.tex, line 323


print compteur ( [0, [0,0] ] )

File: ecrit_2007.tex, line 340



def autre_parcours (n) :
    i = 0
    j = 0
    k = 0
    
    while k < n :
        print (k,i,j)
        if i == 0 and j == 0 :
            k += 1
        if j == 0 and i < k :
            i += 1
        elif i == k and j < k :
            j += 1
        elif j == k and i > 0 :
            i -= 1
        elif i == 0 and j > 0 :
            j -= 1

autre_parcours (3)


File: ecrit_2007.tex, line 379


def ligne_nulle (mat) :
    nb = 0
    for i in range (0, len (mat)) :
        lig = 0
        for j in range (0, len (mat [i])) :
            if mat [i][j] > 0 : lig += 1
            if lig == 0 : nb += 1
    return nb

matri = [ [ random.randint (0,1) for i in range (0,4) ] for j in range (0,20) ]
print ligne_nulle (matri)

File: ecrit_2007.tex, line 417


def ligne_nulle (mat) :
    nb = 0
    for i in range (0, len (mat)) :
        lig = 0
        for j in range (0, len (mat [i])) :
            if mat [i][j] > 0 : lig += 1
        if lig == 0 : nb += 1                      # ligne décalée vers la gauche
    return nb

File: ecrit_2007.tex, line 441


class erreur :
    def __init__ (self) :
        self.e = erreur ()
e = erreur ()

File: ecrit_2007.tex, line 451


Traceback (most recent call last):
  File "examen2007.py", line 4, in ?
    e = erreur ()
  File "examen2007.py", line 2, in __init__
    self.e = erreur ()
  File "examen2007.py", line 2, in __init__
    self.e = erreur ()
  File "examen2007.py", line 2, in __init__
    self.e = erreur ()
  ...

File: ecrit_2007.tex, line 473


class erreur :
    def __init__ (self,e) :
        self.e = e

File: ecrit_2007.tex, line 493


def base3 (n) :
    s = ""
    while n > 0 :
        r = n % 3
        # ....... à compléter
        # ....... à compléter
    return s

File: ecrit_2007.tex, line 512


def base3 (n) :
    s = ""
    while n > 0 :
        r = n % 3
        s = str (r) + s
        n = n / 3            # équivalent à n = (n-r) / 3 
                             # puisque / est une division entière
    return s

File: ecrit_2007.tex, line 534


import copy
import math
import random

class Eleve :
    def __init__ (self, note) :
        self.note = note
        
e = Eleve (0)
l = []
for i in range (0,81) :
    e.note = int (random.gauss (15, 3) + 0.5)  # tirage aélatoire et arrondi
    if e.note >= 20 : e.note = 20              # pas de note au-dessus de 20
    if e.note < 0 : e.note = 0                 # pas de note négative
    l.append (e)
    
moy = 0
var = 0

for e in l :
    moy += e.note    
moy = float (moy) / len (l)  # les notes sont entières, 
                             # il faut convertir avant de diviser
                             # pour obtenir la moyenne
for e in l :
    var += (e.note - moy) ** 2
var = math.sqrt ( float (var) ) / len (l)

print "moyenne ", moy
print "écart-type ", var

File: ecrit_2007.tex, line 570


moyenne  16.0
écart-type  0.0

File: ecrit_2007.tex, line 616


#...
e = Eleve (0)
l = []
for i in range (0,81) :
    e.note = int (random.gauss (15, 3) + 0.5)  
    if e.note >= 20 : e.note = 20              
    if e.note < 0 : e.note = 0                 
    l.append (e.note)                            # ligne modifiée
    
moy = 0
var = 0

for note in l :                                  # ligne modifiée
    moy += note                                  # ligne modifiée
moy = float (moy) / len (l)  
for note in l :                                  # ligne modifiée
    var += (note - moy) ** 2                     # ligne modifiée
var = math.sqrt ( float (var) ) / len (l)

print "moyenne ", moy
print "écart-type ", var

File: ecrit_2007.tex, line 644


moy = 0
var = 0

for note in l :												
    moy += note												
    var += note * note
moy = float (moy) / len (l)  
var = float (var) / len (l)  
var = var - moy * moy
var = math.sqrt ( float (var) ) 

print "moyenne ", moy
print "écart-type ", var

File: ecrit_2007.tex, line 680


def puiss (x, n) :
    s = 1.0
    for i in range (0,n) :
        s *= x
    return s

def log_suite (x) :
    x    = float (x-1)
    # ......
    s    = 0
    old  = -1
    n    = 1
    while abs (old - s) > 1e-10 :
        old = s
        po  = puiss (x,n) / n
        if n % 2 == 0 : po = -po
        s  += po
        n  += 1
        # ......
    return s
    
print log_suite (2)

File: ecrit_2007.tex, line 706


# ......
# ......
# ......
# ......
# ......
# ......
def log_suite (x) :
    x    = float (x-1)
    x0   = x
    s    = 0
    old  = -1
    n    = 1
    while abs (old - s) > 1e-10 :
        old = s
        po  = x / n
        if n % 2 == 0 : po = -po
        s  += po
        n  += 1
        x  *= x0
    return s
    
print log_suite (2)

File: ecrit_2007.tex, line 742


def racine_carree (k) :
    x0 = float (k)+1
    x  = float (k)
    while abs (x-x0) > 1e-10 :
        x0 = x
        x  = (k-x*x) / (2 * x) + x
    return x

File: ecrit_2007.tex, line 768


class Noeud :
    def __init__ (self, mot) :
        self.mot = mot
        self.avant = None
        self.apres = None
    def insere (self, mot) :
        if mot < self.mot :
            if self.avant == None : self.avant = Noeud (mot)
            else : self.avant.insere (mot)
        else :
            if self.apres == None : self.apres = Noeud (mot)
            else : self.apres.insere (mot)
    def affiche (self) :
        if self.avant != None : self.avant.affiche ()
        print self.mot
        if self.apres != None : self.apres.affiche ()
            
li = ["premier","deuxième","troisième","quatrième","cinquième","sixième","centième","mystère"]
r = None
for m in li :
    if r == None : r = Noeud (m)
    else : r.insere (m)
r.affiche ()

File: ecrit_2007.tex, line 799


centième
cinquième
deuxième
mystère
premier
quatrième
sixième
troisième

File: ecrit_2008.tex, line 31


def arrondi_05 (x) :
    return float (int (x * 2 + 0.5)) / 2
    
def arrondi_0125 (x) :
    return float (int (x * 8 + 0.5)) / 8
    
def arrondi (x, p) :
    return float (int (x / p + 0.5)) * p

File: ecrit_2008.tex, line 51


for a in range (0, 10) :
    for b in range (0, 10) :
        for c in range (0, 10) :
             print [a,b,c]

File: ecrit_2008.tex, line 69


a,b,c = 0,0,0
while c < 10 :
    print [a,b,c]
    a += 1
    if a == 10 :
        b += 1
        a = 0
        if b == 10 :
            c += 1
            b = 1

File: ecrit_2008.tex, line 86


l = [0,0,0]
while l [-1] < 10 :
    print l
    l [0] += 1
    i = 0
    while i < len (l)-1 and l [i] == 10 :
        l [i] = 0
        l [i+1] += 1
        i += 1

File: ecrit_2008.tex, line 112


def fibo (n) :
    if n <= 2 : return 2
    else : return fibo (n-1) + fibo (n-2)

File: ecrit_2008.tex, line 137


nb = 0  # variable globale
def fibo (n,p) :
    global nb
    if n <= 2 : 
        nb += 1
        return p # plus de récurrence 
    else : 
        nb += 2
        return fibo (n-1,p) + fibo (n-2,p)
        
for n in range (1, 20) :
    nb = 0    # remis à zéro, à chaque fois
              # nb est la mesure du coût
    print fibo(n,3)-2, nb  # nombres identiques
    # nb vérifie la récurrence de la suite c(n)
    #          c(n) = c(n-1) + c(n-2) + 2

File: ecrit_2008.tex, line 209


l = [0,1,2,3,4,5]
g = l
for i in range (0, len (l)-1) :
    g [i] = g [i+1]
print l
print g

File: ecrit_2008.tex, line 221


l = [0,1,2,3,4,5]
g = [0,1,2,3,4,5]
for i in range (0, len (l)-1) :
    g [i] = g [i+1]
print l
print g

File: ecrit_2008.tex, line 233


l = [0,1,2,3,4,5]
g = [0,1,2,3,4,5]
for i in range (0, len (l)) :
    g [i] = g [(i+1)%len (l)]
print l
print g

File: ecrit_2008.tex, line 253


[1, 2, 3, 4, 5, 5]
[1, 2, 3, 4, 5, 5]

File: ecrit_2008.tex, line 261


[0, 1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 5]

File: ecrit_2008.tex, line 269


[0, 1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 1]

File: ecrit_2008.tex, line 277


l = [0,1,2,3,4,5]
g = [0,1,2,3,4,5]
for i in range (0, len (l)) :
    g [i] = l [(i+1)%len (l)] # ligne modifiée, g devient l
print l
print g

File: ecrit_2008.tex, line 291


import copy
l = [0,1,2,3,4,5]
g = copy.copy (l) # on pourrait aussi écrire g = list (l)
                  # ou encore g = [ i for i in l ]
for i in range (0, len (l)) :
    g [i] = l [(i+1)%len (l)] 
print l
print g

File: ecrit_2008.tex, line 316


def mystere (l) :
    """cette fonction s'applique à des listes de nombres"""
    l.sort ()
    nb = 0 
    for i in range (1,len (l)) :
        if l [i-1] != l [i] : nb += 1
    return nb+1
    
l = [4,3,1,2,3,4]
print mystere (l)  # affiche 4

File: ecrit_2008.tex, line 342


[1, 2, 3, 3, 4, 4]

File: ecrit_2008.tex, line 350


import copy
def mystere (l) :
    """cette fonction s'applique à des listes de nombres"""
    l = copy.copy (l) # ligne insérée
                      # on peut écrire aussi l = list (l)
    l.sort ()
    nb = 0 
    for i in range (1,len (l)) :
        if l [i-1] != l [i] : nb += 1
    return nb+1

File: ecrit_2008.tex, line 376


class Personne :
    def __init__ (self, nom) :
        self.nom = nom
    def entete (self) :
        return ""
    def __str__ (self) :
        s = self.entete () + self.nom
        return s
        
class Homme (Personne) :
    def __init__ (self, nom) :
        Personne.__init__ (self, nom) 
    def entete (self) :
        return "M. "
        
class Femme (Personne) :
    def __init__ (self, nom) :
        Personne.__init__ (self, nom) 
    def entete (self) :
        return "Melle "
        
h = Homme ("Hector")
f = Femme ("Gertrude")
print h
print f

File: ecrit_2008.tex, line 406


class Personne :
    def __init__ (self, nom, entete) :
        self.nom = nom
        self.entete = entete
    def __str__ (self) :
        s = self.entete + self.nom
        return s

h = Personne ("Hector", "M. ")
f = Personne ("Gertrude", "Melle ")
print h
print f














File: ecrit_2008.tex, line 450


M. Hector
Melle Gertrude

File: ecrit_2008.tex, line 459


class Personne :
    def __init__ (self, nom) :
        self.nom = nom
    def entete (self) :
        return ""
    def __str__ (self) :
        s = self.entete () + self.nom
        return s
        
class Homme (Personne) :
    def __init__ (self, nom) :
        Personne.__init__ (self, nom) 
    def entete (self) :
        return "M. "
        
class Femme (Personne) :
    def __init__ (self, nom) :
        Personne.__init__ (self, nom) 
    def entete (self) :
        return "Melle "
        
class Hermaphrodite (Personne) :
    def __init__ (self, nom) :
        Personne.__init__ (self, nom) 
    def entete (self) :
        return "Melle et M. "
        
h = Homme ("Hector")
f = Femme ("Gertrude")
g = Hermaphrodite ("Marie-Jean")
print h
print f
print g

File: ecrit_2008.tex, line 497


class Personne :
    def __init__ (self, nom, entete) :
        self.nom = nom
        self.entete = entete
    def __str__ (self) :
        s = self.entete + self.nom
        return s

h = Personne ("Hector", "M. ")
f = Personne ("Gertrude", "Melle ")
g = Personne ("Marie-Jean", \
                     "Melle et M. ")
print h
print f
print g



















File: ecrit_2008.tex, line 552


def tri_entiers(l):
    """cette fonction s'applique à une liste d'entiers"""
    
    # groupe 1
    m = l [0]
    M = l [0]
    for k in range(1,len(l)):
        if l [k] < m : m = l [k]
        if l [k] > M : M = l [k]
    
    # groupe 2
    p = [0 for i in range (m,M+1) ]
    for i in range (0, len (l)) :
        p [ l [i] - m ] += 1
        
    # groupe 3
    R     = [0 for i in range (m,M+1) ]
    R [0] = p [0]
    for k in range (1, len (p)) :
        R [k] = R [k-1] + p [k]
        
    # groupe 4
    pos = 0
    for i in range (1, len (l)) :
        while R [pos] < i : pos += 1
        l [i-1] = pos + m
    l [len (l)-1] = M

File: ecrit_2008.tex, line 643


import random

def tirage (poids) :
    nb = [ 0 for p in poids ]
    while True :
        i = random.randint (0, len (poids)-1) 
        nb [i] += 1
        if nb [i] == poids [i] :
            return i

salaire = [ 10000, 5000, 3000, 2000 ]
poids   = [ int (s / 1000) for s in salaire ]
nombre  = [ 0 for s in salaire ]

for n in range (0,1000) :
    p = tirage (poids)
    nombre [p] += 1
    
for i in range (0, len (poids)) :
    print "salaire ", salaire [i], " : nb : ", nombre [i]

File: ecrit_2008.tex, line 669


salaire  10000  : nb :  0
salaire  5000  : nb :  49
salaire  3000  : nb :  301
salaire  2000  : nb :  650

File: ecrit_2008.tex, line 685


import random

def tirage (poids, nb) :
    while True :
        i = random.randint (0, len (poids)-1) 
        nb [i] += 1
        if nb [i] % poids [i]  == 0 :
            return i

salaire = [ 10000, 5000, 3000, 2000 ]
poids   = [ int (s / 1000) for s in salaire ]
nombre  = [ 0 for s in salaire ]
temp    = [ 0 for s in salaire ]

for n in range (0,1000) :
    p = tirage (poids, temp)
    nombre [p] += 1
    
for i in range (0, len (poids)) :
    print "salaire ", salaire [i], " : nb : ", nombre [i]

File: ecrit_2008.tex, line 711


salaire  10000  : nb :  90
salaire  5000  : nb :  178
salaire  3000  : nb :  303
salaire  2000  : nb :  429

File: ecrit_2008.tex, line 747


dico = { }
dico ["Jean"] = { }
dico ["Jean"] ["Matthieu"] = { }
dico ["Jean"] ["Pierre"] = { }
dico ["Jean"] ["Matthieu"] ["Thomas"] = { }
dico ["Jean"] ["Matthieu"] ["Louis"] = { }
dico ["Jean"] ["Pierre"] ["Anne"] = dico ["Jean"] ["Matthieu"] ["Thomas"]
dico ["Jean"] ["Pierre"] ["Henri"] = { }
dico ["Jean"] ["Pierre"] ["Anne"] ["Alphonse"] = { }

def print_dico (dico, niveau = 0) :
    decalage = "...." * niveau
    for d in dico :
        print decalage, d
        if len (dico [d]) > 0 : 
            print_dico (dico [d], niveau+1)
            
print_dico (dico)  # première fois
dico ["Jean"] ["Pierre"] ["Anne"] ["Bernard"] = { }  ### ligne B
print "**********"
print_dico (dico)  # seconde fois

File: ecrit_2008.tex, line 774


 Jean
.... Matthieu
........ Louis
........ Thomas
............ Alphonse
.... Pierre
........ Anne
............ Alphonse
........ Henri
**********
 Jean
.... Matthieu
........ Louis
........ Thomas
............ Bernard
............ Alphonse
.... Pierre
........ Anne
............ Bernard
............ Alphonse
........ Henri

File: ecrit_2008_rattrapage.tex, line 33


def u (n) :
    if n <= 2 : return 1
    else : return u (n-1) + u (n-2) + u (n-3)

File: ecrit_2008_rattrapage.tex, line 46


def u_non_recursif (n) :
    if n <= 2 : return 1
    u0 = 1
    u1 = 1
    u2 = 1
    i = 3
    while i <= n :
        u  = u0 + u1 + u2
        u0 = u1
        u1 = u2
        u2 = u
        i += 1
    return u

File: ecrit_2008_rattrapage.tex, line 72


def fonction (n) :
    return n + (n % 2)
    
print fonction (10)
print fonction (11)

File: ecrit_2008_rattrapage.tex, line 91


10
12

File: ecrit_2008_rattrapage.tex, line 101


def fonction3 (n) :
    k = 0
    while k < n : k += 3
    return k

File: ecrit_2008_rattrapage.tex, line 112


def fonction3 (n) :
    if   n % 3 == 0 : return n
    elif n % 3 == 1 : return n + 2
    else : return n + 1

File: ecrit_2008_rattrapage.tex, line 123


def fonction3 (n) :
    if n % 3 == 0 : return n
    else : return n + 3 - (n % 3)

File: ecrit_2008_rattrapage.tex, line 140


def division (n) :
    return n / 2
    
print division (1)
print division (0.9)

File: ecrit_2008_rattrapage.tex, line 158


0
0.45

File: ecrit_2008_rattrapage.tex, line 197


def compare_liste (p,q) :
    i = 0
    while i < len (p) and i < len (q) :
        if   p [i] < q [i] : return -1  # on peut décider
        elif p [i] > q [i] : return  1  # on peut décider
        i += 1                          # on ne peut pas décider
    # fin de la boucle, il faut décider à partir des longueurs des listes
    if   len (p) < len (q) : return -1
    elif len (p) > len (q) : return  1
    else : return 0

File: ecrit_2008_rattrapage.tex, line 214


def compare_liste (p,q) :
    i = 0
    while i < len (p) and i < len (q) :
        c = cmp (p [i], q [i])
        if c != 0 : return c            # on peut décider 
        i += 1                          # on ne peut pas décider
    # fin de la boucle, il faut décider à partir des longueurs des listes
    return cmp (len (p), len (q))

File: ecrit_2008_rattrapage.tex, line 238


l = [0,1,2,3,4,5,6,7,8,9]
i = 1
while i < len (l) :
    print l [i], l [i+1]
    i += 2

File: ecrit_2008_rattrapage.tex, line 250


1 2
3 4
5 6
7 8
9
Traceback (most recent call last):
  File "examen2008_rattrapage.py", line 43, in <module>
    print l [i], l [i+1]
IndexError: list index out of range

File: ecrit_2008_rattrapage.tex, line 285


def suite_geometrique_1 (r) :
    x = 1.0
    y = 0.0
    n = 0
    while x > 0 :
        y += x
        x *= r
        n += 1
    return y,n
    
print suite_geometrique_1 (0.5)  #affiche (2.0, 1075)

File: ecrit_2008_rattrapage.tex, line 303


def suite_geometrique_2 (r) :
    x = 1.0
    y = 0.0
    n = 0
    yold = y + 1
    while abs (yold - y) > 0 :
        yold = y
        y += x
        x *= r
        n += 1
    return y,n
    
print suite_geometrique_2 (0.5)  #affiche (2.0, 55)

File: ecrit_2008_rattrapage.tex, line 348


def hyper_cube_liste (n, m = [0,0]) :
    if n > 1 :
        m [0] = [0,0]
        m [1] = [0,0]
        m [0] = hyper_cube_liste (n-1, m [0])
        m [1] = hyper_cube_liste (n-1, m [1])
    return m
h = hyper_cube_liste (3)
print h                     # affiche [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]

File: ecrit_2008_rattrapage.tex, line 365


def hyper_cube_dico (n) :
    r = { }
    ind = [ 0 for i in range (0,n) ]
    while ind [0] <= 1 :
        cle                 = tuple (  ind ) # conversion d'une liste en tuple
        r [cle]             = 0
        ind [ len (ind)-1] += 1
        k                   = len (ind)-1
        while ind [ k ] == 2 and k > 0 :
            ind [k]    = 0
            ind [k-1] += 1
            k         -= 1
    return r
h = hyper_cube_dico (3)
print h        # affiche {(0, 1, 1): 0, (1, 1, 0): 0, (1, 0, 0): 0, (0, 0, 1): 0, 
               #          (1, 0, 1): 0, (0, 0, 0): 0, (0, 1, 0): 0, (1, 1, 1): 0}

File: ecrit_2008_rattrapage.tex, line 389


def occurrence (l,n) :
    d = ....... # choix d'un hyper_cube (n)
    .....
    return d
suite = [ 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1 ]
h = occurrence (suite, 3)
print h

File: ecrit_2008_rattrapage.tex, line 407


def occurrence (l,n) :
    d = hyper_cube_dico (n)
    for i in range (0, len (l)-n) :
        cle = tuple (l [i:i+n])
        d [cle] += 1
    return d

File: ecrit_2008_rattrapage.tex, line 421


def occurrence (l,n) :
    d = { }
    for i in range (0, len (l)-n) :
        cle = tuple (l [i:i+n])
        if cle not in d : d [cle] = 0
        d [cle] += 1
    return d

File: ecrit_2008_rattrapage.tex, line 436


def occurrence (l,n) :
    d = hyper_cube_liste (n, [0,0])         # * remarque voir plus bas
    for i in range (0, len (l)-n) :
        cle = l [i:i+n]
        t   = d                       # 
        for k in range (0,n-1) :      # point clé de la fonction : 
            t = t [ cle [k] ]         #                accès à un élément
        t [cle [ n-1] ] += 1
    return d

File: ecrit_2008_rattrapage.tex, line 454


Traceback (most recent call last):
  File "examen2008_rattrapage.py", line 166, in <module>
    h = occurrence (suite, n)
  File "examen2008_rattrapage.py", line 160, in occurrence
    t [cle [ n-1] ] += 1
TypeError: 'int' object is not iterable

File: ecrit_2008_rattrapage.tex, line 468


def fonction (l = [0,0]) :
    l [0] += 1
    return l
    
print fonction ()         # affiche [1,0] : résultat attendu
print fonction ()         # affiche [2,0] : résultat surprenant
print fonction ( [0,0])   # affiche [1,0] : résultat attendu

File: ecrit_2008_rattrapage.tex, line 483


import copy
def fonction (l = [0,0]) :
    l = copy.copy (l)
    l [0] += 1
    return l

File: ecrit_2008_rattrapage.tex, line 495


def hyper_cube_liste (n, m = [0,0]) :
    m = copy.copy (m)		
    if n > 1 :
        m [0] = [0,0]
        m [1] = [0,0]
        m [0] = hyper_cube_liste (n-1, m [0])
        m [1] = hyper_cube_liste (n-1, m [1])
    return m

File: ecrit_2009.tex, line 45


def f():
    x = 0
    print x


f()

def g():
    print x

g()

File: ecrit_2009.tex, line 61


def f():
    x = 0
    print x

x = 1
f()

def g():
    print x

g()

File: ecrit_2009.tex, line 89


Traceback (most recent call last):
  File "p1.py", line 11, in <module>
    g()
  File "p1.py", line 9, in g
    print x
NameError: global name 'x' is not defined

File: ecrit_2009.tex, line 106



a       = [ None, 0 ]
b       = [ None, 1 ]
a [0]   = b
b [0]   = a
print a [0][0] [0][0] [0][0] [1]

File: ecrit_2009.tex, line 118


import copy
a       = [ None, 0 ]
b       = [ None, 1 ]
a [0]   = copy.copy (b)
b [0]   = a
print a [0][0] [0][0] [0][0] [1]

File: ecrit_2009.tex, line 141


0
1

File: ecrit_2009.tex, line 147


a       = [ None, 0 ]
b       = [ None, 1 ]
a [0]   = b   # b et a [0] désignent la même liste
b [0]   = a   # b [0] et a désignent la même liste

File: ecrit_2009.tex, line 171


0

File: ecrit_2009.tex, line 204


import random
def somme_alea (tableau, n) :
    s = 0
    for i in range (0, n) :
        h = random.randint (0, len (tableau)) 
        s += tableau [h]
    print s / n
x = somme_alea ( range (0,100), 10)
print "x = ", x

File: ecrit_2009.tex, line 223


44
x =  None

File: ecrit_2009.tex, line 234


Traceback (most recent call last):
  File "examen2009.py", line 10, in <module>
    print somme_alea ( range (0,100), 10)
  File "examen2009.py", line 8, in somme_alea
    s += tableau [h]
IndexError: list index out of range

File: ecrit_2009.tex, line 253


44

File: ecrit_2009.tex, line 258


h = random.randint (0, len (tableau)-1)

File: ecrit_2009.tex, line 288


def moyenne_mobile (suite, m) :
    res = []
    for i in range (m, len (suite)-m) :
        s = 0
        for j in range (-m,m+1) : s += suite [i+j]
        res.append (  float (s) / (m*2+1) )
    return res

File: ecrit_2009.tex, line 301


def moyenne_mobile (suite, m) :
    res = []
    for i in range (m, len (suite)-m) :
        if i == m :
            # ... ligne à remplacer    
        else :
            # ... ligne à remplacer    
        res.append (  float (s) / (m*2+1) )
    return res

File: ecrit_2009.tex, line 333


def moyenne_mobile (suite, m) :
    res = []
    for i in range (m, len (suite)-m) :
        if i == m :
            s = sum ( suite [i-m : i+m+1] )
        else :
            s = s - suite [i-m-1] + suite [i+m]
        res.append (  float (s) / (m*2+1) )
    return res

File: ecrit_2009.tex, line 358


def fonction_mystere (tableau) :
    for i in range (0, len (tableau)) :
        if tableau [i] % 2 != 0 : continue
        pos = i
        for j in range (i+1, len (tableau)) :
            if tableau [j] % 2 != 0 : continue
            if tableau [pos] < tableau [j] : pos = j
        ech           = tableau [i]
        tableau [i]   = tableau [pos]
        tableau [pos] = ech

File: ecrit_2009.tex, line 375


if tableau [i] % 2 != 0 : continue
    if tableau [pos] < tableau [j] : pos = j

File: ecrit_2009.tex, line 381


def fonction_mystere (tableau) :
    for i in range (0, len (tableau)) :
        pos = i
        for j in range (i+1, len (tableau)) :
            if tableau [pos] < tableau [j] : pos = j
        ech           = tableau [i]
        tableau [i]   = tableau [pos]
        tableau [pos] = ech

File: ecrit_2009.tex, line 393


a = [ 0, 1, 4, 3, 5, 2 ]
print a                     # affiche [ 0, 1, 4, 3, 5, 2 ]
b = fonction_mystere (a)
print b                     # affiche [ 4, 1, 2, 3, 5, 0 ]

File: ecrit_2009.tex, line 494


class Boucle :
    def __init__ (self, a, b) :
        self.a = a
        self.b = b
    def iteration (self, i) :              # contenu d'une itération
        pass                               
    def boucle (self) :                    # opère la boucle
        for i in range (self.a, self.b) : 
            self.iteration (i)

File: ecrit_2009.tex, line 510


class Gauss (Boucle) :
    def __init__ (self, b) :
        Boucle.__init__ (self, 1, b+1)
        self.x = 0
        
    def iteration (self,i) :
        self.x += i
        
g = Gauss (10)
g.boucle ()
print g.x

File: ecrit_2009.tex, line 542


class Carre (Gauss) :
    def iteration (self,i) :
        self.x += i*i           # ligne changée
        
g = Carre (10)
g.boucle ()
print g.x

File: ecrit_2009.tex, line 554


class Boucle2 (Boucle) :
    def __init__ (self, a, b, c, d) :
        Boucle.__init__ (self, a, b)    
        self.c = c
        self.d = d
    def iteration (self, i, j) :
        pass
    def boucle (self) :
        for j in range (self.c, self.d) : 
            for i in range (self.a, self.b) : 
                self.iteration (i,j)
                
class Gauss2 (Boucle2) :
    def __init__ (self, a, b) :
        Boucle2.__init__ (self, 1, a+1, 1, b+1)
        self.x = 0
    def iteration (self, i,j) :
        self.x += i+j                

File: ecrit_2009.tex, line 577


class Boucle2 (Boucle) :
    def __init__ (self, a, b, c, d) :
        Boucle.__init__ (self, a, b)    
        self.c = c
        self.d = d
    def iteration (self, i) :
        pass
    def boucle (self) :
        for j in range (self.c, self.d) : 
            self.j = j
            for i in range (self.a, self.b) : 
                self.iteration (i)
                
class Gauss2 (Boucle2) :
    def __init__ (self, a, b) :
        Boucle2.__init__ (self, 1, a+1, 1, b+1)
        self.x = 0
    def iteration (self, i) :
        self.x += self.j+i

File: ecrit_2009.tex, line 601


class Boucle2 (Boucle) :
    def __init__ (self, a, b, c, d) :
        Boucle.__init__ (self, a, b)    
        self.c = c
        self.d = d
    def iteration (self, i) :
        pass
    def boucle (self) :
        for j in range (self.c, self.d) : 
            self.j = j
            Boucle.boucle (self)  # suppression d'une boucle
                                  # caché dans la classe Boucle

File: ecrit_2009.tex, line 618


class Boucle2 (Boucle) :
    def __init__ (self, a, b, c, d) :
        Boucle.__init__ (self, a, b)    
        self.c = c
        self.d = d
        
    def iteration (self, i) :
        for j in range (self.c, self.d) :
            self.iteration2 (i,j)
            
    def iteration2 (self, i,j) :
        pass
        
                        
class Gauss2 (Boucle2) :
    def __init__ (self, a, b) :
        Boucle2.__init__ (self, 1, a+1, 1, b+1)
        self.x = 0
    def iteration2 (self, i, j) :
        self.x += j+i

File: ecrit_2009.tex, line 644


class Boucle2 (Boucle) :
    def __init__ (self, a, b, c, d) :
        Boucle.__init__ (self, a, b)    
        self.c = c
        self.d = d
    def iteration (self, i, j) :
        pass
    def boucle (self) :
        ab = self.b - self.a
        cd = self.d - self.c
        n  = ab * cd
        for k in range (0, n) :
            i = k % ab + self.a
            j = k / ab + self.c
            self.iteration (i,j)

File: ecrit_2010.tex, line 46


l = []
for i in range (0, 4) :
    c = []
    for j in range (0, i) : c += [ j ]  # ou c.append (j)
    l += [ c ]                          # ou l.append (c)

for c in l : print c

File: ecrit_2010.tex, line 58


l = [1,4,1,5,9]
d = { }
for u in l :
    if u in d : d [u] += 1
    else : d [u] = 1
        
print d

File: ecrit_2010.tex, line 76


[]
[0]
[0, 1]
[0, 1, 2]

File: ecrit_2010.tex, line 85


{1: 2, 4: 1, 5: 1, 9: 1}

File: ecrit_2010.tex, line 109


n = 10
l = [i for i in (0,n)]
l[9]

File: ecrit_2010.tex, line 117


  File "ecrit.py", line 3, in <module>
    l[9]
IndexError: list index out of range

File: ecrit_2010.tex, line 129


d = {'un': 1, 'deux': 4}
print deux


File: ecrit_2010.tex, line 137


  File "ecrit.py", line 2, in <module>
    print deux
NameError: name 'deux' is not defined

File: ecrit_2010.tex, line 149


l = [ "mot", "second" ]
print l(0)


File: ecrit_2010.tex, line 157


  File "ecrit.py", line 2, in <module>
    print l(0)
TypeError: 'list' object is not callable

File: ecrit_2010.tex, line 171


l = [4, 2, 1, 3]
ll = l.sort()
print ll[0]

File: ecrit_2010.tex, line 179


  File "ecrit.py", line 2, in <module>
	  print ll[0]
TypeError: 'NoneType' object is unsubscriptable

File: ecrit_2010.tex, line 194


n = 10
l = [i for i in (0,n)]
print l                    # affiche [0, 10]

File: ecrit_2010.tex, line 200


l = [i for i in range (0,n)]

File: ecrit_2010.tex, line 210


l = [4, 2, 1, 3]
ll = list (l)
ll.sort()
print ll[0]

File: ecrit_2010.tex, line 219


l = [4, 2, 1, 3]
print min(l)

File: ecrit_2010.tex, line 240


i = random.randint (0,n) # tire aléatoirement un nombre entier entre 0 et n inclus

l.sort ()                # trie la liste l quel que soit son contenu

File: ecrit_2010.tex, line 248


l = [4,5,3,7,4]
l.sort ()
print l             # affiche [3, 4, 4, 5, 7]

File: ecrit_2010.tex, line 256


l = [ (1,2), (0,10), (4,3), (5,0), (0,9) ]
l.sort ()
print l             # affiche [(0, 9), (0, 10), (1, 2), (4, 3), (5, 0)]

File: ecrit_2010.tex, line 264


def permutation_aleatoire (l) :
    ....
    return ...
    
print permutation_aleatoire ([1,2,3,4])   # affiche [3,1,4,2]

File: ecrit_2010.tex, line 281


tab = ["zéro", "un", "deux"] # tableau à trier
pos = [ (tab [i],i) for i in range (0, len (tab)) ] # tableau de couples
pos.sort () # tri
print pos # affiche [('deux', 2), ('un', 1), ('zéro', 0)]

File: ecrit_2010.tex, line 290


from random import randint

def permutation (liste) :
    alea        = [ randint (0,len (liste)) for i in liste ]
    couple      = [ (r,l) for r,l in zip (alea,liste) ]
    couple.sort ()
    permutation = [ l[1] for l in couple ]
    return permutation

liste = [ i*2 for i in range (0,10) ]
permu = permutation (liste)
print liste  # affiche [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
print permu  # affiche [2, 6, 16, 10, 8, 14, 0, 12, 18, 4]

File: ecrit_2010.tex, line 308


from random import randint
import copy

def permutation (liste) :
    li = copy.copy (liste)
    for i in xrange (0, len (liste)) :
        n = randint (0, len (liste)-1)
        m = randint (0, len (liste)-1)
        s = li [n]
        li [n] = li [m]
        li [m] = s
    return li

File: ecrit_2010.tex, line 325


from random import randint
import copy

def permutation (liste) :
    li = copy.copy (liste)
    for i in xrange (0, len (liste)) :
        n = i
        m = randint (0, len (liste)-1)
        s = li [n]
        li [n] = li [m]
        li [m] = s
    return li

File: ecrit_2010.tex, line 342


from random import randint
import copy

def permutation (liste) :
    li = [ ]
    n  = len (liste)
    for i in xrange (0, n) :
        m = randint (0, len (liste)-1)
        li.append (liste [m])
        del liste [m]          # on supprime l'élément tiré au hasard
    return li

File: ecrit_2010.tex, line 358


from random import randint
import copy

def permutation (liste) :
    li = [ ]
    n  = len (liste)
    for i in xrange (0, n) :
        m = randint (0, len (liste)-1)
        if liste [m] not in li : 
            li.append (liste [m])
    return li

File: ecrit_2010.tex, line 391


def nom_csp (csp) :                      # csp est un entier compris entre 1 et 4
    if   csp == 1  : return "cat. A"           
    elif csp == 2  : return "cat. B"
    elif csp == 3  : return "cat. C"
    else           : return "cat. D"

File: ecrit_2010.tex, line 405


def nom_csp (csp) :                      # csp est un entier compris entre 1 et 4
    if csp <= 2  : 
        if csp == 1 : return "cat. A"           
        else        : return "cat. B"                
    else :
        if csp == 3 : return "cat. C"
        else        : return "cat. D"

File: ecrit_2010.tex, line 450


def nom_csp (csp) :
    if   csp == 3  : return "cat. C"           
    elif csp == 1  : return "cat. A"
    elif csp == 2  : return "cat. B"
    else           : return "cat. D"

File: ecrit_2010.tex, line 513


def calculeN (I,J) :  # I et J sont des entiers comme par exemple I=3 et J=5
    
    nombre = [ [0 for i in range (0, J) ] for i in range (0, I) ]
      # nombre est alors égal à [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
        
    for i in range (0, I) : 
        nombre [i][0] = 1
        
    for j in range (0, I) : 
        nombre [0][j] = 1
        
    for i in range (1, I) : 
        for j in range (1, J) :
            nombre [i][j] = nombre [i-1][j] + nombre [i][j-1] 
            
    return nombre

nombre = calculeN (3,5)
for l in nombre : print l

File: ecrit_2010.tex, line 536


[1, 1, 1, 0, 0]
[1, 2, 3, 3, 3]
[1, 3, 6, 9, 12]

File: ecrit_2010.tex, line 572


for j in range (0, I) :   # il faut écrire range (0, J)
    nombre [0][j] = 1

File: ecrit_2010.tex, line 578


[1, 1, 1, 1, 1]
[1, 2, 3, 4, 5]
[1, 3, 6, 10, 15]

File: ecrit_2010.tex, line 589


def calculeN (I,J) : 
    
    nombre = [ [0 for i in range (0, J) ] for i in range (0, I) ]
        
    for i in range (0, I) : 
        nombre [i][0] = 1
        
    for j in range (1, J) : 
        nombre [0][j] = 1
    nombre [0][1:5] = [2,] * (J-1)  ##### ligne ajoutée
        
    for i in range (1, I) : 
        for j in range (1, J) :
            nombre [i][j] = nombre [i-1][j] + nombre [i][j-1] 
            
    return nombre

nombre = calculeN (3,5)
for l in nombre : print l

File: ecrit_2010.tex, line 612


[1, 2, 2, 2, 2]
[1, 3, 5, 7, 9]
[1, 4, 9, 16, 25]

File: ecrit_2010.tex, line 641


def generation_ensemble (n, s, s1, s2) :
    l     = [ ]
    alpha = s * s2 / s1
    beta  = s2 * (1.0 - s**2) ** 0.5
    for i in range (0, n) :
        x     = random.gauss (0,s1)
        u     = random.gauss (0,1.0)
        y     = alpha * x + beta * u
        l [i] = [ [x,y] ]              # ligne 26
    return l

File: ecrit_2010.tex, line 656


Traceback (most recent call last):
  File "examen2010.py", line 62, in <module>
    points       = generation_ensemble (50000, 1., 2., 6., 0.5)
  File "examen2010.py", line 26, in generation_ensemble
    l [i] = [ [x,y] ]
IndexError: list assignment index out of range

File: ecrit_2010.tex, line 671


def generation_ensemble2 (n, s, s1, s2) :
    l = [ ]
    a = s * 100
    for i in range (0, n) :
        x  = random.gauss (0,s1)
        if (i % 100) <= a :           # le symbole % désigne le modulo:  
                                      # i % 100 est le reste de la division de i par 100
            y = x * s2 / s1
        else :
            y = random.gauss (0,s2)
        l += [ [x,y] ]
    return l

File: ecrit_2011.tex, line 54


def remplissage (mat, x , y) :        # ligne 1
    dico = { (x,y):0 }                # ligne 2
    while len (dico) > 0 :            # ligne 3
        point        = dico.popitem ()# retourne un élément du dictionnaire et le supprime
        x,y          = point [0]      # ligne 5
        mat [x][y]   = 1              # ligne 6
        dico [x-1,y] = 0              # ligne 7
        dico [x+1,y] = 0              # ligne 8
        dico [x,y-1] = 0              # ligne 9
        dico [x,y+1] = 0              # ligne 10

File: ecrit_2011.tex, line 69


...
118 41 13
118 40 13
118 34 8
118 34 7
118 41 13
118 40 13
118 34 8
118 34 7
118 41 13
...

File: ecrit_2011.tex, line 97


def remplissage (mat, x , y) :        # 
    dico = { (x,y):0 }                # 
    while len (dico) > 0 :            # 
        point        = dico.popitem ()# 
        x,y          = point [0]      # 
        if mat [x][y] == 1 : continue # ligne ajoutée
        mat [x][y]   = 1              # 
        dico [x-1,y] = 0              # 
        dico [x+1,y] = 0              # 
        dico [x,y-1] = 0              # 
        dico [x,y+1] = 0              # 

File: ecrit_2011.tex, line 113


def remplissage (mat, x , y) :        # 
    dico = { (x,y):0 }                # 
    while len (dico) > 0 :            # 
        point        = dico.popitem ()# 
        x,y          = point [0]      # 
        mat [x][y]   = 1              # 
        if mat[x-1][y] == 0 : dico [x-1,y] = 0  # 
        if mat[x+1][y] == 0 : dico [x+1,y] = 0  # 
        if mat[x][y-1] == 0 : dico [x,y-1] = 0  # 
        if mat[x][y+1] == 0 : dico [x,y+1] = 0  # 

File: ecrit_2011.tex, line 128


def remplissage (mat, x , y) :         
    int compte = 0                       # ligne ajoutée
    dico = { (x,y):0 }                 
    while len (dico) > 0 :             
        point        = dico.popitem () 
        x,y          = point [0]       
        if mat [x][y] == 1 : continue 
        mat [x][y]   = 1               
        dico [x-1,y] = 0               
        dico [x+1,y] = 0               
        dico [x,y-1] = 0               
        dico [x,y+1] = 0               
        compte += 1                      # ligne ajoutée
    return comte                         # ligne ajoutée

File: ecrit_2011.tex, line 165


def resolution_simple (objets, sac) :
    objets.sort (reverse = True)
    solution = []
    for o in objets :
        ...
    return solution

File: ecrit_2011.tex, line 192


def resolution (objets, sac) :
    if len (objets) == 1 :
        if objets [0] <= sac :  return [ objets [0] ]
        else :                  return []
        
    reduit  = objets [1:]
    s1      = resolution (reduit, sac)
    s2      = resolution (reduit, sac - objets [0])   # ligne B
    
    t1      = sum(s1)
    t2      = sum(s2) + objets [0]                    # ligne C
    
    if   sac >= t1 and (t1 >= t2 or t2 > sac) : return s1
    elif sac >= t2 and (t2 >= t1 or t1 > sac) : return [ objets [0], ] + s2
        
obj = [2,4,7,10]
sac = 15
print "solution ",resolution (obj, sac) # ligne A

File: ecrit_2011.tex, line 215


solution 
Traceback (most recent call last):
  File "examen2011.py", line A, in <module>
    print "solution ",resolution (obj, sac)
  File "examen2011.py", line B, in resolution
    s2      = resolution (reduit, sac - objets [0])
  File "examen2011.py", line C, in resolution
    t2      = sum(s2) + objets [0]
TypeError: 'NoneType' object is not iterable

File: ecrit_2011.tex, line 241


def resolution_simple (objets, sac) :
    objets.sort (reverse = True)
    solution = []
    for o in objets :
        if sum(solution) + o <= sac :   # ligne ajoutée
            solution.append (o)         # ligne ajoutée
    return solution

File: ecrit_2011.tex, line 260


t2      = sum(s2) + objets [0]
TypeError: 'NoneType' object is not iterable

File: ecrit_2011.tex, line 278


s2      = resolution (reduit, sac - objets [0])   # ligne B

File: ecrit_2011.tex, line 284


if   sac >= t1 and (t1 >= t2 or t2 > sac) : return s1
elif sac >= t2 and (t2 >= t1 or t1 > sac) : return [ objets [0], ] + s2

File: ecrit_2011.tex, line 291


if   sac >= t1 and (t1 >= t2 or t2 > sac) : return s1
elif sac >= t2 and (t2 >= t1 or t1 > sac) : return [ objets [0], ] + s2
else : return []     # ligne ajoutée

File: ecrit_2007_rattrapage.tex, line 32


l2 = [ ( l [i], i ) for i in range (0, len (l)) ]
l2.sort ()
print l2 [0][1]  # affiche la position du plus petit élément 
                 # dans le tableau initial

File: ecrit_2007_rattrapage.tex, line 50


def ensemble_lettre (s) :
	  ens = []
	  for i in range (0, len (s)) :
	      c = s [i]
	      if c in ens :
	          ens.append (c)
	  return ens
      
print lettre ("baaa")

File: ecrit_2007_rattrapage.tex, line 75


def ensemble_lettre (s) :
    ens = []
    for i in range (0, len (s)) :
        c = s [i]
        if c not in ens :
            ens.append (c)
    return ens

File: ecrit_2007_rattrapage.tex, line 98


def autre_parcours (n) :
    i = 0
    j = 0
    k = 0
    
    while k < n :
        print (k,i,j)
        if i == 0 and j == 0 :
            k += 1
        if j == 0 and i < k :
            i += 1
        elif i == k and j < k :
            j += 1
        elif j == k and i > 0 :
            i -= 1
        elif i == 0 and j > 0 :
            j -= 1

autre_parcours (3)

File: ecrit_2007_rattrapage.tex, line 127


(0, 0, 0)
(1, 1, 0)
(1, 1, 1)
(1, 0, 1)
(1, 0, 0)
(2, 1, 0)
(2, 2, 0)
(2, 2, 1)
(2, 2, 2)
(2, 1, 2)
(2, 0, 2)
(2, 0, 1)
(2, 0, 0)

File: ecrit_2007_rattrapage.tex, line 165


k = [10,14,15,-1,6]
l = []
for i in range (0,len (k)) :
    l.append ( k [ len (k) - i ] )

File: ecrit_2007_rattrapage.tex, line 180


k = [10,14,15,-1,6]
l = []
for i in range (0,len (k)) :
    l.append ( k [ len (k) - i-1 ] )  # -1 a été ajouté

File: ecrit_2007_rattrapage.tex, line 203


def puiss (x, n) :
    s = 1.0
    for i in range (0,n) :
        s *= x
    return s

def log_suite (x) :
    x    = float (x-1)
    # ......
    s    = 0
    old  = -1
    n    = 1
    while abs (old - s) > 1e-10 :
        old = s
        po  = puiss (x,n) / n
        if n % 2 == 0 : po = -po
        s  += po
        n  += 1
        # ......
    return s
    
print log_suite (2)

File: ecrit_2007_rattrapage.tex, line 231


# ......
# ......
# ......
# ......
# ......
# ......
def log_suite (x) :
    x    = float (x-1)
    x0   = x
    s    = 0
    old  = -1
    n    = 1
    while abs (old - s) > 1e-10 :
        old = s
        po  = x / n
        if n % 2 == 0 : po = -po
        s  += po
        n  += 1
        x  *= x0
    return s
    
print log_suite (2)

File: ecrit_2007_rattrapage.tex, line 269


def racine_carree (k) :
    x0 = float (k)+1
    x  = float (k)
    while abs (x-x0) > 1e-10 :
        x0 = x
        x  = (k-x*x) / (2 * x) + x
    return x

File: ecrit_2007_rattrapage.tex, line 339


class Noeud :
    def __init__ (self, mot) :
        self.mot = mot
        self.avant = None
        self.apres = None
    def insere (self, mot) :
        if mot < self.mot :
            if self.avant == None : self.avant = Noeud (mot)
            else : self.avant.insere (mot)
        else :
            if self.apres == None : self.apres = Noeud (mot)
            else : self.apres.insere (mot)
    def affiche (self) :
        if self.avant != None : self.avant.affiche ()
        print self.mot
        if self.apres != None : self.apres.affiche ()
            
li = ["premier","deuxième","troisième","quatrième", \
      "cinquième","sixième","centième","mystère"]
r = None
for m in li :
    if r == None : r = Noeud (m)
    else : r.insere (m)
r.affiche ()

File: ecrit_2007_rattrapage.tex, line 372


centième
cinquième
deuxième
mystère
premier
quatrième
sixième
troisième

File: ecrit_2007_rattrapage2.tex, line 32


s = 0
for i in range (1,101) :
   s = i + 100-i+1
s = s / 2

File: ecrit_2007_rattrapage2.tex, line 56


def fusion (l1,l2) :
  i,j = 0,0
  r = []

  while len (r) < len (l1) + len (l2) :
    if i < len (l1) and (j >= len (l2) or l1[i] < l2 [j]) :
      r.append (l1 [i])
      i += 1
    else :
      r.append (l2 [j])
      j += 1
      
  return r

File: ecrit_2007_rattrapage2.tex, line 101


class Noeud : 
  def __init__ (self) :
    self.n1 = None
    self.n2 = None

root = Noeud ()
root.n1 = Noeud ()
root.n2 = Noeud ()
root.n1.n1 = Noeud ()
root.n1.n2 = root

File: ecrit_2007_rattrapage2.tex, line 128


def compte_noeud (self, l = []) :
    if self not in l :
        l.append (self)
        if self.n1 != None : self.n1.compte_noeud (l)
        if self.n2 != None : self.n2.compte_noeud (l)
    return len (l)

File: ecrit_2007_rattrapage2.tex, line 150


%

File: ecrit_2009_rattrapage.tex, line 42


def numero_simple (nbimpair, nbpair) :
    im = [..... for i in range (1, nbimpair+1) ]
    pa = [..... for i in range (1, nbpair  +1) ]
    return im,pa

File: ecrit_2009_rattrapage.tex, line 51


def numerotation (longueur, debut, moy) :
    res = []
    for li in range (0, len (longueur)) :
        if len (res) == 0 : x1 = debut
        else :              x1 = res [-1][1]+2
        
        nb = longueur [li] / moy                  # c'est une division entière
                                                  # ligne importante
                                                  # pour la dernière question
        x2 = x1 + nb*2
        res.append ( (x1,x2) )
        debut = x2 + 2
    return res
    
def numero_deux (impair, pair) :
    moypair   = sum (pair)   / len (pair)         # vaut 25
    moyimpair = sum (impair) / len (impair)       # vaut 41
    im        = numerotation (impair, 1, moyimpair)
    pa        = numerotation (pair,   2, moypair)
    return im,pa
    
impair = [20,70,35]
pair   = [20,20,40,35,10]    
im,pa  = numero_deux (impair, pair)
print im
print pa

File: ecrit_2009_rattrapage.tex, line 83


[(1, 1), (3, 5), (7, 7)]
[(2, 2), (4, 4), (6, 8), (10, 12), (14, 14)]

File: ecrit_2009_rattrapage.tex, line 108


a = [ None, [0] ]
b = [ None, [0] ]
c = [ None, [0] ]

a [0] = b
b [0] = c
c [0] = a

x = a
for i in range (0, 9) :
    x [1][0] += 1
    x = x [0]
    
print "a [1][0] =", a [1][0]
print "b [1][0] =", b [1][0]
print "c [1][0] =", c [1][0]

File: ecrit_2009_rattrapage.tex, line 131


a = [ None, [0] ]
b = [ None, [0] ]
c = [ None, [0] ]

a [0] = b
b [0] = c
c [0] = a

import copy             # ligne ajoutée
a = copy.copy (a)       # ligne ajoutée

x = a
for i in range (0, 9) :
    x [1][0] += 1
    x = x [0]
    
print "a [1][0] =", a [1][0]
print "b [1][0] =", b [1][0]
print "c [1][0] =", c [1][0]

File: ecrit_2009_rattrapage.tex, line 157


a = [ None, [0] ]
b = [ None, [0] ]
c = [ None, [0] ]

a [0] = b
b [0] = c
c [0] = a

import copy             	
a = copy.deepcopy (a)     # ligne modifiée

x = a
for i in range (0, 9) :
    x [1][0] += 1
    x = x [0]
    
print "a [1][0] =", a [1][0]
print "b [1][0] =", b [1][0]
print "c [1][0] =", c [1][0]

File: ellipse_fin_exo.tex, line 4


i = random.randint (0,n) # tire aléatoirement un nombre entier entre 0 et n inclus

l.sort ()                # trie la liste l quel que soit son contenu

File: ellipse_fin_exo.tex, line 12


def permutation_aleatoire (l) :
    ....
    return ...
    
print permutation_aleatoire ([1,2,3,4])   # affiche [3,1,4,2]

File: ellipse_fin_exo.tex, line 29


tab = ["zéro", "un", "deux"] # tableau à trier
pos = [ (tab [i],i) for i in range (0, len (tab)) ] # tableau de couples
pos.sort () # tri
print pos # affiche [('deux', 2), ('un', 1), ('zéro', 0)]

File: ellipse_fin_exo.tex, line 38


from random import randint

def permutation (liste) :
    alea        = [ randint (0,len (liste)) for i in liste ]
    couple      = [ (r,l) for r,l in zip (alea,liste) ]
    couple.sort ()
    permutation = [ l[1] for l in couple ]
    return permutation

liste = [ i*2 for i in range (0,10) ]
permu = permutation (liste)
print liste  # affiche [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
print permu  # affiche [2, 6, 16, 10, 8, 14, 0, 12, 18, 4]

File: conseil_ecrire_programme.tex, line 46

    
def somme_double (liste) :
    return 1.0 * sum(liste)

def test_somme_double () :
    y = somme_double([ 1 ]) / 2
    if y == 0 : raise Exception ("valeur > 0 attendue")
        
if __name__ == "__main__" :
    test_somme_double()

File: conseil_ecrire_programme.tex, line 60

    
Traceback (most recent call last):
  File "conseil.py", line 10, in <module>
    test_somme_double()
  File "conseil.py", line 7, in test_somme_double
    if y == 0 : raise Exception ("valeur > 0 attendue")
Exception: valeur > 0 attendue

File: resume_utile.tex, line 25


import sys
print (sys.version)

File: resume_utile.tex, line 43


def fonction () :
     """fonction de 
     démonstration"""
     return 0
help (fonction)    # affiche fonction de 
                   # démonstration 

File: resume_utile.tex, line 66


va = <valeur>

File: resume_utile.tex, line 83


t = ()        # tuple vide
t = (2, "e")  # tuple de deux éléments
print (t[0])  # affiche le premier élément

File: resume_utile.tex, line 108


t [i:j]  # correspond à un sous-ensemble allant des indices i à j exclu
t [:j]   #  = t[0:j]
t [i:]   # = t [i: len (t)]

File: resume_utile.tex, line 116


st = "langage python"
st = 'langage python'           # idem
st = 'un guillement "'          # chaîne contenant un guillement
st = "un guillement \""         # chaîne contenant un guillement, il faut ajouter \
                                #     pour ne pas confondre avec l'autre guillement
st = st.upper ()                # mise en lettres majuscules
i  = st.find ("PYTHON")         # on cherche "PYTHON" dans st
print (i)                       # affiche 8  Version 3.x, écrire print (i),
                                #    pour la version 2.x, écrire print i
print (st.count ("PYTHON"))     # affiche 1  Version 3.x : idem print (...)
print (st.count ("PYTHON", 9))  # affiche 0  Version 3.x : idem print (...)

File: resume_utile.tex, line 189


x = 0.123456789
print ("%1.2f" % x)    # donne 0.12
s = "%2.2e %s" % (3.14159, "est une approximation de pi")
print (s)              # Version 2.x : print s

File: resume_utile.tex, line 203


a = [1,2]
b = a

File: resume_utile.tex, line 210


a = [1,2]
import copy
b = copy.copy (a)

File: resume_utile.tex, line 218


a = [1,2]
import copy
b = copy.deepcopy (a)

File: resume_utile.tex, line 231


x = [4,5]               # création d'une liste composée de deux entiers
x = ["un",1,"deux",2]   # création d'une liste composée deux chaînes de caractères
                        # et de deux entiers, l'ordre d'écriture est important
x = [3,]                # création d'une liste d'un élément, sans la virgule, 
                        # le résultat reste une liste
x = [ ]                 # crée une liste vide
x = list ()             # crée une liste vide

File: resume_utile.tex, line 368


x = range(0,5)                      # liste des entiers de 0 à 5 exclu
                                    # Version 3.x : range retourne un itérateur, il faut écrire
                                    #     x = list(range(0,5))
y = [ i for i in x if i % 2 == 0]   # sélection des éléments pairs
print (y)                           # affiche [0,2,4]		  Version 2.x : écrire print y
z = [ i+j for i in x for j in x]    # construit tous les nombres i+j possibles
print (z)                           # affiche [0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3, 
                                    # 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8]

File: resume_utile.tex, line 385


x = { "cle1":"valeur1", "cle2":"valeur2" }
print (x ["cle1"])        # affiche valeur1  Version 2.x : écrire print ...
x [(0,1)]  = "clé tuple"  # ajoute une nouvelle valeur dont la clé est (0,1)
                          #   les parenthèses sont superflues
y = { }                   # crée un dictionnaire vide
z = dict ()               # crée aussi un dictionnaire vide

File: resume_utile.tex, line 490


import numpy
a = numpy.array ( [0,1] )

File: resume_utile.tex, line 503


if x < 5 :
    x = x*2
    ...

File: resume_utile.tex, line 511


if x < 5 :
    x = x*2
    ...
else :
    x = x*3
    ...

File: resume_utile.tex, line 522


if x < 5 :  x=x*2
else :      x=x*3

File: resume_utile.tex, line 529


if   x < 5 :  x = x*2
elif x > 5 :  x = x*3
else       :  x = x*6

File: resume_utile.tex, line 537


if 5 < x and x < 10 :     # peut être écrit : if 5 < x < 10 :
    ...

File: resume_utile.tex, line 546


while condition :
    # lignes décalées
    # contenu de la boucle

File: resume_utile.tex, line 554


for i in range(0,n) :             # parcourt tous les entiers de 0 à n-1 inclus   
for i in xrange(0,n) :            # même chose mais en plus rapide  
                                  # Version 3.x : la fonction xrange n'existe plus, 
                                  #               et range équivaut à xrange
for i in range(n,0,-1) :          # parcourt tous les entiers de n à 1 inclus 
                                  #                  dans le sens décroissant   
for i in range(2,1000,3) :        # parcourt tous les entiers de 2 à 1000 de 3 en 3
                                  #                                     (2,5,8,...)
for e in li :                     # parcourt tous les éléments de la liste li
for cle,valeur in di.items () :   # parcourt tous les éléments du dictionnaire di

File: resume_utile.tex, line 573


l = [ 4, 5, 6 ]
s = 0
for i in range(0,len(l)) : 
    s += l[i]

File: resume_utile.tex, line 581


l = [ 4, 5, 6 ]
s = 0
for i,x in enumerate(l) :
    s += x

File: resume_utile.tex, line 591


l = [ 4, 5, 6 ]
g = [ 3,10,11 ]
s = 0
for i in range(0,len(l)) : 
    s += l[i] + g[i]

File: resume_utile.tex, line 600


l = [ 4, 5, 6 ]
g = [ 3,10,11 ]
s = 0
for x,y in zip(l,g) :
    s += x + y

File: resume_utile.tex, line 614


def fonction (x) : return x % 2
li  = [ 3,4,5]
li2 = map (fonction, li)
print (list(li2))           # affiche [ 1, 0, 1 ]

File: resume_utile.tex, line 623


def fonction (x) :
    if x % 2 == 0 : yield x
li  = [ 3,4,5]
li2 = map (fonction, li)
print (list(li2))           # affiche [ 4 ]

File: resume_utile.tex, line 636


with random_matrix(1000,1000) as mat :
    #   appelle mat.__enter__()
    ...
    #   appelle mat.__exit__()

File: resume_utile.tex, line 652


def exemple_fonction (p1, p2, p3) :
    # code de la fonction
    return r1, r2

a,b = exemple_fonction (1,2,3)   # exemple d'appel de la fonction

File: resume_utile.tex, line 662


def exemple_fonction (p1, p2 = 4, p3 = 7) :
    # code de la fonction
    return r1, r2

a,b = exemple_fonction (1)         # = exemple_fonction (1,4,7)
a,b = exemple_fonction (1,2,3)     # = exemple_fonction (1,2,3)
a,b = exemple_fonction (1,2)       # = exemple_fonction (1,2,7)
a,b = exemple_fonction (1,p3 = 2)  # = exemple_fonction (1,4,2)

File: resume_utile.tex, line 675


def exemple_fonction (p1, p2 = 4, p3) :
    # code de la fonction
    return r1, r2
# affiche le message d'erreur : SyntaxError: non-default argument follows default argument

File: resume_utile.tex, line 684


def exemple_fonction (p1) :
    p1 = 3
a = 1
exemple_fonction (a)
print (a)  # affiche 1

File: resume_utile.tex, line 694


def exemple_fonction (p1) :
    p1[0] = 3
a = [1]
exemple_fonction (a)
print (a)  # affiche [3]    Version 2.x : print ...

File: resume_utile.tex, line 707


def fonction (x) : return x % 2
li  = [ 3,4,5]
li2 = map (fonction, li)
print (list(li2))           # affiche [ 1, 0, 1 ]

File: resume_utile.tex, line 716


li  = [ 3,4,5]
li2 = map (lambda x : x%2, li)
print (list(li2))                 # affiche [ 1, 0, 1 ]

File: resume_utile.tex, line 724


li  = [ 3,4,5]
k   = 2
li2 = map (lambda x,y=k : x%k, li)
print (list(li2))                 # affiche [ 1, 0, 1 ]

File: resume_utile.tex, line 736


def iterate_double_on_list(l) :
    for x in l :
        yield x*2
print (iterate_double_on_list( [4,5,6]))
     # affiche <generator object iterate_double_on_list at 0x025196C0>

File: resume_utile.tex, line 746


for x in iterate_double_on_list( [4,5,6]) :
    print (x)

File: resume_utile.tex, line 762


class ma_classe :
    def __init__ (self, att1, att2, att3) :
        self.att1 = att1
        self.att2 = att2
        self.att3 = att3
        self.att4 = att1 * att2 * att3
        
a = ma_classe (-1,1,2) # déclare une variable de type ma_classe
print (a.att1)  # affiche -1       
print (a.att2)  # affiche 3        Version 2.x : print ...
print (a.att3)  # affiche 4
print (a.att4)  # affiche -12

File: resume_utile.tex, line 779


class ma_classe :
    def __init__ (self, att1, att2, att3) :
        self.att1 = att1
        self.att2 = att2
        self.att3 = att3
        self.att4 = self.calcule4 ()
        
    def calcule4 (self) :
        return self.att1 * self.att2 * self.att3
        
a = ma_classe (-1,1,2) # déclare une variable de type ma_classe
print (a.att1)           # affiche -1
print (a.att2)           # affiche 3
print (a.att3)           # affiche 4
print (a.att4)           # affiche -12

File: resume_utile.tex, line 804


class ma_classe :
    def __init__ (self, att1, att2, att3) :
        self.att1 = att1                    # attribut
        self.att2 = att2                    # attribut
        self.att3 = att3                    # attribut
        self.att4 = att1 * att2 * att3      # attribut

    def calcule (self,x) :                   # méthode
        return self.att1 * self.att2 * self.att3 * x
				
a = ma_classe (1,2,3)
print (a.att1)                 # affiche 1 
print (a.__dict__ ["att1"])    # affiche aussi 1, ligne équivalente à la précédente
print (a.calcule(2))           # appel d'une méthode

File: resume_utile.tex, line 826


class ma_classe :
    def __init__ (self, att1, att2, att3) :
		    # ...

    @staticmethod
    def calcule_static (x,y) :         # méthode statique
        return x * y
				
print (ma_classe.calcule_static(2,3))  # appel d'une méthode statique

File: resume_utile.tex, line 844


class ma_classe :
    def __init__ (self, att1, att2, att3) :
        self.att1 = att1
        self.att2 = att2
        self.att3 = att3
        self.att4 = att1 * att2 * att3
        
    def __add__ (self, a) :
         return ma_classe (self.att1 + a.att1, self.att2 + a.att2, \
                       self.att3 + a.att3, self.att4 + a.att4)

a = ma_classe (1,2,3)
b = ma_classe (4,5,6)
c = a + b              # n'a de sens que si l'opérateur __add__ a été redéfini

File: resume_utile.tex, line 868


class ma_classe :
    def __init__ (self, att1, att2, att3) :
        self.att1 = att1
        self.att2 = att2
        self.att3 = att3
        self.att4 = att1 * att2 * att3

a = ma_classe (1,2,3)
b = a
b.att1 = -16
print (a.att1)  # affiche -16
print (b.att1)  # affiche -16

File: resume_utile.tex, line 885


class ma_classe :
    def __init__ (self, att1, att2, att3) :
        self.att1 = att1
        self.att2 = att2
        self.att3 = att3
        self.att4 = att1 * att2 * att3

a = ma_classe (1,2,3)
import copy
b = copy.copy (a)
b.att1 = -16
print (a.att1)  # affiche 1
print (b.att1)  # affiche -16

File: resume_utile.tex, line 910


class ma_classe :
    def __init__ (self, att1, att2, att3) :
        self.att1 = att1
        self.att2 = att2
        self.att3 = att3
        self.att4 = att1 * att2 * att3

class ma_classe2 (ma_classe) :      # héritage simple
    pass                            # pour dire que la classe est vide

File: resume_utile.tex, line 928


class ma_classe :
    def __init__ (self, att1) :
        self.att1 = att1
        self.att2 = self.calcul ()

    def calcul (self) :
        return self.att1 ** 2

class ma_classe2 (ma_classe) :
    def calcul (self) :
        # dans cette méthode, on change le comportement
        # de la méthode calcul tout en se servant de celui 
        # de la classe mère
        return ma_classe.calcul (self) * self.att1

a = ma_classe (2)
b = ma_classe2 (2)
print (a.att2)   # affiche 4  = 2 * 2
print (b.att2)   # affiche 8  = (2*2) * 2

File: resume_utile.tex, line 955


def makebold(fn):
    def wrapped():
        return "<b>" + fn() + "</b>"
    return wrapped

def makeitalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped

@makebold
@makeitalic
def hello():
    return "hello world"

print (hello()) ## returns <b><i>hello world</i></b>

File: resume_utile.tex, line 976


class C(object):
    def __init__ (self) :
        self._p = 1
    @property
    def p(self):
        return self._p
    @p.setter
    def p(self, val):
        self._p = val * 2
        
obj = C()
print (obj.p)  # utilise p_get, affiche 1
obj.p = 5      # utilise p_set
print (obj.p)  # utilise p_get affiche 10

File: resume_utile.tex, line 1003


f = open ("nom-fichier", "w") # ouverture en mode écriture "w" ou écriture ajout "a"

f.write (  s )                # écriture de la chaîne de caractères  s 
f.write (  s2 )               # écriture de la chaîne de caractères  s2
...

f.close ()  # fermeture

File: resume_utile.tex, line 1022


with open ("nom-fichier", "w") as f : 
    f.write (  s )                
    f.write (  s2 )               

File: resume_utile.tex, line 1029


with open ("nom-fichier", "w", encoding = "utf8") as f : 
    f.write (  s )                
    f.write (  s2 )               

File: resume_utile.tex, line 1039


f = open ("essai.txt", "r")   # ouverture du fichier en mode lecture
l = f.readlines ()            # lecture de toutes les lignes, 
                              #   elles sont placées dans une liste
f.close ()                    # fermeture du fichier

for s in l : print (s)        # on affiche les lignes à l'écran

File: resume_utile.tex, line 1053


f = open ("essai.txt", "r")     # ouverture du fichier en mode lecture
l = f.readlines ()              # lecture de toutes les lignes, 
                                #   elles sont placées dans une liste placées dans une liste
f.close ()                      # fermeture du fichier

l_net = []                      # contiendra la liste nettoyée des lignes du fichier
for s in l : 
    s2 = s.replace ("\n", "")   # on supprime le code de fin de ligne \n 
    s2 = s2.replace ("\r", "")  # on supprime le code de fin de ligne \r 
                                #                   (Windows uniquement)
	  s2 = s2.strip("\r\n")       # cette ligne est équivalente aux deux précédentes
    l_net.append (s2)           # on ajoute le résultat à la liste nettoyée

File: resume_utile.tex, line 1072


nom  ; prénom ; livre
Hugo  ; Victor  ; Les misérables
Kessel ; Joseph  ; Le lion
Woolf ; Virginia  ; Mrs Dalloway
Calvino ; Italo  ; Le baron perché

File: resume_utile.tex, line 1082


f = open ("essai.txt", "r")     # ouverture du fichier en mode lecture
l = f.readlines ()              # lecture de toutes les lignes, placées dans une liste
f.close ()                      # fermeture du fichier

for s in l : 
    s2 = s.replace ("\n", "")   # on supprime le code de fin de ligne \n 
    s2 = s2.replace ("\r", "")  # on supprime le code de fin de ligne \r (Windows uniquement)
    case = s2.split (";")
    if len (case) >= 3 :
        print (case [1], " ", case [0], " a écrit ", case [2])
				      # Version 2.x : print ...

File: resume_utile.tex, line 1102


# définition du module geometrie.py

def carre (x) :
    return x ** 2
    
class point :
    def __init__ (self,x,y) :
        self.x, self.y = x,y
        
    def norme (self) :
        return (self.x ** 2 + self.y ** 2) ** 0.5

File: resume_utile.tex, line 1120


import geometrie
print (geometrie.carre (1.5))
p = geometrie.point (1,2)

File: resume_utile.tex, line 1127


import geometrie as GEO  # on donne un pseudonyme au module geometrie
print (GEO.carre (1.5))
p = GEO.point (1,2)

File: resume_utile.tex, line 1134


from  geometrie import * 
print (carre (1.5))
p = point (1,2)

File: resume_utile.tex, line 1144


if __name__ == "__main__" :
    # quelques instructions ici

File: resume_utile.tex, line 1160


def inverse (x):
    y = 1.0 / x
    return y
b = inverse (0)
print (b)

File: resume_utile.tex, line 1170


Traceback (most recent call last):
  File "cours.py", line 2, in ?
    y = 1.0 / x
ZeroDivisionError: float division

File: resume_utile.tex, line 1179


def inverse (x):
    y = 1.0 / x
    return y
try :
    b = inverse (0)  # déclenche une exception
    print (b)
except :
    print ("le programme a déclenché une erreur")

File: resume_utile.tex, line 1192


def inverse (x):
    y = 1.0 / x
    return y
try :
    print (inverse (2))
    print (inverse (0))
except Exception as exc:
    print ("exception de type ", exc.__class__)
         # affiche exception de type  exceptions.ZeroDivisionError
    print ("message ", exc)
         # affiche le message associé à l'exception

File: resume_utile.tex, line 1208


def inverse (x):
    y = 1.0 / x
    return y
try :
    print ((-2.1) ** 3.1)
    print (inverse (2))
    print (inverse (0))
except ZeroDivisionError:
    print ("division par zéro")
except Exception as exc:
    print ("erreur insoupçonnée : ", exc.__class__)
    print ("message ", exc)

File: resume_utile.tex, line 1225


class AucunChiffre (Exception) :
    """chaîne de caractères contenant
    aussi autre chose que des chiffres"""

    def __init__(self, s, f = "") :
        Exception.__init__(self, s)
        self.s = s
        self.f = f

    def __str__(self) :
        return """exception AucunChiffre, lancée depuis la fonction """ + self.f + \
        " avec le paramètre " + self.s

def conversion (s) :
    """conversion d'une chaîne de caractères en entier"""
    if not s.isdigit () :
        raise AucunChiffre, (s, "conversion")
    return int (s)

try :
    s = "123a"
    i = conversion (s)
    print (s, " = ", i)
except AucunChiffre as exc :
    print (AucunChiffre.__doc__, " : ", exc)
    print ("fonction : ", exc.f)

File: resume_utile.tex, line 1264


s = "abcdefghijklmnopqrstuvwxyz"
print (s [4])    # affiche "e"
print (s [4:6])  # affiche "ef"

File: resume_utile.tex, line 1276


l  = [ un, deux, trois, quatre ]
up = []
for i in range (0, len (l)) :
    up.append ( l [i].upper () )

File: resume_utile.tex, line 1295


l  = [ "un", "deux", "trois", "quatre" ]
up = []
for i in range (0, len (l)) :
    up.append ( l [i].upper () )

File: resume_utile.tex, line 1304


l  = [ "un", "deux", "trois", "quatre" ]
up = []
for m in l :
    up.append ( m.upper () )

File: resume_utile.tex, line 1322


l = [ "un", "deux", "trois", "quatre" ]
s = ""
for m in l :
    s += m # concaténation des mots en une seule chaîne de caractères

File: resume_utile.tex, line 1336


a = calcul1 (3)
b = calcul2 (a)
c = calcul3 (b) # c résultat souhaité et affiché

File: resume_utile.tex, line 1346


def calcul1(x) :
    return x+3
y = calcul1(4)
print (y)            # affiche None
                     # car la fonction calcul1 ne retourne pas de résultat, elle l'affiche

File: resume_utile.tex, line 1356


def calcul1(x) : print (x+3)
def calcul2(x) : return calcul1(x) + 5
y = calcul2(4)     # affiche l'erreur
                   # ported operand type(s) for +: 'NoneType' and 'int'

File: resume_utile.tex, line 1399

    
def somme_double (liste) :
    return 1.0 * sum(liste)

def test_somme_double () :
    y = somme_double([ 1 ]) / 2
    if y == 0 : raise Exception ("valeur > 0 attendue")
        
if __name__ == "__main__" :
    test_somme_double()

File: resume_utile.tex, line 1413

    
Traceback (most recent call last):
  File "conseil.py", line 10, in <module>
    test_somme_double()
  File "conseil.py", line 7, in test_somme_double
    if y == 0 : raise Exception ("valeur > 0 attendue")
Exception: valeur > 0 attendue

File: chapn_tools.tex, line 41


def run () :
    files = [".\\genchm.py", ".\\genhelp.py", "os", "sys"]
    res   = genhelp.genhelp (files)
    print res  # ['genchm.html', 'genhelp.html', 'os.html', 'sys.html']   
    genchm (res, "GenHelp")
    
if __name__ == "__main__" :
    # écrit des informations relatives à l'exécution de la fonction
    # run () dans le fichier profile.txt
    import profile
    profile.run ('run()', "profile.txt")  
 
    # récupère les informations stockées dans profile.txt
    # et construit le nombre de passages dans chaque
    # fonction et les temps d'exécution moyen                                      
    import pstats
    p = pstats.Stats('profile.txt')
    p.strip_dirs().sort_stats(-1).print_stats()

File: chapn_tools.tex, line 62


Mon May 12 22:38:02 2008    profile.txt

         77 function calls in 5.557 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        5    0.000    0.000    0.000    0.000 :0(append)
        4    0.000    0.000    0.000    0.000 :0(close)
        2    0.000    0.000    0.000    0.000 :0(len)
        4    0.003    0.001    0.003    0.001 :0(open)
       16    0.000    0.000    0.000    0.000 :0(replace)
        1    0.001    0.001    0.001    0.001 :0(setprofile)
        2    0.000    0.000    0.000    0.000 :0(split)
        5    5.551    1.110    5.551    1.110 :0(system)
        4    0.000    0.000    0.000    0.000 :0(write)
        1    0.000    0.000    5.556    5.556 <string>:1(<module>)
        1    0.000    0.000    2.562    2.562 genchm.py:102(genchm)
        1    0.000    0.000    0.001    0.001 genchm.py:11(genhhp)
        1    0.000    0.000    5.556    5.556 genchm.py:113(run)
        1    0.000    0.000    0.001    0.001 genchm.py:42(gen_premierepage)
       13    0.000    0.000    0.000    0.000 genchm.py:54(genhh_input)
        1    0.000    0.000    0.001    0.001 genchm.py:61(genhhc)
        8    0.000    0.000    0.000    0.000 genchm.py:7(g)
        1    0.000    0.000    0.001    0.001 genchm.py:83(genhhk)
        4    0.000    0.000    2.993    0.748 genhelp.py:17(generate_help_file)
        1    0.000    0.000    2.994    2.994 genhelp.py:26(genhelp)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    5.557    5.557 profile:0(run())

File: chapn_tools.tex, line 117


>>> addition ( [1,2], [3,-1])
[4, 1]

File: chapn_tools.tex, line 124


def _test():
    import doctest
    print doctest.testmod()

File: chapn_tools.tex, line 130


File "testdoc1.py", line 6, in __main__.addition
Failed example:
    addition ( [1,2], [3,-1])
Expected:
    [4,  1]
Got:
    [4, 1]
**********************************************************************
1 items had failures:
   1 of   2 in __main__.addition
***Test Failed*** 1 failures.

exemple de test avec \codesindex{doctest

# coding: latin-1
def addition (l1, l2):
    """cette fonction additionne deux listes
    >>> addition ( [], [])
    []
    >>> addition ( [1,2], [3,-1])
    [4, 1]
    """
    res = []
    for i in range (0, len (l1)) :
        res.append ( l1 [i] + l2 [i] )
    return res

def _test():
    import doctest
    doctest.testmod()

if __name__ == "__main__":
    _test()

File: chapn_tools.tex, line 148


Traceback (most recent call last):
    ...
Exception: listes de tailles différentes

exemple de test plus complet avec \codesindex{doctest

# coding: latin-1
def addition (l1, l2):
    """cette fonction additionne deux listes
    >>> addition ( [], [])
    []
    >>> addition ( [1,2], [3,-1])
    [4, 1]
    >>> addition ( [1], [3,-1])
    Traceback (most recent call last):
        ...
    Exception: listes de tailles différentes
    """
    if len (l1) != len (l2) :
        raise Exception ("listes de tailles différentes")
    res = []
    for i in range (0, len (l1)) :
        res.append ( l1 [i] + l2 [i] )
    return res

def _test():
    import doctest
    doctest.testmod()

if __name__ == "__main__":
    _test()

module à tester

# coding: latin-1
def addition (l1, l2):
    """cette fonction additionne deux listes"""
    if len (l1) != len (l2) :
        raise Exception ("listes de tailles différentes")    
    res = []
    for i in range (0, len (l1)) :
        res.append ( l1 [i] + l2 [i] )
    return res

liste de tests avec \codesindex{unittest

# coding: latin-1
import unittest
from testunit1 import *

class TestCase_for_addition (unittest.TestCase):
    
    def test_addition_vide (self) :
        """test_addition_vide : on vérifie que l'addtion de deux listes retourne une liste vide"""
        assert [] == addition ( [], [] )
        
    def test_addition (self) :
        """test_addition : test de [1,2] + [3,-1] != [4,1]"""
        l1 = [1,2]
        l2 = [3,-1]
        l  = addition (l1, l2)
        assert l [0] == 4 and l [1] == 1
        
    def test_exception (self) :
        """test_exception : on vérifie que l'addition 
        de deux listes de tailles différentes génère une exception"""
        l1 = [1]
        l2 = [3,-1]
        try :
            l  = addition (l1, l2)  # la fonction doit lancer une exception
            assert False            # si elle ne le fait pas, alors le test a achoué
        except Exception, e :
            # on vérifie que l'exception générée n'est pas due à l'instruction assert False
            assert str (e.__class__ .__name__) != "AssertionError"
            # on vérifie ici que le message de l'exception est celui attendu
            assert str (e) == "listes de tailles différentes"

if __name__ == "__main__" :
    # on lance les tests
    unittest.main ()                       

File: chapn_tools.tex, line 187


======================================================================
ERROR: test_addition : test de [1,2] + [3,-1] != [4,1]
----------------------------------------------------------------------
Traceback (most recent call last):
  File "testunit2.py", line 16, in test_addition
    assert l [0] == 4 and l [1] == 1
IndexError: list index out of range

File: chapn_tools.tex, line 197


======================================================================
FAIL: on vérifie que l'addition de deux listes de tailles différentes génère une exception
----------------------------------------------------------------------
Traceback (most recent call last):
  File "testunit2.py", line 27, in test_exception
    assert str (e.__class__ .__name__) != "AssertionError"
AssertionError

exécution de tests unitaires répartis sur plusieurs fichiers

# coding: latin-1
import unittest
import os

def get_test_file () :
    """retourne la liste de tous les fichiers *.py commençant par test_"""
    li = os.listdir (".")
    li = [ l for l in li if "test_" in l and ".py" in l and \
                            ".pyc" not in l and ".pyd" not in l]
    return li

def import_files (li) :
    """pour un fichier test_*.py, cherche les classes Test...
    et crée une suite de test pour ses méthodes commençant 
    par test..., retourne la suite de test"""
    allsuite = []
    for l in li :
        fi = l.replace (".py", "")
        mo = __import__ (fi)
        cl = dir (mo)
        for c in cl :
            if len (c) < 5 or c [:4] != "Test" : continue
            # classe de test c
            testsuite = unittest.TestSuite ()
            exec compile ("di = dir (mo." + c + ")", "", "exec")
            for d in di :
                if len (d) < 5 or d [:4] != "test" : continue
                # method d.c
                exec compile ("t = mo." + c + "(\"" + d + "\")", "", "exec")
                testsuite.addTest (t)
        allsuite.append ((testsuite, l))

    return allsuite

def main () :
    """crée puis lance les suites de textes définis dans 
    des programmes test_*.py"""
    li      = get_test_file ()
    suite   = import_files (li)
    runner  = unittest.TextTestRunner()
    for s in suite :
        print "running test for ", s [1]
        runner.run (s [0])
    
if __name__ == "__main__" :
    main ()

File: chapn_tools.tex, line 221


# coding: cp1252
import glob
import shutil
def copie_repertoire (rep1, rep2) :
    """copie tous les fichiers d'un répertoire rep1 vers un autre rep2"""
    li = glob.glob (rep1 + "/*.*")
    for l in li :
        to = l.replace (rep1, rep2)  # nom du fichier copié (on remplace rep1 par rep2)
        shutil.copy (l, to)
copie_repertoire ("c:/original", "c:/backup")

File: chapn_tools.tex, line 235


c:\python25\python.exe synchro.py c:/original c:/backup

File: chapn_tools.tex, line 247


interpréteur_python programme_python argument1 argument2 ...

lancer un programme \pythons en ligne de commande

# coding: latin-1
import glob
import shutil
def copie_repertoire (rep1, rep2) :
    """copie tous les fichiers d'un répertoire rep1 vers un autre rep2"""
    li = glob.glob (rep1 + "/*.*")
    for l in li :
        to = l.replace (rep1, rep2)  # nom du fichier copié 
                                     # (on remplace rep1 par rep2)
        shutil.copy (l, to)
        
import sys
                      # sys.argv [0] --> nom du programme (ici, synchro.py)
rep1 = sys.argv [1]   # récupération du premier paramètre
rep2 = sys.argv [2]   # récupération du second paramètre
copie_repertoire (rep1, rep2)

File: chapn_tools.tex, line 265


c:\python25\python.exe c:\batch\synchro.py "c:\Program Files\source" "c:\Program Files\backup"

File: chapn_tools.tex, line 276


os.system ("scite -open:fichier.txt")

File: chapn_tools.tex, line 282


import subprocess
args = ["scite.exe", "-open:fichier.txt"]
proc = subprocess.Popen(args)
retcode = proc.wait()            # on attend la fin de l'exécution
if retcode!=0:
    # ici, traiter les erreurs

File: chapn_tools.tex, line 293


import subprocess
args = ["scite.exe", "-open:fichier.txt", ">>output.txt"]
proc = subprocess.Popen(args)

File: chapn_tools.tex, line 457


cd "répertoire d'installation de SVN\bin"
svnadmin create c:\svnrepository

File: chapn_tools.tex, line 472


ping 127.0.0.1

File: chapn_tools.tex, line 480


http://127.0.0.1:81/

File: chapn_tools.tex, line 517


c:\python25\python c:\python25\lib\pydoc.py random
c:\python25\python c:\python25\lib\pydoc.py .\mon_programme.py

File: chapn_tools.tex, line 522


import os
os.system (r"c:\python25\python c:\python25\lib\pydoc.py .\mon_programme.py")

génération automatique de l'aide

# coding: latin-1
"""genhelp.py : génération automatique de l'aide dans le répertoire d'exécution"""
import os
import sys
python_path = r"c:\python25\python"          # constante
pydoc_path  = r"c:\python25\lib\pydoc.py"    # constante

class ClassExemple :
    """classe vide, exemple d'aide"""
    def __init__ (self) :
        """constructeur"""
        pass
    def methode (self) :
        """unique méthode"""
        return 1

def generate_help_file (f, pyt = python_path, pyd = pydoc_path) :
    """génère l'aide associée à un fichier ou un module
    le nom de ce fichier peut apparaître sans son extension ou alors
    précédé de .\\ ou avec son chemin complet
    pyt est le répertoire de python
    pyd est l'emplacement de pydoc.py"""
    s = "call " + pyt + " " + pyd + " -w " + f
    os.system (s)
    
def replace_firstpage (file, page) :
    """la génération de l'aide chm s'arrête avant la fin si le lien <a href=".">index</a>
    est laissé dans les pages générées par pydoc, on le remplace par une page
    comme index.html"""
    f = open (file, "r")
    li = f.readlines ()
    f.close ()
    f = open (file, "w")
    for l in li :
        f.write (l.replace ("""<a href=".">index</a>""", page))
    f.close ()
    
def genhelp (files, pyt = python_path, pyd = pydoc_path, firstpage = "index.html") :
    """génère l'aide associée à des fichiers ou des modules,
    un fichier se distingue d'un module par son extension,
    retourne la liste des fichiers générés,
    pyt est le répertoire de python
    pyd est l'emplacement de pydoc.py
    firstpage voir fonction replace_firstpage"""
    res = []
    for f in files :
        print "génération de l'aide de ", f
        if ".py" in f : # fichier
            generate_help_file (f, pyt, pyd)
            g    = f.split ("\\")  # ne garde que le nom de fichier et non son chemin
            page = g [ len (g)-1].replace (".py", ".html")
        else :          # module
            generate_help_file (f, pyt, pyd)
            page = f + ".html"
        res.append (page)
        replace_firstpage (page, firstpage)
    return res

if __name__ == "__main__" :
    import sys
    import os

    files = [".\\genchm.py", ".\\genhelp.py", "os", "sys"]
    res   = genhelp (files)
    print res  # ['genchm.html', 'genhelp.html', 'os.html', 'sys.html']

exemple de fichier \textit{hpp

[OPTIONS]
Compatibility=1.1 
Full-text search=Yes
Contents file=help.hhc    # fichier table des matières
Default Window=main
Default topic=index.html  # page par défaut, première page à apparaître
Index file=help.hhk       # fichier index
Language=0x40C French
Binary TOC=YES
Create CHI file=No
Title="GenHelp"           # titre

[WINDOWS]                 # définition de la page principale, elle reprend des éléments cités ci-dessus
main="GenHelp", "help.hhc", "help.hhk" , "index.html", "index.html",,,,,0x23520,,0x387e,,,,,,,,0

[FILES]                   # ici commence la liste des fichiers à insérer dans le projet
genchm.html
genhelp.html
os.html
sys.html
index.html

File: chapn_tools.tex, line 568


<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML><HEAD></HEAD><BODY>

File: chapn_tools.tex, line 572


</BODY></HTML>

File: chapn_tools.tex, line 576


<LI><OBJECT type="text/sitemap">
<param name="Name" value="intitule">
<param name="Local" value="page HTML correspondante">
<param name="ImageNumber" value="11"></OBJECT>

exemple de fichier \textit{hhk

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML><HEAD></HEAD><BODY>
<OBJECT type="text/site properties">param name="GenHelp" value="right">OBJECT>
<UL>
    <LI><OBJECT type="text/sitemap">
        <param name="Name" value="GenHelp">
        <param name="Local" value="index.html">
        <param name="ImageNumber" value="11"></OBJECT>
    <UL>
        <LI><OBJECT type="text/sitemap">
            <param name="Name" value="genchm">
            <param name="Local" value="genchm.html">
            <param name="ImageNumber" value="11"></OBJECT>
        <LI><OBJECT type="text/sitemap">
            <param name="Name" value="genhelp">
            <param name="Local" value="genhelp.html">
            <param name="ImageNumber" value="11"></OBJECT>
        <LI><OBJECT type="text/sitemap">
            <param name="Name" value="os">
            <param name="Local" value="os.html">
            <param name="ImageNumber" value="11"></OBJECT>
        <LI><OBJECT type="text/sitemap">
            <param name="Name" value="sys">
            <param name="Local" value="sys.html">
            <param name="ImageNumber" value="11"></OBJECT>
        <LI><OBJECT type="text/sitemap">
            <param name="Name" value="index">
            <param name="Local" value="index.html">
            <param name="ImageNumber" value="11"></OBJECT>
    </UL>
</UL>
</BODY></HTML>

génération automatique d'un fichier \textit{chm

# coding: latin-1
"""genchm.py : génération automatique du fichier d'aide chm"""
import genhelp
import os
htmlworkshop_path = "\"c:\\Program Files\\HTML Help Workshop\\hhc.exe\""

def g (s) :
    """ajoute des guillements autour d'une chaîne de caractères"""
    return "\"" + s + "\""
    
def genhhp (files, premierepage, titre, \
            hhp = "help.hhp", hhc = "help.hhc", hhk = "help.hhk") :
    """génère le fichier hpp définissant le fichier d'aide chm,
    files est la liste des fichiers HTML
    premierepage est la page à afficher en premier
    titre est le titre de l'aide"""
    proj = """[OPTIONS]
Compatibility=1.1
Full-text search=Yes
Contents file=""" + hhc + """
Default Window=main
Default topic=""" + premierepage + """
Index file=""" + hhk + """
Language=0x40C French
Binary TOC=YES
Create CHI file=No
Title=""" + g (titre) + """

[WINDOWS]
main=""" + g (titre) + """, """ + g (hhc) + """, """ + g (hhk) + """ , """ + \
        g (premierepage) + """, """ + g (premierepage) + """,,,,,0x23520,,0x387e,,,,,,,,0

[FILES]
"""
    for f in files :
        proj += f + "\n"
        
    f = open (hhp, "w")
    f.write (proj)
    f.close ()
    
def gen_premierepage (files, titre, res = "index.html") :
    """génère la première page de l'aide au format HTML"""
    s = """<HTML><head><title>""" + titre + """</title></head><BODY>\n"""
    s += "<H1>" + titre + "</H1>\n"
    for f in files :
        s += "<A HREF=\"" + f + "\">" + f.replace (".html", "") + "</A><BR>\n"
    s += "</BODY></HTML>\n"
    
    f = open (res, "w")
    f.write (s)
    f.close ()
    
def genhh_input (entree, page, link = True) :
    """retourne la chaîne de caractères associée à une entrée de la table des matières"""
    res = """<LI><OBJECT type="text/sitemap"><param name="Name" value=\"""" + entree + """\">"""
    if link : res += """<param name="Local" value=\"""" + page + """\">"""
    res += """<param name="ImageNumber" value="11"></OBJECT>\n"""
    return res
    
def genhhc (files, premierepage, titre, hhc = "help.hhc") :
    """génère le fichier hhc, même paramètre que pour hhp"""
    res ="""<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML><HEAD></HEAD><BODY>
        <OBJECT type="text/site properties">
        <param name=""" + g (titre) + """ value="right">
        </OBJECT>
        <UL>"""
    res += genhh_input (titre, premierepage, False)
    res += "<UL>\n"
    res += genhh_input ("modules", premierepage, False)
    res += "<UL>\n"
    for f in files :
        res += genhh_input (f.replace (".html", ""), f)
    res += "</UL>\n"
    res += "</UL>\n"
    res += "</UL>\n"
    res += "</BODY></HTML>\n"
    
    f = open (hhc, "w")
    f.write (res)
    f.close ()

def genhhk (files, premierepage, titre, hhk = "help.hhk") :
    """génère le fichier hhk, même paramètre que pour hhp"""
    res ="""<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML><HEAD></HEAD><BODY>
        <OBJECT type="text/site properties">
        <param name=""" + g (titre) + """ value="right">
        </OBJECT>
        <UL>"""
    res += genhh_input (titre, premierepage)
    res += "<UL>\n"
    for f in files :
        res += genhh_input (f.replace (".html", ""), f)
    res += "</UL>\n"
    res += "</UL>\n"
    res += "</BODY></HTML>\n"
    
    f = open (hhk, "w")
    f.write (res)
    f.close ()

def genchm (files, titre, \
            hhp = "help.hhp", hhc = "help.hhc", hhk = "help.hhk") :
    """génère le fichier d'aide complet"""
    premierepage = "index.html"                     # génère la page de garde
    gen_premierepage (files, titre, premierepage)   
    files.append (premierepage) 
    genhhp (files, premierepage, titre)             # génère le fichier hhp
    genhhc (files, premierepage, titre)             # génère le fichier hhc
    genhhk (files, premierepage, titre)             # génère le fichier hhk
    os.system (htmlworkshop_path + " " + hhp)       # appelle HTML WorkShop en ligne de commande

if __name__ == "__main__" :
    files = [".\\genchm.py", ".\\genhelp.py", "os", "sys"]
    res   = genhelp.genhelp (files)
    print res  # ['genchm.html', 'genhelp.html', 'os.html', 'sys.html']   
    genchm (res, "GenHelp")

File: chapn_tools.tex, line 625


[Setup]                                    ; nom de la section 
AppName=HalPython                          ; nom de l'application à installer
AppVerName=HalPython 1.5.1162              ; numéro de version
AppPublisher=Xavier Dupré                  ; auteur
AppPublisherURL=http://www.xavierdupre.fr/ ; site web
AppSupportURL=http://www.xavierdupre.fr/   ; site web, support
AppUpdatesURL=http://www.xavierdupre.fr/   ; site web, mise à jour
DefaultDirName={pf}/HalPython              ; emplacement par défaut sur la machine utilisateur
                                           ; le code {pf} signife le répertoire \textit{Program Files}
DefaultGroupName=HalPython                 ; nom par défaut du sous menu dans 
                                           ;                            Démarrer / Tous les programmes
OutputDir=c:                               ; répertoire où sera écrit l'installateur
OutputBaseFilename=setup_HalPython_py25    ; nom de l'installateur ou setup
Compression=lzma                           ; type de compression, ne pas changer 
SolidCompression=yes                       ; type de compression, ne pas changer
VersionInfoVersion=1.0.0                   ; version, ne pas changer

File: chapn_tools.tex, line 648


[Files]
Source: "chemin_concepteur"; DestDir: "chemin_utilisateur"  ;
Source: "..\hal_dll.dll"; DestDir: "{app}\hal_python"       ; autre exemple

File: chapn_tools.tex, line 660


[Run]
Filename: "{win}\system32\msiexec.exe"; Parameters: "/i ""{app}\python-2.5.2.msi"" /qr ALLUSERS=1"; 
Filename: "{cmd}"; Parameters: "/c del python-2.5.2.msi"; WorkingDir: "{app}";

File: chapn_tools.tex, line 671


[Icons]
; liens vers diverses applications
Name: "{group}\PyScripter"; Filename: "{app}\PyScripter.exe"; WorkingDir: "{app}"
Name: "{group}\PyScripter Help"; Filename: "{app}\pyscripter.chm"; WorkingDir: "{app}"
Name: "{group}\Help"; Filename: "{app}\hal_python.chm"; WorkingDir: "{app}"
Name: "{group}\smallest sample with PyScripter"; Filename: "{app}\small_sample.bat"; WorkingDir: "{app}"

; hyperlien ou url vers un site
Name: "{group}\Website"; Filename: "{app}\hal_python.url"

; lien vers le désinstalleur créé automatiquement par InnoSetup
Name: "{group}\uninstall"; Filename: "{uninstallexe}"; WorkingDir: "{app}"  

File: chapn_tools.tex, line 688


[InternetShortcut]
URL=http://www.xavierdupre.fr/hal_python/hal_python_help_html/index.html

File: chapn_tools.tex, line 695


[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; 
    Flags: checkedonce

File: chapn_tools.tex, line 705


[Registry]
Root: HKLM; Subkey: "SOFTWARE\HalPython\InstallPath"; ValueType: string; ValueName: ""; 
      ValueData: "{app}"; Flags: uninsdeletekey
Root: HKLM; Subkey: "SOFTWARE\HalPython\Version"; ValueType: string; 
     ValueName: ""; ValueData: "1.5.1162"; Flags: uninsdeletekey

construction d'un installateur

; section non commentée
[Setup]
AppName=HalPython
AppVerName=HalPython 1.5.1162
AppPublisher=Xavier Dupré
AppPublisherURL=http://www.xavierdupre.fr/hal_python/hal_python_help_html/index.html
AppSupportURL=http://www.xavierdupre.fr/hal_python/hal_python_help_html/index.html
AppUpdatesURL=http://www.xavierdupre.fr/hal_python/hal_python_help_html/index.html
DefaultDirName={pf}/HalPython
DefaultGroupName=HalPython
OutputDir=D:\Dupre\_data\site\hal_python\executable
OutputBaseFilename=setup_HalPython_py25
Compression=lzma
SolidCompression=yes
VersionInfoVersion=1.0.0

[Code]

; cette fonction retourne le chemin d'installation de Python 2.5
; le résultat est vide si celui-ci n'a pas été installé
; le chemin est celui stocké dans la clé de registre 
;           HKLM\Software\Python\PythonCore\2.5\InstallPath
function GetPythonPath(Param: String): String;
begin
  Result := '';
  Result := ExpandConstant('{reg:HKLM\Software\Python\PythonCore\2.5\InstallPath,|}');
  if Result <> '' then
    Result := Result + '\pythonw.exe';
end;

; cette fonction retourne {win}\system32\msiexec.exe
; si Python 2.5 a été installé, vide sinon
function GetPythonPathExec(Param: String): String;
begin
  Result := GetPythonPath () ;
  if Result <> '' then
    Result := ExpandConstant('{win}\system32\msiexec.exe') ;
end;

; clés de registre
; mémorise le répertoire d'installation
; et le numéro de version
[Registry]
Root: HKLM; Subkey: "SOFTWARE\HalPython\InstallPath"; ValueType: string; ValueName: ""; 
        ValueData: "{app}"; Flags: uninsdeletekey
Root: HKLM; Subkey: "SOFTWARE\HalPython\Version"; ValueType: string; ValueName: ""; 
        ValueData: "1.5.1162"; Flags: uninsdeletekey

; icône sur le bureau
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; 
     Flags: checkedonce

; fichiers
[Files]
; le module en question
Source: "..\hal_dll.dll"; DestDir: "{app}\hal_python";
Source: "..\hal_dll_ext.dll"; DestDir: "{app}\hal_python";
Source: "..\hal_dll_model.dll"; DestDir: "{app}\hal_python";
Source: "..\hal_python.dll"; DestDir: "{app}\hal_python";
Source: "..\wxwindows_old.dll"; DestDir: "{app}\hal_python";
Source: "..\boost_python.dll"; DestDir: "{app}\hal_python";
Source: "..\_graphviz_draw.exe"; DestDir: "{app}\hal_python";
Source: "..\_hal_script.exe"; DestDir: "{app}\hal_python";
Source: "..\hal_python.py"; DestDir: "{app}\hal_python";
Source: "..\install\__init__.py"; DestDir: "{app}\hal_python";
Source: "..\install\setup.py"; DestDir: "{app}";
Source: "..\_test\temp\hal_python.chm"; DestDir: "{app}";

; les fichiers annexes
Source: "hal_python.url"; DestDir: "{app}";    URL de l'application
Source: "pyscripter.chm"; DestDir: "{app}";    aide de l'éditeur PyScripter
Source: "PyScripter.exe"; DestDir: "{app}";    éditeur PyScripter
Source: "python-2.5.2.msi"; DestDir: "{app}";  installateur Python 2.5
Source: "sample.bat"; DestDir: "{app}";        fichier de commande
Source: "sample.py"; DestDir: "{app}";         exemple de programme

; création des icônes
[Icons]
Name: "{group}\PyScripter"; Filename: "{app}\PyScripter.exe"; WorkingDir: "{app}"
Name: "{group}\PyScripter Help"; Filename: "{app}\pyscripter.chm"; WorkingDir: "{app}"
Name: "{group}\Help"; Filename: "{app}\hal_python.chm"; WorkingDir: "{app}"
Name: "{group}\smallest sample with PyScripter"; Filename: "{app}\small_sample.bat"; WorkingDir: "{app}"
Name: "{group}\Website"; Filename: "{app}\hal_python.url"
Name: "{group}\uninstall"; Filename: "{uninstallexe}"; WorkingDir: "{app}"

[Run]
; installe Python 2.5 si GetPythonPathExec retourne un résultat non vide
; passe à l'instruction suivante sinon
Filename: "{code:GetPythonPathExec}"; Parameters: "/i ""{app}\python-2.5.2.msi"" /qr ALLUSERS=1"; 
          StatusMsg: "Installing Python 2.5..."; Flags: skipifdoesntexist
          
; installe le module  si GetPythonPath retourne un résultat non vide
; passe à l'instruction suivante sinon
; exécute en fait l'insttruction python setup.py install
Filename: "{code:GetPythonPath}"; Parameters:"setup.py install"; WorkingDir: "{app}"; 
          StatusMsg: "Installing HalPython for Python 2.5..."

; supprime l'installation de Python 2.5
Filename: "{cmd}"; Parameters: "/c del python-2.5.2.msi"; WorkingDir: "{app}";

File: chapn_tools.tex, line 730


PyScripter.exe sample.py

construction d'un installateur de mise à jour

; section non commentée
[Setup]
AppName=HalPython
AppVerName=HalPython 1.5.1162
AppPublisher=Xavier Dupré
AppPublisherURL=http://www.xavierdupre.fr/hal_python/hal_python_help_html/index.html
AppSupportURL=http://www.xavierdupre.fr/hal_python/hal_python_help_html/index.html
AppUpdatesURL=http://www.xavierdupre.fr/hal_python/hal_python_help_html/index.html
DefaultDirName={pf}/HalPython
DefaultGroupName=HalPython
OutputDir=D:\Dupre\_data\site\hal_python\executable
OutputBaseFilename=setup_HalPython_update_py25
Compression=lzma
SolidCompression=yes
VersionInfoVersion=1.0.0

[Code]
function GetPythonPath(Param: String): String;
begin
  Result := '';
  Result := ExpandConstant('{reg:HKLM\Software\Python\PythonCore\2.5\InstallPath,|}');
  if Result <> '' then
    Result := Result + '\pythonw.exe';
end;

function GetHalPythonPath(Param: String): String;
begin
  Result := '';
  Result := ExpandConstant ('{reg:HKLM\Software\HalPython\InstallPath,|}') ;
end;

function InitializeSetup(): Boolean;
begin
  Result := True ;
  MsgBox (GetPythonPath (''), mbConfirmation, MB_OK) ;
  MsgBox (GetHalPythonPath (''), mbConfirmation, MB_OK) ;
  if GetPythonPath ('') = '' then begin
    MsgBox('Python 2.5 has not been installed. You should download 
            the complete Setup with Python 2.5 included instead of updating.', mbError, MB_OK) ;
    Result := False ;
  end else if GetHalPythonPath ('') = '' then begin
    MsgBox('HalPython for Python 2.5 has not been installed. 
            You should download the complete Setup with Python 2.5 included instead of updating.', 
            mbError, MB_OK) ;
    Result := False ;
  end
end;

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; 
      Flags: checkedonce

[Files]
Source: "..\hal_dll.dll"; DestDir: "{app}\hal_python";
Source: "..\hal_dll_ext.dll"; DestDir: "{app}\hal_python";
Source: "..\hal_dll_model.dll"; DestDir: "{app}\hal_python";
Source: "..\hal_python.dll"; DestDir: "{app}\hal_python";
Source: "..\wxwindows_old.dll"; DestDir: "{app}\hal_python";
Source: "..\boost_python.dll"; DestDir: "{app}\hal_python";
Source: "..\_graphviz_draw.exe"; DestDir: "{app}\hal_python";
Source: "..\_hal_script.exe"; DestDir: "{app}\hal_python";
Source: "..\hal_python.py"; DestDir: "{app}\hal_python";
Source: "..\install\__init__.py"; DestDir: "{app}\hal_python";
Source: "..\install\setup.py"; DestDir: "{app}";
Source: "hal_python.url"; DestDir: "{app}";
Source: "small_sample.bat"; DestDir: "{app}";
Source: "sample.py"; DestDir: "{app}";
Source: "..\_test\temp\hal_python.chm"; DestDir: "{app}";

[Registry]
Root: HKLM; Subkey: "SOFTWARE\HalPython\InstallPath"; ValueType: string; ValueName: ""; 
      ValueData: "{app}"; Flags: uninsdeletekey
Root: HKLM; Subkey: "SOFTWARE\HalPython\Version"; ValueType: string; ValueName: ""; 
      ValueData: "1.5.1162"; Flags: uninsdeletekey

[Icons]
Name: "{group}\PyScripter"; Filename: "{app}\PyScripter.exe"; WorkingDir: "{app}"
Name: "{group}\PyScripter Help"; Filename: "{app}\pyscripter.chm"; WorkingDir: "{app}"
Name: "{group}\Help"; Filename: "{app}\hal_python.chm"; WorkingDir: "{app}"
Name: "{group}\smallest sample with PyScripter"; Filename: "{app}\small_sample.bat"; WorkingDir: "{app}"
Name: "{group}\Website"; Filename: "{app}\hal_python.url"
Name: "{group}\uninstall"; Filename: "{uninstallexe}"; WorkingDir: "{app}"

[Run]
Filename: "{code:GetPythonPath}"; Parameters:"setup.py install"; WorkingDir: "{app}"; 
     StatusMsg: "Installing HalPython for Python 2.5..."

File: chapn_tools.tex, line 747


[Code]
function GetLnkSciTE(Param:String): String;
begin
    Result := CreateShellLink(ExpandConstant('{app}\SciTE sample.lnk'), 
                              'Opens SciTE with a sample', 
                              ExpandConstant('{app}\wscite\scite.exe'), 
                              ExpandConstant('"{app}\sample.py"'), 
                              ExpandConstant('{app}'),
                              '', 
                              0, 
                              SW_SHOWNORMAL);
end;

[Icons]
Name: "{group}\smallest sample with SciTE"; Filename: "{code:GetLnkSciTE}"; WorkingDir: "{app}"

File: chapn_tools.tex, line 769


def replace_string (file, s1, s2) :
    f = open (file, "r")
    li = f.readlines ()
    f.close ()
    f = open (file, "w")
    for l in li :
        s = l.replace (s1, s2)
        f.write (s)
    f.close ()

if __name__ == "__main__" :
    import sys
    file = sys.argv [1]  # fichier à modifier
    s1   = sys.argv [2]  # chaîne à remplacer
    s2   = sys.argv [3]  # nouvelle chaîne
    replace_string (file, s1, s2)

File: chapn_tools.tex, line 790

    
[Code]
; retourne le chemin du programme pythonw.exe
function GetPythonPathW(Param: String): String;
begin
  Result := '';
  Result := ExpandConstant('{reg:HKLM\Software\Python\PythonCore\2.5\InstallPath,|}');
  if Result <> '' then
    Result := Result + '\pythonw';
end;

; construit les paramètres de la ligne de commande
; "c:\Program Files\HalPython\replace_conf.py" "=pythonw" "=c:\python25\pythonw"
function GetReplaceConf(Param:String):String;
begin
    Result := ExpandConstant ('"{app}\replace_conf.py"')
    Result := Result + ' ' + ExpandConstant ('"{app}\wscite\python.properties"')
    Result := Result + ' "=pythonw"'
    Result := Result + ' "=' + GetPythonPathW ('') + '"' ;
end;

[Run]
; exécution de la ligne de commande
Filename: "{code:GetPythonPath}"; Parameters:"{code:GetReplaceConf}"; WorkingDir: "{app}"; 

File: chapn_tools.tex, line 818

 
c:\python25\pythonw "c:\Program Files\HalPython\replace_conf.py" "=pythonw" "=c:\python25\pythonw"

File: chapn_tools.tex, line 855


C:
cd c:\TEMP\moin-1.6.3
C:\Python25\python setup.py install --record=install.log

File: chapn_tools.tex, line 864


cd C:\
md Moin
md Moin\mywiki
md Moin\mywiki\data
md Moin\mywiki\underlay
cd c:\Python25\share\moin
xcopy data       C:\Moin\mywiki\data /E
xcopy underlay   C:\Moin\mywiki\underlay /E
copy  config\*.* C:\Moin\mywiki\*.*
copy  server\*.* C:\Moin\mywiki\*.*

File: chapn_tools.tex, line 892


#!/usr/env/bin python

File: chapn_tools.tex, line 897


#!c:/Python25/python.exe

File: chapn_tools.tex, line 912


data_dir = r'C:\Moin\mywiki\data'
data_underlay_dir = r'C:\Moin\mywiki\underlay'

File: chapn_tools.tex, line 919


actions_excluded = ['DeletePage', 'RenamePage', ]

File: chapn_tools.tex, line 925


superuser = [u"admin", ]

File: chapn_tools.tex, line 931


acl_rights_before = u"admin:read,write,delete,revert,admin"

File: chapn_tools.tex, line 940


sitename = u'NomSite'
page_front_page = u"FirstPage"

File: chapn_tools.tex, line 948


language_default = 'fr'

File: chapn_tools.tex, line 986


acl_rights_default = u"dupre:read,write,delete,revert,admin All:read"            

File: chapn_tools.tex, line 1008


theme_default = 'modern'

File: chapn_tools.tex, line 1040

            
<<TableOfContents(2)>>

= Titre 1 =

http://www.xavierdupre.fr/mywiki/XavierDupre

== Titre 1 niveau 2 ==
= Titre 2 =
  
Affichage d'une liste :
  * élément 1
  * élément 2
  * élement 3 : sous liste
     * sous élément 1
     * sous élément 2
  * dernier élément de la première liste

''italique''    '''gras''' __souligné__

une ligne

----            

File: chapn_tools.tex, line 1079


http://www.xavierdupre.fr/mywiki/XavierDupre
[[http://www.xavierdupre.fr/mywiki/XavierDupre|wiki de Xavier Dupré]]

File: chapn_tools.tex, line 1095


#acl dupre:read,write

File: chapn_tools.tex, line 1109


<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/python_cgi">
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Allow from all
</Directory>

Alias /pycgih "C:/Program Files/Apache Software Foundation/Apache2.2/python_cgi"   
ScriptAlias /pycgi "C:/Program Files/Apache Software Foundation/Apache2.2/python_cgi"   

File: chapn_tools.tex, line 1124


#!c:/Python25/python.exe
# ligne 1 : emplacement de python (obligatoire)
# ligne 2 : la page ne contiendra que du texte
print "Content-Type: text/plain\n\n"
# premier message au navigateur
print "premier message\n"

File: chapn_tools.tex, line 1135


<html><body>
<h1> Lien vers un script CGI écrit en Python </h1>
<a href="/pycgi/hello.cgi">hello.cgi</a>
</body></html>

File: chapn_tools.tex, line 1144


http://localhost/pycgih/index.html

File: chapn_tools.tex, line 1159


print "Content-Type: text/html\n\n"

File: chapn_tools.tex, line 1166


#!c:/Python25/python.exe
# coding: cp1252
print "Content-Type: text/html\n\n"
# premier message au navigateur,
# les passages à la ligne \n sont sans effet à l'affichage
print "<html><body>\n"
print "<b>premier message en gras</b>\n"
print "</body></html>"

File: chapn_tools.tex, line 1187


#!c:/Python25/python.exe
# coding: cp1252
print "Content-Type: text/html\n\n"
print "<html><body>\n"
try:
    print "<b>premier message en gras</b>\n"
    print "<br>déclenchement d'une erreur (instruction inconnue)<br>"
    stop
except:
    import sys
    import traceback
    print "<pre>"
    traceback.print_exc(file=sys.stdout)
    print "</pre>"
print "</body></html>"

File: chapn_tools.tex, line 1207


Traceback (most recent call last):
  File "C:/Program Files/Apache Software Foundation/Apache2.2/python_cgi/hello4.cgi", line 8, in 
    stop
NameError: name 'stop' is not defined

File: chapn_tools.tex, line 1221


<balise>  ....  </balise>

File: chapn_tools.tex, line 1228


<html>
<head>
.... entête de la page, n'est pas affiché, il est possible d'y définir
.... des feuilles de styles pour un affichage amélioré
.... ou la définition de nouvelles balises
.... la ligne 
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
.... permet de définir un jeu de caractères incluant les accents français
</head>
<body>
.... contenu de la page
</body>
</html>

File: chapn_tools.tex, line 1300


http://URL?param1=valeur1¶m2=valeur2&...

File: chapn_tools.tex, line 1307


#!c:/Python25/python.exe
# coding: cp1252
print "Content-Type: text/html\n\n"
print "<html><body>\n"
import cgi
par = cgi.FieldStorage()
if len (par) == 0 :
    print "<b> aucun paramètre à cette page </b>"
else :
    print "<b>liste des paramètres </b><br>"
    print """<table border="1">"""
    for p in par :
        print "<tr>"
        name  = str (p)
        value = par.getvalue (name)
        print "<td>", name, "</td><td>", value, "</td>"
        print "</tr>"
    print "</table>"
print "</body></html>"

File: chapn_tools.tex, line 1332


http://localhost/pycgi/pyform.cgi

File: chapn_tools.tex, line 1337


http://localhost/pycgi/pyform.cgi?nom=dupre&prenom=xavier

File: chapn_tools.tex, line 1351


#!c:/Python25/python.exe
# coding: cp1252
print "Content-Type: text/html\n\n"
print "<html><body>\n"
def print_form () :
    # création du formulaire avec deux champs nom et et prenom
    print """
    <FORM action="/pycgi/pyform.cgi" method=post>
    <P>
    <LABEL for="nom">Nom : </LABEL> <INPUT type="text" name="nom"><BR>
    <LABEL for="prenom">Prénom : </LABEL> <INPUT type="text" name="prenom"><BR>
    <INPUT type=submit value="Envoyer"> <INPUT type=reset value="Annuler">
    </P>
    </FORM>
    """
    
import cgi
par = cgi.FieldStorage ()
if len (par) == 0 :
    # s'il n'y a aucun paramètre, on affiche le formulaire
    print_form ()
else :
    # sinon, cela signifie que le formulaire a rappelé le script CGI
    # avec des paramètres et le traitement suit une direction différente
    # ici, cela consiste à afficher les informations reçues en gras
    nom = par.getvalue ("nom")
    prenom = par.getvalue ("prenom")
    print "Votre nom est <b>", nom, "</b> et votre prénom <b>", prenom, "</b>"
print "</html></body>\n"

File: chapn_tools.tex, line 1423


SELECT codepays
FROM PAYS 
WHERE pays = 'France'

File: chapn_tools.tex, line 1431


SELECT num,nom,prenom
FROM ELEVE
WHERE codepays IN ( 
                    SELECT codepays
                    FROM PAYS 
                    WHERE pays = 'France'
                  )

File: chapn_tools.tex, line 1476


SELECT nom,prenom,AVG(note) FROM ELEVE,NOTE
WHERE num = nume and 
      numm IN ( SELECT num FROM MATIERES WHERE matiere = 'français' ) 
GROUP BY nume

File: chapn_tools.tex, line 1490


CREATE TABLE ELEVE (
     num integer primary key,
     nom varchar (30),
     prenom varchar (30),
     date date,
     adresse varchar (100),
     codepays integer,
     classe integer)

création d'une table avec \codesindex{sqlite3

import sqlite3 as SQL
cx = SQL.connect("madatabase.db3")
cur = cx.cursor()

cur.execute ("""
CREATE TABLE ELEVE (
     num integer primary key,
     nom varchar (30),
     prenom varchar (30),
     date date,
     adresse varchar (100),
     codepays integer,
     classe integer)
""")

File: chapn_tools.tex, line 1509


cur.execute ("CREATE TABLE NOTE (nume integer, numm integer, note double)")
cur.execute ("CREATE TABLE MATIERES (num integer, matiere varchar (30))")
cur.execute ("CREATE TABLE PAYS (codepays integer, pays varchar (30))")

insertion de valeurs dans une table \codesindex{sqlite3

import sqlite3 as SQL
cx = SQL.connect("madatabase.db3")
cur = cx.cursor()

cur.execute ("""
CREATE TABLE ELEVE (
     num integer primary key,
     nom varchar (30),
     prenom varchar (30),
     date date,
     adresse varchar (100),
     codepays integer,
     classe integer)
""")

File: chapn_tools.tex, line 1520


import sqlite3 as SQL
cx = SQL.connect("madatabase.db3")
cur = cx.cursor()
cur.execute("select * from ELEVE")
for row in cur.fetchall(): print row

File: chapn_tools.tex, line 1529


(1, u'dupre', u'xavier', u'11/08/1975', u'---- paris', 33, 19)
(2, u'dupre', u'gilles', u'24/12/1946', u'---- charleville', 33, 56)

File: chapn_tools.tex, line 1537


cur.execute ("INSERT INTO PAYS (codepays, pays) VALUES (33, 'France')")
cur.execute ("INSERT INTO PAYS (codepays, pays) VALUES (44, 'Royaume-Uni')")
cur.execute ("INSERT INTO MATIERES (matiere, num) VALUES ('français', 1)")
cur.execute ("INSERT INTO MATIERES (matiere, num) VALUES ('mathématiques', 2)")
cx.commit ()

File: chapn_tools.tex, line 1547


note = [(1, 1, 12), (1, 1, 14), (1, 2, 16), (1, 2, 8), (1, 2, 12), \
        (2, 1, 8),  (2, 1, 9),  (2, 2, 11), (2, 2, 8), (2, 2, 12)]
for n in note :
    req = "INSERT INTO NOTE (nume,numm,note) VALUES " + str (n)
	  cur.execute (req)
cx.commit ()

File: chapn_tools.tex, line 1558


req = """
SELECT nom,prenom,AVG(note) FROM ELEVE,NOTE
WHERE num = nume and 
      numm IN ( SELECT num FROM MATIERES WHERE matiere = 'français' ) 
GROUP BY nume
"""
cur.execute (req)
for row in cur.fetchall(): print row

File: chapn_tools.tex, line 1570


(u'dupre', u'xavier', 13.0)
(u'dupre', u'gilles', 8.5)

File: chapn_tools.tex, line 1577


req = """
SELECT nom,prenom,AVG(note) FROM ELEVE,NOTE
WHERE num = nume and 
      numm IN ( SELECT num FROM MATIERES WHERE matiere = 'français' ) 
GROUP BY nume
HAVING AVG(note) >= 10
"""
cur.execute (req)
for row in cur.fetchall(): print row

File: chapn_tools.tex, line 1634


CREATE DATABASE datatest ;

connexion ODBC, création d'une table

import odbc
cx = odbc.odbc("mysqlperso")
cur = cx.cursor()

cur.execute ("""
CREATE TABLE ELEVE (
     num integer primary key,
     nom varchar (30),
     prenom varchar (30),
     date date,
     adresse varchar (100),
     codepays integer,
     classe integer)
""")

connexion ODBC, ajout de données

import odbc
cx = odbc.odbc("mysqlperso")
cur = cx.cursor()

cur.execute ("""INSERT INTO ELEVE (num, nom, prenom, date, adresse, codepays, classe)
                VALUES (1, 'dupre', 'xavier', '1975-08-11', '---- paris', 33, 19) ;""")
cur.execute ("""INSERT INTO ELEVE (num, nom, prenom, date, adresse, codepays, classe)
                VALUES (2, 'dupre', 'gilles', '1946-12-24', '---- charleville', 33, 56) ;""")
cx.commit ()

File: chapn_tools.tex, line 1709


import odbc 
cx = odbc.odbc("mysqlperso")
cur = cx.cursor()
cur.execute ("SELECT * from ELEVE") 
for row in cur.fetchall () :
    print row

File: chapn_tools.tex, line 1721


print [ str (r) for r in row ]

File: chapn_tools.tex, line 1737


import odbc
cx = odbc.odbc("odbc_sql_server")

File: chapn_tools.tex, line 1744


dbi.operation-error: [Microsoft][ODBC SQL Server Driver][SQL Server]Login failed for user ''. 
The user is not associated with a trusted SQL Server connection. in LOGIN

File: chapn_tools.tex, line 1751


import odbc
cx = odbc.odbc("odbc_sql_server/login/password")

File: chapn_tools.tex, line 1757


cx = odbc.odbc("DSN=odbc_sql_server;UID=login;PWD=password")

File: chapn_tools.tex, line 1766


cd c:\Program Files\Apache Software Foundation\Apache2.2\bin
httpd -k stop
httpd

File: chapn_tools.tex, line 1840


import odbc 
cx = odbc.odbc("mysqlperso")

cur = cx.cursor()
cur.execute ("SELECT * from ELEVE") 
for row in cur.fetchall () :
    print row
cur.close ()


File: chapn_tools.tex, line 1855


import MySQLdb
cx  = MySQLdb.connect('localhost','root', \
        'admin', 'datatest')
cur = cx.cursor()
cur.execute ("select * from ELEVE" )
for row in cur.fetchall() :
    print row
cur.close()
cx.close() 

File: chapn_tools.tex, line 1874


import win32com.client
connexion = win32com.client.gencache.EnsureDispatch('ADODB.Connection')
connexion.Open("Provider='SQLOLEDB';Data Source='localhost';Initial Catalog='datatest';User ID='root';Password='admin';")
recordset = connexion.Execute('select * from client')[0]
while not recordset.EOF:
    for i in recordset.Fields : print i,
    print "<br>\n"
    recordset.MoveNext()
connexion.Close()      

extraction du texte d'un fichier \textit{pdf

from pdftools.pdffile import PDFDocument
from pdftools.pdftext import Text

def contents_to_text (contents):
    for item in contents:
        if isinstance (item, type ([])):
            for i in contents_to_text (item):
                yield i
        elif isinstance (item, Text):
            yield item.text

doc = PDFDocument ("declaration.pdf")
n_pages = doc.count_pages ()
text = []

for n_page in range (1, (n_pages+1)):
    print "Page", n_page
    page = doc.read_page (n_page)
    contents = page.read_contents ().contents
    text.extend (contents_to_text (contents))

print "".join (text)

f = open ("ok.txt", "w")
f.write ("".join (text))
f.close ()

graphiques avec GNUPlot

# coding: latin-1

import sys
import os

default_path     = r"C:\Program Files\gp423win32\gnuplot\bin\pgnuplot.exe"
default_temp_dir = "tempgnuplot"
imagenumber      = 0

def execute_script_gnuplot (scr) :
    global default_temp_dir
    global imagenumber
    global default_path

    if not os.path.exists (default_temp_dir) : os.mkdir (default_temp_dir)

    # avant
    scr          = "set term png\n" + scr
    image        = default_temp_dir + ("/image_%05d.png" % imagenumber)
    imagenumber += 1
    scr          = "set out \"" + image + "\"\n" + scr

    # après
    scr += "show out\n"
    scr += "exit\n"

    name = default_temp_dir + "/gnuscript.txt"
    f    = open (name, "w")
    f.write (scr)
    f.close ()

    line = default_path + " " + name
    os.system (line)

    return image

def build_script_gnuplot (series, seriesname, title = None, \
                     xlabel = None, ylabel = None, histo = False) :
    global default_temp_dir
    global default_path

    if not os.path.exists (default_temp_dir) : os.mkdir (default_temp_dir)
    scr = ""

    if xlabel != None : scr += "set xlabel \"" + xlabel + "\"\n"
    if ylabel != None : scr += "set ylabel \"" + ylabel + "\"\n"
    if title  != None : scr += "set title \"" + title + "\"\n"

    scr += "set grid\n"
    if histo : scr += "set style data histograms\n"
    else : scr += "set style data lines\n"
    scr += "plot "

    id = 0
    for s,lab in zip (series, seriesname) :
        name = default_temp_dir + "/series%d.txt" % (id)
        id  += 1
        f    = open (name, "w")
        for l in s :
            if histo : f.write ("%f\n" % (l [1]))
            else : f.write ("%f\t%f\n" % (l [0], l [1]))
        f.close ()
        scr += "\"" + name + "\" title \"" + lab + "\", "
    scr = scr [:len (scr)-2]
    scr += "\n"

    return execute_script_gnuplot (scr)


if __name__ == "__main__" :
    print "chemin pour gnuplot ", default_path

    series = [ [], [] ]
    for i in range (0, 100) :
        x = float (i) / 100
        y = x ** 0.5
        z = 1.0 - y
        series [0].append ( (x,y) )
        series [1].append ( (x,z) )

    image = build_script_gnuplot (series, ["serie 1", "serie 2"], \
                        xlabel="abscisses", ylabel="ordonnées", histo = False)
    print "image ", image
    image = build_script_gnuplot (series, ["serie 1", "serie 2"], \
                        xlabel="abscisses", ylabel="ordonnées", histo = True)
    print "image ", image

graphiques avec MatPlotLib

#coding:latin-1
def GraphOHLC (title, dates, ohlc, file, size = (800,400), t1 = 0, t2 = -1) :
    """dessine une série financière avec matplotlib
    - title est une titre
    - dates est une liste de date
    - ohlc est une liste de dictionnaire avec les clés 
                      ("Open", "High", "Low", "Close", "Volume")
    - file est un nom de fichier, le graphe y sera sauvegardé
    - size est la taille désirée pour le graphique
    - t1 est l'indice de la première date du graphique
    - t2 est l'indice de la dernière date du graphique
    """
    
    # on coupe la série si besoin
    if t2 == -1 : t2 = len (dates)
    dates = dates [t1:t2]
    ohlc = ohlc [t1:t2]
    
    import pylab
    
    # on crée les labels pour les abscisses
    # sans afficher toutes les dates car elles deviennent illisibles sinon
    # on en affiche que 10
    ind  = pylab.arange (len (dates))
    lab  = ["" for i in ind]
    for i in range (0,len (dates),len(dates)/10) : lab [i] = dates [i]

    # on crée la figure
    fig  = pylab.figure (figsize=(size [0]/100, size [1]/100))
    ax   = fig.add_subplot(111)
    
    # la première série à tracer est celle des volumes sous forme d'histogramme
    for i in range (0, len (ohlc)) :
        oh = ohlc [i]
        
        # l'histogramme est vert si c'est un jour de hausse
        # rouge si c'est un jour de baisse
        if i == 0 : co = (0.5,0.5,0.5)
        elif ohlc [i]["Close"] > ohlc [i-1]["Close"] : co = (0.0,1.0,0.0)
        else : co = (1.0,0.0,0.0)
        if len (dates) > 300 : 
            pylab.plot ( [i, i], [0, oh ["Volume"]], "k", color = co)
        elif len (dates) > 100 : 
            pylab.plot ( [i, i], [0, oh ["Volume"]], "k", \
                                         linewidth = 2.0, color = co)
        else : 
            pylab.plot ( [i, i], [0, oh ["Volume"]], "k", \
                                          linewidth = 4.0, color = co)
        
    # on écrit la légende du volume
    v = [0.0 for i in ind]
    pylab.plot (ind, v, "c.")
    pylab.ylabel ("volume")
        
    # on construit un second axe au graphique pour la série des prix
    ymin, ymax = pylab.ylim()
    pylab.ylim (ymin, ymax*3)
    pylab.xticks (ind, lab, fontsize = "small", rotation = 13  )
    ax2 = pylab.twinx()
    
    # puis un dessine les prix sur le graphique selon le même schéma, 
    # la même série de points
    # (i-0.5, Open) (i,Open) (i,Low) (i,High) (i,Close) (i+0.5,Close)
    for i in range (0, len (dates)) :
        oh = ohlc [i]
        co = (0.0,0.0,1.0)
        pylab.plot ([i-0.5, i], [oh["Open"],  oh["Open"]],  "k", \
                                      linewidth = 1.0, color = co)
        pylab.plot ([i, i],     [oh["Low"],   oh["High"]],  "k", \
                                      linewidth = 1.0, color = co)
        pylab.plot ([i, i+0.5], [oh["Close"], oh["Close"]], "k", \
                                      linewidth = 1.0, color = co)

    # on termine par le titres, la légende du second axe et celles des abscisses
    pylab.title   (title)
    pylab.ylabel  ("euros")
    pylab.xticks  (ind, lab, fontsize = "small", rotation = 13)
    pylab.xlabel  ("dates")
    # il ne reste plus qu'à sauver la figure
    pylab.savefig (file, orientation='paysage')

File: chapn_tools.tex, line 1957


Listen 81

File: chapn_tools.tex, line 1972


LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

<Location /svn/>
    DAV svn
    SVNListParentPath on 
    SVNParentPath "c:/svnrepository/"
    SVNPathAuthz on
    #AuthzSVNAccessFile "C:/Program Files/Apache Software Foundation/Apache2.2/bin/apachesvnauth 
    AuthName "Subversion Repositories" 
    AuthType Basic
    AuthBasicProvider file
    AuthUserFile "C:/Program Files/Apache Software Foundation/Apache2.2/bin/apachesvnpasswd"
    require valid-user
</Location>

File: chapn_tools.tex, line 1992


cd C:\Program Files\Apache Software Foundation\Apache2.2\bin
htpasswd.exe -c apachesvnpasswd utilisateur

File: chapn_tools.tex, line 2012


ScriptAlias /mywiki "C:/Moin/mywiki/moin.cgi"    
Alias /moin_static163 "C:/Python25/share/moin/htdocs"

File: chapn_tools.tex, line 2019


<Directory "C:/Python25/share/moin/htdocs">
    Order deny,allow
    Allow from all
</Directory>
<Directory "C:/Moin/mywiki">
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Allow from all
</Directory>

File: chapn_tools.tex, line 2033


#!c:/python25/python.exe

File: chapn_tools.tex, line 2037


#!/usr/bin/python

File: chapn_tools.tex, line 2042


ScriptInterpreterSource registry
<Directory "C:/Python25">            # il faut également une section
    AllowOverride None               # comme celle-ci définie
    Options ExecCGI                  # pour le répertoire contenant
    Order allow,deny                 # le script CGI
    Allow from all                   #
</Directory>
AddType application/x-httpd-py .py
AddHandler cgi-script .py
Action application/x-httpd-py "C:/python25/python.exe"

File: chapn_tools.tex, line 2069


netstat -ao

File: chapn_tools.tex, line 2075


httpd -k uninstall -n ApacheSecond                  # on désinstalle le service s'il existait
httpd -f "new_conf.conf" -n ApacheSecond -k install # on installe à nouveau le service
httpd -n ApacheSecond -k start                      # on démarre Apache

File: chapn_tools.tex, line 2089


(OS 10048)Only one usage of each socket address (protocol/network address/port) is normally permitted.  : make_sock: could not bind to address 0.0.0.0:8084
no listening sockets available, shutting down
Unable to open logs

File: chapn_tools.tex, line 2106


<Directory "C:/Python25">
    AllowOverride None
    Options ExecCGI
    Order allow,deny
    Allow from all
</Directory>
<Directory "C:/_home/query-intent/projects/common_tools/cgi/">
    AllowOverride None
    Options FollowSymLinks ExecCGI
    Order allow,deny
    Allow from all
</Directory>

File: chapn_tools.tex, line 2123


<IfModule mime_module>
    TypesConfig conf/mime.types
    AddType application/x-httpd-py .py
    AddHandler cgi-script .py
</IfModule>
Action application/x-httpd-py "C:/python25/python.exe"

File: chapn_tools.tex, line 2134


ScriptAlias /py/ "C:/script_cgi_python/"

File: chapn_tools.tex, line 2140


header = """Content-type: text/html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>"""

footer = """</body></html>"""

print header
print "<b>Script CGI</b><br>\n"
print footer

File: chapn_tools.tex, line 2160


http://localhost:80/py/script.py

calcul d'une intégrale

# coding: cp1252
import math

n = 2000
a = -2.0
b = 3.0
h = (b-a)/n

sum = 0
for i in xrange (1,n):
    x = a + h * i
    sum += h * x * math.cos (x)

print "intégrale : ", sum

import scipy.integrate as integral            # on importe le module d'intégration
def fff(x): return x * math.cos (x)           # on définit la fonction à intégrer				
sum = integral.quad (fff, a,b, args=()) [0]   # on appelle la fonction d'intégration
print "intégrale avec scipy : ", sum          # on affiche le résultat

File: integrale.tex, line 47


import scipy.integrate as integral             # on importe le module d'intégration
def fff(x): return x * math.cos (x)            # on définit la fonction à intégrer				
sum = integral.quad (fff, a,b, args=()) [0]    # on appelle la fonction d'intégration
print "intégrale avec scipy : ", sum           # on affiche le résultat

File: integrale.tex, line 56


intégrale :  -1.96640795695
intégrale avec scipy :  -1.96908048953

File: tri.tex, line 13


x = [1,3,2,5,8,4,9,0,7,6] 
x.sort ()
print x

tri par sélection

# coding: cp1252
import random

def construit_suite(n):
    """construit une liste de n nombres entiers compris entre 0 et 99"""
    l = []
    for i in range(0,n):
        l.append (random.randint(0,100))
    return l

def tri_selection(l):
    """ tri une liste l, tri par sélection"""
    # première boucle, répétition des étapes A et B
    for i in range(0,len(l)):

        # recherche du maximum, on suppose pour commencer
        # qu'il est à la position 0
        pos = 0
        # boucle de l'étape A
        for j in range(1,len(l)-i):
            if l [pos] < l [j]: pos = j

        # échange de l'étape B
        # la position du maximum est conservé dans la variable pos
        # on fait l'échange avec l'élément à la position len(l)-i-1
        k       = len(l)-i-1
        ech     = l [k]
        l [k]   = l [pos]
        l [pos] = ech

l = construit_suite(8)          # création d'une suite aléatoirement
print "liste non triée :\t",l   # affichage
tri_selection (l)               # tri
print "liste triée     :\t",l   # affichage

tri fusion

# coding: cp1252
import random

def construit_suite(n):
    """construit une liste de n nombres entiers compris entre 0 et 99"""
    l = []
    for i in range(0,n):
        l.append (random.randint(0,100))
    return l

def fusion_liste (l1,l2):
    """fusionne deux listes l1 et l2 triées par ordre croissant
    de sorte que la liste résultante soit également triée"""
    i,j,k = 0,0,0
    fin   = len (l1) + len (l2)
    l = []
    while k < fin :
        if j >= len (l2) or (i < len (l1) and l1 [i] < l2 [j]) :
            l.append (l1 [i])
            k += 1
            i += 1
        else :
            l.append (l2 [j])
            k += 1
            j += 1
    return l

def tri_fusion(l):
    """ tri une liste l par fusion"""
    if len (l) <= 1 : return None # on élimine le cas simple
    n = 1
    while n < len (l) :
        for i in xrange (0, len (l), 2*n):
            a  = i
            m  = min (len (l), a + n)
            b  = min (len (l), a + 2 * n)
            if m < b:
                t        = fusion_liste (l [a:m], l [m:b])
                l [a:b] = t
        n *= 2
        
l = construit_suite(13)          # création d'une suite aléatoirement
print l [0:3]
print "liste non triée :\t",l    # affichage
tri_fusion (l)                   # tri
print "liste triée     :\t",l    # affichage

tri par insertion

# coding: cp1252
import random

def construit_suite(n):
    """construit une liste de n nombres entiers compris entre 0 et 99"""
    l = []
    for i in range(0,n):
        l.append (random.randint(0,100))
    return l

def recherche_dichotomique (l,x):
    """cherche l'élément x dans la liste l, la liste l est
    supposée être triée par ordre croissant"""
    a = 0
    b = len(l)-1
    while a <= b :
        m = (a+b) // 2
        r = cmp (x, l[m])
        if r == 0 : return m
        elif r == -1 : b = m-1
        else : a = m + 1
    return a

def tri_insertion(l):
    """ tri une liste l par insertion dichotomique, on suppose que l est non vide"""
    lt = []
    for x in l :
        if len (lt) == 0 : 
            lt.append (x)
            continue
        m = recherche_dichotomique (lt, x)
        lt.insert (m, x)
    l [0:len (l)] = lt


l = construit_suite(13)         # création d'une suite aléatoirement
print l [0:3]
print "liste non triée :\t",l   # affichage
tri_insertion (l)               # tri
print "liste triée     :\t",l   # affichage

tri d'entiers

# coding: cp1252
import random

def construit_suite(n):
    """construit une liste de n nombres entiers compris entre 0 et 99"""
    l = []
    for i in range(0,n):
        l.append (random.randint(0,10))
    return l

def tri_entiers(l):
    """ tri une liste l, les éléments à trier sont entiers"""
    # première boucle, minimum, maximum
    m = l [0]
    M = l [0]
    for k in range(1,len(l)):
        if l [k] < m : m = l [k]
        if l [k] > M : M = l [k]
    
    # calcul du nombre d'occurrences
    p = [0 for i in range (m,M+1) ]
    for i in range (0, len (l)) :
        p [ l [i] - m ] += 1
        
    # fonction de répartition
    P = [0 for i in range (m,M+1) ]
    P [0] = p [0]
    for k in range (1, len (p)) :
        P [k] = P [k-1] + p [k]
        
    # tri
    pos = 0
    for i in range (1, len (l)) :
        while P [pos] < i : pos += 1
        l [i-1] = pos + m
    l [len (l)-1] = M


l = construit_suite(8)          # création d'une suite aléatoirement
print "liste non triée :\t",l   # affichage
tri_entiers (l)                 # tri
print "liste triée     :\t",l   # affichage

File: chap2_precis.tex, line 26


MsgBox "première partie" & _
       "seconde partie\n" & _
       "troisième partie"

File: chap2_precis.tex, line 64


Dim a As Integer
Dim s As String
Dim v As Variant

File: chap2_precis.tex, line 81


' mois est un tableau de chaînes de caractères
' dont les indices vont de 0 à 12 inclus
Dim Mois(12) As String

' Matrice est un tableau à deux dimensions d'entiers
Dim Matrice(3, 4) As Integer

' Matrice2 est un tableau de réels à deux dimensions pour lesquels
' les indices désirés sont explicitement spécifiés
Dim Matrice2(1 To 5,  4 To 9,  3 To 5) As Double

' accès à un paramètre
Dim t(3 To 6) As Integer
t(3) = 4

File: chap2_precis.tex, line 105


3 + 4         ' vaut 7
31 Mod 5      ' vaut 1
2^4           ' vaut 16
"un" & "deux" ' vaut undeux

File: chap2_precis.tex, line 115


((3 < 4) And (5 < 6)) Or (2 > 1)

File: chap2_precis.tex, line 123


s = "première ligne" & vbCrLf & "seconde ligne"

File: chap2_precis.tex, line 140


Dim s As String
Dim a As Double
s = Str (3.14)
a = Val ("3.14")

File: chap2_precis.tex, line 155


Type Contacts
    Nom As String
    Prenom As String
    Age As Integer
End Type

Sub procedure ()
    Dim ct As Contacts
    ct.Nom = "Microsoft"
    ct.Prenom = "VBA"
    ct.Age = 10     ' environ
End Sub

File: chap2_precis.tex, line 174


Type Contacts
    Nom As String
    Prenom As String
    Age As Integer
End Type

Sub essai()
    Dim ct As Contacts
    With ct
        .Nom = "Microsoft"
        .Prenom = "VBA"
        .Age = 10
    End With
End Sub

File: chap2_precis.tex, line 212


Public nom As String

Sub essai()
    nom = "inconnu"
End Sub

File: chap2_precis.tex, line 222


Dim c As New ClassNom
c.nom = "eeee"
c.essai

File: chap2_precis.tex, line 231


Private Sub Class_initialize()
    ' code du constructeur
End Sub

Private Sub Class_Terminate()
    ' code du destructeur
End Sub

File: chap2_precis.tex, line 246


MsgBox "message"

File: chap2_precis.tex, line 260


Reponse = MsgBox ("Voulez-vous continuer ?", vbYesNo)

File: chap2_precis.tex, line 269


Dim Message As String
Message = InputBox("intitulé de la question", "nom de la boîte de dialogue", _
                                  "réponse par défaut")

File: chap2_precis.tex, line 286


If condition Then
    ' faire..
End If

File: chap2_precis.tex, line 294


If condition Then   ' faire

File: chap2_precis.tex, line 300


If condition Then
    ' faire..
Else
    ' sinon faire...
End If

File: chap2_precis.tex, line 310


If condition1 Then
    ' faire..
ElseIf condition2 Then
    ' faire...
Else
    ' sinon faire...
End If

File: chap2_precis.tex, line 325


Dim NiveauEau As Integer
Dim Mention As String
NiveauEau = 10
Select Case NiveauEau
    Case 0
        Mention = "sec"
    Case 1 To 5
        Mention = "presque sec"
    Case 6 To 10
        Mention = "normal"
    Case 11 To 15
        Mention = "trop d'eau"
    Case 16 To 19
        Mention = "inondations"
    Case Else
        Mention = "on déménage"
End Select

File: chap2_precis.tex, line 350


Dim s as Integer
Dim i as Integer ' déclarer la variable de la boucle
s = 0
For i = 1 To 10
    s = s + 1
Next i           ' passer au i suivant

File: chap2_precis.tex, line 361


Dim s as Integer
Dim i as Integer ' déclarer la variable de la boucle
s = 0
For i = 1 To 10 Step 2  ' i = 1 3 5 ... 9
    s = s + 1
Next i           ' passer au i suivant

File: chap2_precis.tex, line 375


Dim s as Integer
Dim i as Integer ' déclarer la variable de la boucle
s = 0
i = 1
While i <= 10 
    s = s + 1
    i = i + 1
Wend

File: chap2_precis.tex, line 391


Dim s as Integer
Dim i as Integer ' déclarer la variable de la boucle
s = 0
i = 1
Do While i <= 10 
    s = s + 1
    i = i + 1
Loop

File: chap2_precis.tex, line 406


Dim s as Integer
Dim i as Integer ' déclarer la variable de la boucle
s = 0
i = 1
Do 
    s = s + 1
    i = i + 1
Loop While i <= 10 

File: chap2_precis.tex, line 427


Sub exemple_procedure ()
   ' code de la procédure
End Sub

File: chap2_precis.tex, line 435


Sub exemple_procedure (ByVal param1 As Long)
   ' code de la procédure
End Sub
Sub main ()
    ' appel de la procédure
    exemple_procedure 3
End Sub

File: chap2_precis.tex, line 449


Function exemple_fonction () As Integer
   ' code de la procédure
   ...
   ' retourner le résultat
   exemple_fonction =
End Function

File: chap2_precis.tex, line 467


Sub proc ()
   Static i As Integer
End Sub

File: chap2_precis.tex, line 486


Function exemple_fonction (ByVal s As String, ByRef v As Variant) As Long
    ' ...
End Function

File: chap2_precis.tex, line 505


Dim nom_tres_tres_long As String
Dim s As String
Set s = nom_tres_tres_long
' par la suite, s et nom_tres_tres_long désignent la même variable

File: chap2_precis.tex, line 547


Sub proc ()
	On Error Goto erreur
	  '
	  ' code susceptible de produire une erreur
	  '
	Exit Sub
erreur:
	'
	' en cas d'erreur
	'	
End Sub

File: chap2_precis.tex, line 572


Dim intFile As Integer
Dim filename as String
Dim s as String
intFile = 1                            ' ou intFile = FreeFile
filename = "c:\file.txt"               ' nom du fichier
s = "contenu du fichier"               ' chaîne à enregistrer dans le fichier
Open filename For OutPut As intFile    ' ouverture du fichier
Print intFile, s                       ' écriture dans le fichier
Close intFile                          ' fermeture du fichier

File: chap2_precis.tex, line 592


Dim sLine as String
Dim intFile As Integer
intFile = 1                             ' ou intFile = FreeFile
Open sNomeFile For Input As intFile     ' ouverture en mode lecture

Do While Not EOF(1)                     ' tant qu'on n'a pas atteint la fin du fichier
    Line Input intFile, sLine           ' on lit une ligne et on place le contenu dans sLine
Loop
Close intFile                           ' on ferme le fichier

File: td_black_scholes.tex, line 88


MsgBox "boîte à message"

File: td_black_scholes.tex, line 96


Dim r As Double

File: td_black_scholes.tex, line 101


r = Worksheets("Sheet1").Cells(4, 1).Value

File: td_black_scholes.tex, line 121


Function Simulation(ByVal r As Double, ByVal sigma As Double, ByVal x0 As Double, _
            ByVal dt As Double, ByVal T As Long) As Variant
            
    '  code de la fonction            
   
    ' Lorsqu'on connaît le résultat de la fonction, on écrit
    Simulation = résultat
   
End Function

File: td_black_scholes.tex, line 136


Dim n as Long
n = T / dt + 1

File: td_black_scholes.tex, line 143


Dim res() As Double
ReDim res(n)
res (0) = x0

File: td_black_scholes.tex, line 150


Dim w As Double
w = Rnd     ' nombre aléatoire de loi uniforme [0,1]
w = Application.WorksheetFunction.NormSInv(w) * dt ^ 0.5

File: td_black_scholes.tex, line 159


For i = 1 To nb
   res (i) = res(i-1) * ... à compléter
Next i

File: td_black_scholes.tex, line 166


Simulation = res

File: td_black_scholes.tex, line 175


Dim solution As Variant
solution = Simulation(r, sigma, x0, dt, T)

File: td_black_scholes.tex, line 181


Dim nb as Long
nb = UBound (solution)

File: td_black_scholes.tex, line 187


For i = 0 To nb
    Worksheets("Sheet1").Cells(7 + i, 1) = ... ' temps t
    Worksheets("Sheet1").Cells(7 + i, 2) = ... ' Y_t
Next i

File: td_black_scholes.tex, line 225


Dim plage As Range
Set plage = Worksheets("Sheet1").Range(_
                   Worksheets("Sheet1").Cells(7, 1), _
                   Worksheets("Sheet1").Cells(8, 2) _
               )

File: td_black_scholes.tex, line 236


Dim graphe_in As ChartObject
Dim graphe As Chart
Set graphe_in = Worksheets("Sheet1").ChartObjects.Add(100, 30, 400, 250)
Set graphe = graphe_in.Chart

File: td_black_scholes.tex, line 244


graphe.ChartType = xlXYScatterLines

File: td_black_scholes.tex, line 249


graphe.SetSourceData plage, xlColumns

File: td_black_scholes.tex, line 254


graphe.HasTitle = True
graphe.ChartTitle.Text = "Black Scholes"

File: td_black_scholes.tex, line 260


graphe.Axes(xlValue, xlPrimary).HasTitle = True
graphe.Axes(xlValue, xlPrimary).AxisTitle.Text = "Xt"

graphe.Axes(xlCategory, xlPrimary).HasTitle = True
graphe.Axes(xlCategory, xlPrimary).AxisTitle.Text = "temps (jour)"

File: td_black_scholes.tex, line 269


graphe.SeriesCollection(1).Name = "Courbe1"
graphe.SeriesCollection(1).Border.Color = RGB(0, 0, 255)
graphe.SeriesCollection(1).MarkerStyle = xlMarkerStyleNone

File: td_black_scholes.tex, line 277


Dim serie
Set serie = graphe.SeriesCollection.NewSeries
serie.XValues = Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(7, 1), _
                    Worksheets("Sheet1").Cells(7 + nb, 1))
serie.Values = Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(7, 1 + i), _
                    Worksheets("Sheet1").Cells(7 + nb, 1 + i))
serie.Name = "nouvelle série"

File: td_black_scholes_cor.tex, line 11



' il est préférable de mettre cette ligne en haut du fichier
' afin de préciser à VBA qu'il ne doit rien faire de manière
' implicite comme utiliser une variable non déclarée
Option Explicit


'
' cette fonction prend 5 paramètres qui permettent de simuler
' l'équation stochastique de Black Scholes
'
' elle retourne un tableau de réels
'
'
Function Simulation(ByVal r As Double, ByVal sigma As Double, ByVal x0 As Double, _
            ByVal dt As Double, ByVal T As Long) As Variant


    Dim res() As Double
    Dim X As Double
    Dim i As Long
    Dim w As Double
    Dim nb As Long
    
    nb = T / dt + 1
    
    ReDim res(nb)
    X = x0
    res(0) = X
    
    For i = 1 To nb
        w = Rnd
        w = Application.WorksheetFunction.NormSInv(w) * dt
        X = X * (1 + r * dt + sigma * w)
        res(i) = X
    Next i
    
    Simulation = res
    
End Function



'
' définition de la macro Simulation_macro
'
Sub Simulation_macro()

    Dim r As Double
    Dim sigma As Double
    Dim x0 As Double
    Dim dt As Double
    Dim T As Double
    
    ' on récupère les informations depuis la feuille Excel
    r = Worksheets("Sheet1").Cells(4, 1).Value
    sigma = Worksheets("Sheet1").Cells(4, 2).Value
    x0 = Worksheets("Sheet1").Cells(4, 3).Value
    dt = Worksheets("Sheet1").Cells(4, 4).Value
    T = Worksheets("Sheet1").Cells(4, 5).Value
    
    ' on appelle la fonction simulation 5 fois
    Dim i As Long
    Dim marche(5) As Variant
    For i = 1 To 5
        marche(i) = Simulation(r, sigma, x0, dt, T)
    Next i
    
    ' on trace la courbe avec r = 0
    Dim non_stochastique As Variant
    non_stochastique = Simulation(r, 0, x0, dt, T)
    
    ' on récupère le nombre de points dans une solution
    Dim nb As Long
    nb = UBound(non_stochastique)
    
    
    ' on recopie les valeurs de temps et le résultats de la fonction Simulation
    Dim k As Long
    For i = 0 To nb
        Worksheets("Sheet1").Cells(7 + i, 1) = dt * i
        For k = 1 To 5
            Worksheets("Sheet1").Cells(7 + i, 1 + k) = marche(k)(i)
        Next k
    Next i
    
    ' on recopie la solution non stochastique
    k = 6
    For i = 0 To nb
        Worksheets("Sheet1").Cells(7 + i, 1 + k) = non_stochastique(i)
    Next i
    
    
    ' on met une légende
    Worksheets("Sheet1").Cells(6, 1) = "temps"
    Worksheets("Sheet1").Cells(6, 7) = "non stochastique"
    For k = 1 To 5
        Worksheets("Sheet1").Cells(6, 1 + k) = "Simulation " & k
    Next k
    
    
    '
    ' deuxième partie
    ' on crée le graphique s'il n'existe pas
    '
    
    Dim nb_graphe As Long
    
    ' on compte le nombre de graphes de la feuille Sheet1
    nb_graphe = Worksheets("Sheet1").ChartObjects.Count
    
    If nb_graphe = 0 Then
        ' s'il n'y a pas alors...
    
        Dim plage As Range
        
        ' on récupère les données liées à la feuille (2 colonnes)
        Set plage = Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(7, 1), _
                           Worksheets("Sheet1").Cells(7 + nb, 2))
        
        ' on crée un graphe
        Dim graphe_in As ChartObject
        Dim graphe As Chart
        Set graphe_in = Worksheets("Sheet1").ChartObjects.Add(100, 30, 400, 250)
        Set graphe = graphe_in.Chart
        
        ' on spécifie son type
        graphe.ChartType = xlXYScatterLines
        
        ' on lui dit quelles sont les données à dessiner,
        ' le second paramètres précise qu'elles sont organisées en colonnes
        graphe.SetSourceData plage, xlColumns
        
        ' on lui met un titre
        graphe.HasTitle = True
        graphe.ChartTitle.Text = "Black Scholes"
        
        ' on met un titre sur l'axe des Y
        graphe.Axes(xlValue, xlPrimary).HasTitle = True
        graphe.Axes(xlValue, xlPrimary).AxisTitle.Text = "Xt"
        
        ' on met un titre sur l'axe des X
        graphe.Axes(xlCategory, xlPrimary).HasTitle = True
        graphe.Axes(xlCategory, xlPrimary).AxisTitle.Text = "temps (jour)"
        
        ' on modifie le nom de la première série
        graphe.SeriesCollection(1).Name = "Courbe1"
        graphe.SeriesCollection(1).Border.Color = RGB(0, 0, 255)
        graphe.SeriesCollection(1).MarkerStyle = xlMarkerStyleNone
        
        ' on ajoute les séries suivantes
        Dim serie As Series
        For i = 2 To 5
            Set serie = graphe.SeriesCollection.NewSeries
            serie.XValues = Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(7, 1), _
                           Worksheets("Sheet1").Cells(7 + nb, 1))
            serie.Values = Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(7, 1 + i), _
                           Worksheets("Sheet1").Cells(7 + nb, 1 + i))
            serie.Name = "Courbe" & i
            serie.Border.Color = RGB(0, 0, 255)
            serie.MarkerStyle = xlMarkerStyleNone
        Next i
        
        ' on ajoute la solution non stochastique
        i = 6
        Set serie = graphe.SeriesCollection.NewSeries
        serie.XValues = Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(7, 1), _
                            Worksheets("Sheet1").Cells(7 + nb, 1))
        serie.Values = Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(7, 1 + i), _
                            Worksheets("Sheet1").Cells(7 + nb, 1 + i))
        serie.Name = "non stochastique" & i
        serie.Border.Color = RGB(255, 0, 0)
        serie.MarkerStyle = xlMarkerStyleNone
        serie.Border.Weight = xlMedium
    
    End If
    
End Sub


File: td_maths_couple.tex, line 53


' on crée un document Word
Dim word As Object
Set word = CreateObject("Word.Application")
word.Documents.Add

' on met en forme
word.Selection.Font.Size = 16
word.Selection.Font.Bold = True
  
' écriture d'un petit texte dans ce nouveau document et on va deux fois à la ligne
word.Selection.TypeText "Organisation de la classe vendredi prochain" _
            & vbCrLf & vbCrLf

' vbCrLf insère un paragraphe dans le document Word
' le symbole & permet de concaténer plusieurs chaînes de caractères

' on ajoute le tableau dans le document word
word.Selection.Paste

' on change la mise en forme
word.Selection.Font.Size = 12
word.Selection.Font.Bold = False

' on écrit un petit message de fin
word.Selection.TypeText vbCrLf & vbCrLf & "Bon courage et à vendredi" _
   & vbCrLf & vbCrLf & "Votre professeur de mathématiques"

File: td_maths_couple.tex, line 85


' on imprime le document dans un fichier posscript
' l'imprimante doit être installée sur votre ordinateur
word.ActivePrinter = "HP LaserJet 5P/5MP PostScript"
word.PrintOut Filename:="c:\vendredi.doc", PrintToFile:=True, _
           OutputFileName:="c:\vendredi.ps"

' Fermeture de ce document :
word.ActiveDocument.Close
Set word = Nothing

File: td_maths_couple.tex, line 101


Shell ("C:\texmf\miktex\bin\epstopdf.exe c:\vendredi.ps")

File: td_maths_couple.tex, line 107


Dim s As String
s = Chr(34)
Shell (s & "C:\Program Files\Ghostgum\gs8.60\bin\gswin32c" & s & _
    " -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile=" & _
    "c:\vendredi.pdf d:\vendredi.ps")

File: td_maths_couple.tex, line 120


Dim look As Object
Set look = CreateObject("Outlook.Application")
Dim email As Object
Set email = look.CreateItem(olMailItem)
email.to = ...
email.Body = "organisation de la séance de vendredi, voir pièce jointe"
email.Subject = "cours de maths"
email.Attachments.Add "c:\vendredi.pdf"
email.Send

File: td_maths_couple.tex, line 138


Sub procedure_protege_contre_les_erreurs ()

    On Error Goto Marqueur1 
    
       ' s'il se produit une erreur dans ces lignes,
       ' le programme va directement à la ligne qui
       ' comment par Marqueur1

    On Error Goto Marqueur2
    
       ' s'il se produit une erreur dans ces lignes,
       ' le programme va directement à la ligne qui
       ' comment par Marqueur2
       
       ' la procédure s'arrête ici
       Exit Sub

Marqueur1 :

    ' on affiche un message d'erreur
    MsgBox "Une erreur s'est produite dans la première partie."
    Exit Sub
   
Marqueur2 :

    ' on affiche un message d'erreur
    MsgBox "Une erreur s'est produite dans la seconde partie."
    Exit Sub
   
End Sub

File: td_maths_couple_cor.tex, line 12


'
'  convertit un fichier file1.ps en un fichier file2.pdf
'
Function conversionPDF(ByVal file1 As String, ByVal file2 As String) As String
    
    ' les guillemets
    Dim s As String
    s = Chr(34)
    
    ' version Ghostcript 8.53
    On Error GoTo solution2:
    Shell (s & "C:\Program Files\Ghostgum\gs8.53\bin\gswin32c" & s & _
               " -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile=" & _
               file2 & " " & file1)
    conversionPDF = file2
    Exit Function
    
solution2:

    ' version Ghostcript 8.60
    On Error GoTo solution3:
    Shell (s & "C:\Program Files\gs\gs8.60\bin\gswin32c.exe" & s & _
               " -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile=" & _
               file2 & " " & file1)
    conversionPDF = file2
    Exit Function
    
solution3:
    
    ' version Miktex, il faut que Miktex soit installé
    ' http://miktex.org/
    MsgBox "miktex"
    On Error GoTo pasdesolution
    Shell (s & "C:\texmf\miktex\bin\epstopdf.exe" & s & " " & file1)
    conversionPDF = file2
    Exit Function
    
pasdesolution:
    conversionPDF = ""
    
End Function

'
' macro
'
Sub SeanceVendredi()

    ' recopie des données pour les trier ailleurs
    Range("A2:B13").Select
    Selection.Copy
    Range("E2").Select
    ActiveSheet.Paste
    
    ' on sélectionne la zone à trier et on trie
    Range("E2:F13").Select
    Selection.Sort Key1:=Range("F2"), Order1:=xlAscending, Header:=xlNo, _
                        OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
                        
    ' on forme les couples
    ' le plus fort avec le moins fort
    Dim i As Long  ' position du premier
    Dim j As Long  ' position du dernier
    Dim k As Long  ' position du couple
    Dim m1 As String
    Dim m2 As String
    
    i = 2
    j = 13
    k = 15
    
    While i < j
        Cells(k, 2) = Cells(i, 5)
        Cells(k, 3) = Cells(j, 5)
        
        ' on fait aussi la somme des notes du groupe
        Cells(k, 4) = Cells(i, 6).Value + Cells(j, 6).Value
        
        k = k + 1
        i = i + 1
        j = j - 1
    Wend
    
    '
    ' on crée un document Word à envoyer aux élèves
    '
    
    ' on copie la sélection
    Range("B15:D20").Select
    Selection.Copy
    
    ' on crée un document Word
    Dim word As Object
    Set word = CreateObject("Word.Application")
    word.Documents.Add
    
    ' on met en forme
    word.Selection.Font.Size = 16
    word.Selection.Font.Bold = True
  
    ' écriture d'un petit texte dans ce nouveau document et on va deux fois à la ligne
    word.Selection.TypeText "Organisation de la classe vendredi prochain" & vbCrLf & vbCrLf
    
    ' on ajoute le tableau dans le document word
    word.Selection.Paste
    
    ' on change la mise en forme
    word.Selection.Font.Size = 12
    word.Selection.Font.Bold = False
    
    ' on écrit un petit message de fin
    word.Selection.TypeText vbCrLf & vbCrLf & "Bon courage et à vendredi" & vbCrLf & vbCrLf & _
                                              "Votre professeur de mathématiques"
    
    ' sauvegarde de ce document ainsi créé :
    word.ActiveDocument.SaveAs "c:\temp\vendredi.doc"
    
    ' pour voir le résultat et éviter que Word ne se ferme tout de suite
    ' word.Visible = True
    ' MsgBox "Cliquer pour continuer"
    ' word.Visible = False
    
    ' si l'impression se passe mal, on va à PasImprimante
    On Error GoTo PasImprimante
    
    ' on imprime le document dans un fichier posscript
    ' l'imprimante doit être installée sur votre ordinateur
    word.ActivePrinter = "HP LaserJet 5P/5MP PostScript"
    word.PrintOut Filename:="c:\temp\vendredi.doc", PrintToFile:=True, _
                  OutputFileName:="c:\temp\vendredi.ps"
    
    ' Fermeture de ce document :
    word.ActiveDocument.Close
    Set word = Nothing
    
    ' conversion de ps vers pdf
    Dim ist As String
    ist = conversionPDF("c:\temp\vendredi.ps", "c:\temp\vendredi.pdf")
    If ist = "" Then GoTo PasPDF
    
    
    ' envoi d'un mail
    ' voici la version sans document attaché mais elle marche sans outlook
    'ActiveWorkbook.FollowHyperlink _
            Address:="mailto:xavier.dupre@wanadoo.fr?subject=cours de maths&body=groupes pour vendredi", _
            NewWindow:=True
            
    ' on récupère les adresses dans une chaîne de caractères
    Dim tous As String
    For i = 2 To 13
        tous = tous & Cells(i, 3)
        If i < 13 Then tous = tous & ";"
    Next i
    
    On Error GoTo PasOutlook
                                
    ' envoi d'un mail avec Outlook
    Dim look As Object
    Set look = CreateObject("Outlook.Application")
    Dim email As Object
    Set email = look.CreateItem(olMailItem)
    email.to = tous
    email.Body = "organisation de la séance de vendredi, voir pièce jointe"
    email.Subject = "cours de maths"
    email.Attachments.Add "c:\temp\vendredi.pdf"
    email.Send
    
    Set email = Nothing
    
    Exit Sub
    
PasPDF:
    MsgBox "Il est impossible de convertir le fichier ps en PDF."
    Exit Sub
    
PasImprimante:
    ' Fermeture de ce document :
    word.ActiveDocument.Close
    Set word = Nothing
    MsgBox "Il est impossible d'imprimer."
    Exit Sub
    
PasOutlook:
    MsgBox "Outlook n'est pas disponible ou la conversion en PDF s'est mal passée."
    Exit Sub
    
End Sub

File: td_presentation_cor.tex, line 11


'
' crée deux graphes correspondant à une année
'
Sub GrapheAnnee(ByVal annee As Long)
    
    ' on cherche la ligne correspond à l'année
    Dim ligne As Long
    ligne = 9
    While Worksheets("table").Cells(ligne, 1) <> annee And ligne < 3000
        ligne = ligne + 1
    Wend
    
    If ligne = 3000 Then
        MsgBox "L'année " & annee & " est introuvable."
        Exit Sub
    End If
    
    ' on insère deux feuilles de calcul pour y mettre les graphes
    Dim feuille As Object
    Dim feuille_pie As Object
    
    On Error GoTo existe_pas
    
    Set feuille = Worksheets("graphes")
    Set feuille_pie = Worksheets("graphes_pie")
    GoTo suite
    
existe_pas:

    Set feuille = Sheets.Add
    feuille.Name = "graphes"
    Set feuille_pie = Sheets.Add
    feuille_pie.Name = "graphes_pie"
    
suite:

    ' '''''''''''''''''''''''''''''''''''''''''''''
    ' on crée un premier graphe
    ' '''''''''''''''''''''''''''''''''''''''''''''
    
    ' on récupère les données liées à la feuille (2 colonnes)
    Dim plage As Range
    Set plage = Worksheets("table").Range(Worksheets("table").Cells(ligne, 2), _
                       Worksheets("table").Cells(ligne, 4))
        
    ' création du premier graphe
    Dim graphe_in As ChartObject
    Dim graphe As Chart
    Set graphe_in = Worksheets("graphes").ChartObjects.Add(10 + (ligne - 8) * 20, 10 + (ligne - 8) * 20, 400, 300)
    Set graphe = graphe_in.Chart
    
    ' on spécifie son type
    graphe.ChartType = xlColumnClustered
    
    ' on lui dit quelles sont les données à dessiner,
    ' le second paramètres précise qu'elles sont organisées en colonnes
    graphe.SetSourceData plage, xlLines
    
    ' on lui met un titre
    graphe.HasTitle = True
    graphe.ChartTitle.Text = "Employees Year " & annee
    
    ' on assigne au graphe la légende des x
    graphe.SeriesCollection(1).XValues = "=(table!R7C2,table!R7C3,table!R7C4)"
    graphe.SeriesCollection(1).Name = Worksheets("table").Cells(ligne, 1)
    graphe.SeriesCollection(1).Border.ColorIndex = 3
    graphe.SeriesCollection(1).Interior.ColorIndex = 3
    
    ' on spécifie pas de légende
    graphe.HasLegend = False
    
    ' on indique le maximum sur les ordonnées
    graphe.Axes(xlValue).MaximumScale = 3500
    
    ' '''''''''''''''''''''''''''''''''''''''''''''
    ' on crée un second graphe
    ' '''''''''''''''''''''''''''''''''''''''''''''
    
    ' on récupère les données
    Dim plage2 As Object
    Set plage2 = Worksheets("table").Range(Worksheets("table").Cells(ligne, 5), _
                       Worksheets("table").Cells(ligne, 13))
    
    
    ' on crée le second graphe
    Dim graphe_in_pie As ChartObject
    Dim graphe_pie As Chart
    Set graphe_in_pie = Worksheets("graphes_pie").ChartObjects.Add(10 + (ligne - 8) * 20, 10 + (ligne - 8) * 20, 400, 300)
    Set graphe_pie = graphe_in_pie.Chart
    
    ' on spécifie son type
    graphe_pie.ChartType = xlPie
    
    ' on lui dit quelles sont les données à dessiner,
    ' le second paramètres précise qu'elles sont organisées en colonnes
    graphe_pie.SetSourceData Source:=plage2, PlotBy:=xlRows
    
    ' on lui met un titre
    graphe_pie.HasTitle = True
    graphe_pie.ChartTitle.Text = "Civilian Agencies " & annee
    
    ' on spécifie pas de légende
    graphe_pie.HasLegend = False
    
    ' on lui donne des étiquettes
    graphe_pie.SeriesCollection(1).XValues = "=table!R8C5:R8C13"
    
    ' on lui dit comment afficher les étiquettes
    graphe_pie.SeriesCollection(1).ApplyDataLabels Type:=xlDataLabelsShowLabel, _
        AutoText:=True, LegendKey:=True, HasLeaderLines:=True
    
    ' on change la couleur du fond
    graphe_pie.ChartArea.Interior.ColorIndex = 2
    graphe_pie.PlotArea.Interior.ColorIndex = 2
    
    ' on change quelques détails sur la position du graphe...
    graphe_pie.PlotArea.Left = 87
    graphe_pie.PlotArea.Top = 55
    graphe_pie.PlotArea.Width = 161
    graphe_pie.PlotArea.Height = 160
    graphe_pie.PlotArea.Width = 209
    graphe_pie.PlotArea.Height = 210
    graphe_pie.PlotArea.Border.LineStyle = xlNone
    
    ' on change la taille de la police
    With graphe_pie.SeriesCollection(1).DataLabels.Font
        .Name = "Arial"
        .FontStyle = "Normal"
        .Size = 9
    End With
    
    ' pas de bordure autour du graphe
    graphe_pie.ChartArea.Border.LineStyle = xlNone
    
End Sub

File: td_presentation_cor.tex, line 151


'
' seconde partie : création de la présentation
'
Sub GrapheAnneeMacro_SecondePartie()

    ' on crée un document PowerPoint
    Dim power As Object
    Set power = CreateObject("PowerPoint.Application")
    
    ' création d'une présentation
    Dim pres As Object
    Set pres = power.Presentations.Add(WithWindow:=msoTrue)

    ' on crée autant de pages qu'il y a de graphiques
    Dim page As Object
    
    ' pour voir le résultat et éviter que Word ne se ferme tout de suite
    power.Visible = True
    
    Dim nb As Long
    Dim t As Object
    Dim g1 As Object
    Dim g2 As Object
    
    For nb = 1 To Worksheets("graphes").ChartObjects.Count
    
        ' on récupère les graphes
        Set g1 = Worksheets("graphes").ChartObjects(nb)
        Set g2 = Worksheets("graphes_pie").ChartObjects(nb)
        
        ' on ajoute un slide vide
        Set slide = pres.Slides.Add(Index:=nb, Layout:=12)
        power.ActiveWindow.ViewType = 1
        
        ' on copie le graphique comme une image
        g1.CopyPicture
        
        ' on l'ajoute au slide
        slide.Shapes.Paste
        
        ' on sélectionne l'image pour changer sa taille
        ' magouille PowerPoint
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.View.GotoSlide Index:=nb
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.Selection.SlideRange.Shapes(1).Select
        
        ' on modifie sa taille
        With power.ActiveWindow.Selection.ShapeRange
            .Height = 538.38
            .Width = 716.38
            .Left = 0#
            .Top = 0#
        End With
        
        ' on récupère le graphe pie
        ' on copie le graphique comme une image
        g2.CopyPicture
        
        ' on l'ajoute au slide
        slide.Shapes.Paste
        
        ' on sélectionne l'image pour changer sa taille
        ' magouille PowerPoint
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.View.GotoSlide Index:=nb
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.Selection.SlideRange.Shapes(2).Select
        
        ' on modifie sa taille
        With power.ActiveWindow.Selection.ShapeRange
            .Height = 250
            .Width = 350
            .Left = 350#
            .Top = 50#
        End With        
        
        Set slide = Nothing
        
    Next nb
    
    ' on règle les transitions entre transparents
    With power.ActivePresentation.Slides.Range.SlideShowTransition
        .EntryEffect = 2819
        .Speed = 3
        .AdvanceOnClick = msoTrue
        .AdvanceOnTime = msoTrue
        .AdvanceTime = 1
        .SoundEffect.Type = 0
    End With
    

End Sub

File: td_presentation_cor.tex, line 250


Private Sub annuler_Click()
    Unload graphes_dialog
End Sub

Private Sub ok_Click()
    
    ' on génère tous les graphes
    Dim i As Long
    Dim j As Long
    Dim a As Long
    
    i = Val(premier.Text)
    j = Val(dernier.Text)
    
    For a = i To j
        GrapheAnnee a
    Next a
    
    ' on créé la présentation
    GrapheAnneeMacro_SecondePartie
    
    ' on supprime la boîte de dialogue
    Unload graphes_dialog
End Sub

File: td_presentation_image.tex, line 21


Cells (4,3).Value = 3  ' on modifie le contenu de la ligne 4 colonne 3

File: td_presentation_image.tex, line 29


Dim power As Object
Set power = CreateObject("PowerPoint.Application")

File: td_presentation_image.tex, line 35


Dim pres As Object
Set pres = power.Presentations.Add(WithWindow:=msoTrue)

File: td_presentation_image.tex, line 41


power.Visible = True

File: td_presentation_image.tex, line 48


Set slide = pres.Slides.Add(Index:=nb, Layout:=12)
power.ActiveWindow.ViewType = 1

File: td_presentation_image.tex, line 54


power.ActiveWindow.Selection.Unselect
power.ActiveWindow.View.GotoSlide Index:=nb
power.ActiveWindow.Selection.Unselect

File: td_presentation_image.tex, line 61


power.ActiveWindow.Selection.SlideRange.Shapes.AddPicture _
        (Filename:=imnom, LinkToFile:=False, SaveWithDocument:=True, _
        Left:=0, Top:=0).Select

File: td_presentation_image.tex, line 68


Set slide = Nothing

File: td_presentation_image.tex, line 82


power.ActiveWindow.Selection.Unselect
power.ActiveWindow.View.GotoSlide Index:=nb
power.ActiveWindow.Selection.Unselect
power.ActiveWindow.Selection.SlideRange.Shapes(1).Select

File: td_presentation_image.tex, line 90


With power.ActiveWindow.Selection.ShapeRange
    .Left   ' coordonnées du coin supérieur gauche
    .Top    ' 
    
    .Width  ' largeur et 
    .Height ' hauteur de l'image
End With

File: td_presentation_image.tex, line 140


Load image_dialog    ' création de la boîte de dialogue
image_dialog.repertoire.Text = Cells(1, 1).Value  
   ' on stipule que dans la zone de saisie (dont le nom est repertoire),
   ' il doit y avoir lorsque la fenêtre apparaît
   ' le contenu de la première cellule de la feulle de calcul
image_dialog.Show  ' Excel reprend le contrôle et attend vos instructions 
                   ' après avoir affiché la boîte de dialogue

File: td_presentation_image.tex, line 153


' VBA ajoute automatiquement la première et la dernière de ces trois lignes
' variable_Annuler n'est pas la légende (Caption) du bouton Annuler
' mais son nom (Name)
Private Sub variable_Annuler_Click()
   Unload image_dialog
End Sub

File: td_presentation_image.tex, line 164


Unload image_dialog   							' on détruit la boîte de dialogue
Cells(1, 1).Value = repertoire.Text ' on récupère le répertoire saisi
                                    ' et on le met dans la première cellule de la feuille
' et ici : lancer la création du diaporama

File: td_presentation_image.tex, line 173


Private Sub Changer_Click()
    Dim s As String
    s = BrowseForFolderShell("Choisissez un répertoire", repertoire.Text)
    repertoire.Text = s
End Sub

File: td_presentation_image.tex, line 185


Function BrowseForFolderShell(title As String, repertoire As String) As String
    Dim objShell As Object
    Dim objFolder As Object
    Dim strFolderFullPath As String
    
    Set objShell = CreateObject("Shell.Application")
    Set objFolder = objShell.BrowseForFolder(0, titre, 0, repertoire)
    
    If (Not objFolder Is Nothing) Then
        On Error Resume Next
        If IsError(objFolder.Items.Item.path) Then
           strFolderFullPath = CStr(objFolder): GoTo Here
        End If
        On Error GoTo 0
        If Len(objFolder.Items.Item.path) > 3 Then
            strFolderFullPath = objFolder.Items.Item.path & Application.PathSeparator
        Else
            strFolderFullPath = objFolder.Items.Item.path
        End If
    Else
        BrowseForFolderShell = repertoire
        Exit Function
    End If
    
Here:
    BrowseForFolderShell = strFolderFullPath
    
    Set objFolder = Nothing
    Set objShell = Nothing
    
End Function

File: td_presentation_image.tex, line 221


Function BrowseForFolderShell(title As String, repertoire As String) As String
    Dim fd As FileDialog
    Set fd = Application.FileDialog(msoFileDialogFolderPicker)
    fd.title = title
    fd.AllowMultiSelect = False
    fd.InitialFileName = repertoire & "\"

    If fd.Show = -1 Then
        Dim v As Variant
        For Each v In fd.SelectedItems
            BrowseForFolderShell = v
        Next
    Else 
        BrowseForFolderShell = repertoire
    End If

    Set fd = Nothing
End Function

File: td_presentation_image.tex, line 250


Function ListFileInFolder(chemin As String) As Variant
    Dim i As Long
    Dim res() As String
    
    ' mise en place de la liste de fichier
    With Application.FileSearch
         .NewSearch
         .FileType = msoFileTypeAllFiles
         .Filename = "*.jpg;*.jpeg;*.tif;*.png;*.bmp"
         .SearchSubFolders = False
         .LookIn = chemin
         If .Execute() > 0 Then
            ReDim res(.FoundFiles.Count)
            For i = 1 To .FoundFiles.Count
                res(i) = .FoundFiles(i)
            Next i
         End If
    End With
    ListFileInFolder = res
End Function

File: td_presentation_image_cor.tex, line 12


'
' retourne la liste des images d'un répertoire
'
Function ListFileInFolder(chemin As String) As Variant
    Dim i As Long
    Dim res() As String

    ' mise en place de la liste de fichier
    With Application.FileSearch
         .NewSearch
         .FileType = msoFileTypeAllFiles
         .Filename = "*.jpg;*.jpeg;*.tif;*.png;*.bmp"
         .SearchSubFolders = False
         .LookIn = chemin
         If .Execute() > 0 Then
            ReDim res(.FoundFiles.Count)
            For i = 1 To .FoundFiles.Count
                res(i) = .FoundFiles(i)
            Next i
         End If
    End With
    ListFileInFolder = res
End Function
      
'
' création d'un power point avec une liste d'images
'
Sub macro_film()

    Dim chemin As String
    Dim image As Variant
    Dim ligne As Long
    Dim colnne As Long
    
    ' on récupère le chemin sélectionné
    chemin = Selection.Value
    
    ' et sa position
    ligne = Selection.Row
    colonne = Selection.Column
    
    ' on récupère la liste des images
    image = ListFileInFolder(chemin)
    
    ' on crée un document PowerPoint
    Dim power As Object
    Set power = CreateObject("PowerPoint.Application")
    
    ' création d'une présentation
    Dim pres As Object
    Set pres = power.Presentations.Add(WithWindow:=msoTrue)

    ' on crée autant de pages qu'il y a de graphiques
    Dim page As Object
    
    ' pour voir le résultat et éviter que Word ne se ferme tout de suite
    power.Visible = True
    
    ' on insère les images
    Dim nb As Long
    For nb = 1 To UBound(image)
    
        ' on écrit le nom de l'image dans la cellule
        Cells(ligne + nb + 1, colonne).Value = image(nb)
    
        ' on ajoute un slide vide
        Set slide = pres.Slides.Add(Index:=nb, Layout:=12)
        power.ActiveWindow.ViewType = 1
        
        ' on sélectionne l'image pour changer sa taille
        ' magouille PowerPoint
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.View.GotoSlide Index:=nb
        power.ActiveWindow.Selection.Unselect
        
        ' on insère une image
        power.ActiveWindow.Selection.SlideRange.Shapes.AddPicture _
                (Filename:=image(nb), LinkToFile:=False, SaveWithDocument:=True, _
                Left:=0, Top:=0).Select
        
        ' on sélectionne l'image pour changer sa taille
        ' magouille PowerPoint
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.View.GotoSlide Index:=nb
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.Selection.SlideRange.Shapes(1).Select
        
        ' on la position en haut à gauche
        With power.ActiveWindow.Selection.ShapeRange
            .Left = 0#
            .Top = 0#
        End With
        
        ' on sélectionne l'image pour changer sa taille
        ' magouille PowerPoint
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.View.GotoSlide Index:=nb
        power.ActiveWindow.Selection.Unselect
        power.ActiveWindow.Selection.SlideRange.Shapes(1).Select
        
        ' on modifie sa taille
        With power.ActiveWindow.Selection.ShapeRange
            ' si l'image est trop petite
            If .Height < .Width And .Width < 400 Then .Width = 400
            If .Width < .Height And .Height < 400 Then .Height = 400
            ' si l'image est trop grande
            If .Width > power.Width Then .Width = power.Width
            If .Height > power.Height Then .Height = power.Height
            ' on centre l'image
            .Left = (power.Width - .Width) / 2
            .Top = (power.Height - .Height) / 2
            
            ' on écrit les dimensions de l'image dans les cellules suivantes
            Cells(ligne + nb + 1, colonne + 1).Value = .Left
            Cells(ligne + nb + 1, colonne + 2).Value = .Top
            Cells(ligne + nb + 1, colonne + 3).Value = .Width
            Cells(ligne + nb + 1, colonne + 4).Value = .Height        
        End With

        Set slide = Nothing
    Next nb
        
    ' on met un fond noir
    With power.ActivePresentation.SlideMaster.Background
        .Fill.Visible = msoTrue
        .Fill.ForeColor.SchemeColor = 2
        .Fill.Transparency = 0#
        .Fill.Solid
    End With
    With power.ActivePresentation.Slides.Range
        .FollowMasterBackground = msoTrue
        .DisplayMasterShapes = msoTrue
    End With
    
    ' on règle les transitions entre transparents
    With power.ActivePresentation.Slides.Range.SlideShowTransition
        .EntryEffect = 2819
        .Speed = 3
        .AdvanceOnClick = msoTrue
        .AdvanceOnTime = msoTrue
        .AdvanceTime = 1
        .SoundEffect.Type = 0
    End With
End Sub

File: td_presentation_image_cor.tex, line 160


Function BrowseForFolderShell(title As String, repertoire As String) As String
    Dim objShell As Object
    Dim objFolder As Object
    Dim strFolderFullPath As String
    
    Set objShell = CreateObject("Shell.Application")
    Set objFolder = objShell.BrowseForFolder(0, titre, 0, repertoire)
    
    If (Not objFolder Is Nothing) Then
        On Error Resume Next
        If IsError(objFolder.Items.Item.path) Then strFolderFullPath = CStr(objFolder): GoTo Here
        On Error GoTo 0
        '// Is it the Root Dir?...if so change
        If Len(objFolder.Items.Item.path) > 3 Then
            strFolderFullPath = objFolder.Items.Item.path & Application.PathSeparator
        Else
            strFolderFullPath = objFolder.Items.Item.path
        End If
    Else
        BrowseForFolderShell = repertoire
        Exit Function
    End If
    
Here:
    BrowseForFolderShell = strFolderFullPath
    Set objFolder = Nothing
    Set objShell = Nothing
End Function

File: td_presentation_image_cor.tex, line 193


Private Sub Changer_Click()
    Dim s As String
    s = BrowseForFolderShell("Choisissez un répertoire", repertoire.Text)
    repertoire.Text = s
End Sub

Private Sub Ok_Click()
    ' on supprime la boîte de dialogue
    Unload image_dialog    
    Cells(1, 1).Value = repertoire.Text
End Sub

Private Sub Annuler_Click()
    ' on supprime la boîte de dialogue
    Unload image_dialog
End Sub

File: td_sudoku.tex, line 42


Function nombre_possible_pour_case(ByRef su As Variant, _
						ByVal i As Long, ByVal j As Long) As Variant
    ' ....
End Function

File: td_sudoku.tex, line 58


Function nombre_possible_pour_case(ByRef su As Variant, _
						ByVal i As Long, ByVal j As Long) As Variant
    Dim res() As Long     ' on crée le résultat sans connaître son contenu
    If ............ 
        ReDim res(0)                  ' on crée un tableau vide
        nombre_possible_pour_case = res ' c'est le résultat de la fonction
        Exit Function                   ' on quitte la fonction
    End If
End Function

File: td_sudoku.tex, line 73


Dim paspossible(9) As Long
Dim k As Long
For k = 1 To 9
    paspossible(k) = 0  ' au départ, tous les chiffres sont possibles
Next k

File: td_sudoku.tex, line 84


Dim ii, jj As Long
ii = i - ((i - 1) Mod 3)
jj = j - ((j - 1) Mod 3)

File: td_sudoku.tex, line 94


Dim n As Long
n = 0
For k = 1 To 9
    If ............... Then n = n + 1
Next k

File: td_sudoku.tex, line 105


ReDim res(n)
n = 0
For k = 1 To 9
    If ................  Then
        ...........
        ...........
    End If
Next k

' fin
nombre_possible_pour_case = res

File: td_sudoku.tex, line 123


Function resolution(ByRef su As Variant) As Variant
    ' .....
End Function

File: td_sudoku.tex, line 143


Function resolution(ByRef su As Variant) As Variant
    ' étape 1
    Dim i,j,vi,vj As Long
    vi = -1
    For i = 1 To 9 
        For j = 1 To 9
            If su (i,j) = 0 Then
               ...................
            End If
        Next j
     Next i
     
     If vi = ..... Then
         resolution = ..........
         Exit Function
     End If
     
     ' étape 2
     Dim ens As Variant
     ens = nombre_possible_pour_case (.......)
     If UBound (ens) ...... Then
         Dim res(0) As Long
         resolution = res
         Exit Function
     End If
     
     ' étape 3
     Dim k As Long
     Dim copie,solution As Variant
     copie = su
     For k = 1 To ..... 
         copie ( ...... ) = ens (k)
         solution = resolution (copie)
         If ..... Then
             .....
             Exit Function
         End If
     Next k
     
     ' au fait, a-t-on réussi ou non si on arrive ici,
     ' lors de l'exécution du programme ?
     resolution = .....
End Function

File: td_sudoku.tex, line 191


Dim nbiter As Long
Function resolution(ByRef su As Variant) As Variant
    nbiter = nbiter + 1
End Function

File: td_sudoku.tex, line 202


Sub macro_sudoku()
    Dim i As Long
    i = 0
    For Each ch In Selection
        i = i + 1  ' pointeur d'arrêt ici
    Next ch
    If i <> 81 * 2 Then
        MsgBox "Vous n'avez pas sélectionné 81 * 2 cases, on sélectionne la plage B2:J10 + N2:V10"
        Range("B2:J10,N2:V10").Select
        Range("N2").Activate
    End If 
End Sub

File: td_sudoku.tex, line 232


Dim sudoku(9, 9) as Long
i = 1
j = 1
For Each ch In Selection
    sudoku(i, j) = ........
    If j = 9 Then
        ......
    Else
        j = j + 1
    End If
Next ch

File: td_sudoku.tex, line 248


Dim r As Variant
nbiter = 0
r = resolution(sudoku)

File: td_sudoku_cor.tex, line 10


Option Explicit

Dim nbiter As Long

'
'  retourne le nombre de cases non vides
' on compte toutes celles qui ne contiennent pas 0
'
Function sudoku_cases_non_vide(ByRef su As Variant) As Long
    Dim n As Long
    Dim i As Long
    Dim j As Long
    
    n = 0
    For i = 1 To 9
        For j = 1 To 9
            If su(i, j) > 0 Then n = n + 1
        Next j
    Next i
    
    sudoku_cases_non_vide = n
End Function

'
' retourne l'ensemble des nombres possibles pour une case
' en tenant compte des contraintes
'
Function nombre_possible_pour_case(ByRef su As Variant, _
						ByVal i As Long, ByVal j As Long) As Variant

    Dim res() As Long
    
    ' on regarde d'abord si la case est vide
    If su(i, j) > 0 Then
        ReDim res(0)
        nombre_possible_pour_case = res
        Exit Function
    End If
    
    ' on crée un tableau,
    ' si paspossible (i) : alors le chiffre i est déjà
    ' pris ailleurs dans la ligne, dans la colonne ou dans le petit carré
    ' qui contiennent la case i,j
    
    Dim paspossible(9) As Long
    Dim k As Long
    For k = 1 To 9
        paspossible(k) = 0  ' au départ, tous sont possibles
    Next k
    
    ' vérification des contraintes en ligne et en colonne
    For k = 1 To 9
        If su(i, k) > 0 Then
            paspossible(su(i, k)) = 1
        End If
        
        If su(k, j) > 0 Then
            paspossible(su(k, j)) = 1
        End If
    Next k
    
    ' vérification des contraintes dans le petit carré de la case i,j
    Dim ii, jj, iii, jjj As Long
    ii = i - ((i - 1) Mod 3)
    jj = j - ((j - 1) Mod 3)
    
    For iii = ii To ii + 2
        For jjj = jj To jj + 2
            If su(iii, jjj) > 0 Then
                paspossible(su(iii, jjj)) = 1
            End If
        Next jjj
    Next iii
    
    ' nombre de possibles = tous ceux qui ne sont pas dans pospossible
    ' on les compte d'abord
    Dim n As Long
    n = 0
    For k = 1 To 9
        If paspossible(k) = 0 Then n = n + 1
    Next k
    
    ' puis on les met dans res
    ReDim res(n)
    n = 0
    For k = 1 To 9
        If paspossible(k) = 0 Then
            n = n + 1
            res(n) = k
        End If
    Next k
    
    ' fini
    nombre_possible_pour_case = res
    
End Function

'
' retourne l'ensemble des nombres possibles pour une case
' en tenant compte des contraintes
'
Function get_best_solution(ByRef su As Variant) As Variant
    Dim i, j, mi, mj As Long
    Dim pos As Variant
    
    ' on regarde d'abord si toutes les cases sont encore viables
    For i = 1 To 9
        For j = 1 To 9
            If su(i, j) = 0 Then
                pos = nombre_possible_pour_case(su, i, j)
                If UBound(pos) = 0 Then
                    Dim r(0) As Long
                    get_best_solution = r
                    Exit Function
                End If
            End If
        Next j
    Next i
    
    ' on teste la case qui offre le moins de chiffres possibles vérifiant
    ' les contraintes
    Dim l As Long
    l = 0
    For i = 1 To 9
        For j = 1 To 9
            If su(i, j) = 0 Then
                pos = nombre_possible_pour_case(su, i, j)
                If UBound(pos) = 1 Then
                    Dim rrr(2) As Long
                    rrr(1) = i
                    rrr(2) = j
                    get_best_solution = rrr
                    Exit Function
                ElseIf l = 0 Or UBound(pos) < l Then
                    l = UBound(pos)
                    mi = i
                    mj = j
                End If
            End If
        Next j
    Next i
    
    If l > 0 Then
        ' s'il y a une solution
        Dim rr(2) As Long
        rr(1) = mi
        rr(2) = mj
        get_best_solution = rr
    Else
        ' s'il n'y en a pas
        ' excusez le nom de la variable (rrrr),
        ' la portée d'une variable en VBA est la procédure
        ' même si sa déclaration est à l'intérieur d'un bloc
        Dim rrrr(0) As Long
        get_best_solution = rrrr
    End If
End Function

'
' résolution du sudoku, su est le sudoku à résoudre
'
Function resolution(ByRef su As Variant) As Variant
    ' premier cas, le sudoku est déjà résolu,
    ' auquel cas, c'est fini
    ' la variable nbiter compte le nombre d'itération pour la résolution
    ' il vaut mieux vérifier que ce nombre ne devient pas trop grand,
    ' sinon, il est possible que le programme entre dans une boucle infinie
    ' ce qui oblige l'utilisateur à relancer Excel après l'avoir détruit l'application
    ' dans le gestionnaire des tâches
    If sudoku_cases_non_vide(su) = 81 Or nbiter > 2000 Then
        resolution = su
        Exit Function
    End If
    
    nbiter = nbiter + 1
    
    Dim copie As Variant
    copie = su
    
    ' retourne la case la plus sympathique
    Dim b As Variant
    b = get_best_solution(copie)
    
    ' s'il existe une case impossible
    If UBound(b) = 0 Then
        Dim r(0) As Variant
        resolution = r
        Exit Function
    End If
    
    Dim i, j As Long
    i = b(1)
    j = b(2)
    
    Dim nb As Variant
    Dim sol As Variant
    nb = nombre_possible_pour_case(copie, i, j)
    
    ' sinon on teste toutes les solutions possibles pour une case
    Dim k As Long
    For k = 1 To UBound(nb)
        copie(i, j) = nb(k)
        sol = resolution(copie)
        If UBound(sol) > 0 Then
            resolution = sol
            Exit Function
        End If
    Next k
    
    ' pas de solution
    Dim re(0) As Long
    resolution = re
End Function

'
' macro appelée lorsque le bouton est enclenché
'
Sub macro_sudoku()
    Dim sudoku() As Variant
    Dim i, j As Long
    Dim nb As Long
    Dim ch
    
    ' vérification
    i = 0
    For Each ch In Selection
        i = i + 1
    Next ch
    If i <> 81 * 2 Then
        MsgBox "Vous n'avez pas sélectionné 81 * 2 cases, on sélectionne la plage B2:J10 + N2:V10"
        Range("B2:J10,N2:V10").Select
        Range("N2").Activate
    End If
    
    ' on remplit le sudoku avec les 81 premières cases
    ReDim sudoku(9, 9)
    i = 1
    j = 1
    For Each ch In Selection
        sudoku(i, j) = ch.Value
        If j = 9 Then
            j = 1
            i = i + 1
            If i = 10 Then Exit For
        Else
            j = j + 1
        End If
    Next ch
        
    ' on résoud le sudoku
    Dim r As Variant
    nbiter = 0
    r = resolution(sudoku)
    
    If UBound(r) > 0 Then
        ' s'il y a une solution, on remplit les cases
        i = 1
        j = 1
        For Each ch In Selection
            If i >= 10 Then
                ch.Value = r(i - 9, j)
            End If
            If j = 9 Then
                j = 1
                i = i + 1
            Else
                j = j + 1
            End If
        Next ch
    Else
        ' s'il n'y a pas de solution, on remplit les cases de zéros
        i = 1
        j = 1
        For Each ch In Selection
            If i >= 10 Then
                ch.Value = 0
            End If
            If i = 9 Then
                i = 1
                j = j + 1
            Else
                i = i + 1
            End If
        Next ch
    End If
End Sub

calcul d'un quantile

def quantile (valeurs, alpha) :
    """calcul le quantile d'ordre alpha"""
    if len (valeurs) == 0 : raise Exception ("liste vide")
    valeurs.sort ()
    i = int (alpha * len (valeurs))
    return valeurs [i]

calcul d'un quantile

numToAlpha = 'abcdefghijklmnopqrstuvwxyz'.upper ()
def celluple (s) :
    """convertit une cellule en couple ligne,colonne  C2 --> 2,3,  AA1 --> 1,27"""
    if len (s) <= 1 : return 1,1
    if "0" <= s [1] <= "9" : return int (s [1:]), numToAlpha.find (s [0])+1
    else : return int (s [1:]), (numToAlpha.find (s [0])) * 26 + numToAlpha.find (s [1]) + 1

import win32com.client                                  # module 
excel = win32com.client.Dispatch ('Excel.Application')  # connexion à Excel

tab = 'A2:A25'              # plage de valeurs
par = celluple ('C2')       # position du quantile demandé
res = celluple ('C3')       # position du résultat

feuille = excel.ActiveSheet                                  # on récupère la feuille active
plage   = [ v [0].Value for v in feuille.Range (tab) ]       # on convertit une plage en une liste
param   = float (feuille.Cells (par [0], par [1]).Value)     # on convertit une valeur en un réel

try :
    # on calcule le quantile
    import quantile
    q = quantile.quantile (plage, param)
    feuille.Cells (res [0], res [1]).Value = q          # on place le résultat dans la plage C3
except Exception, e :
    # au cas où une erreur se produit
    feuille.Cells (res [0], res [1]).Value = str (e)    # on place l'erreur dans la plage C3

File: chap4_vba_python.tex, line 48


Public Sub UpdatePythonCode()
    Shell ("c:\python25\pythonw excel.py")
End Sub

File: chap4_vba_python.tex, line 66


tab = __PLAGE__               # ligne 11
par = celluple (__PAR__)      # ligne 12
res = celluple (__RES__)      # ligne 13

File: chap4_vba_python.tex, line 78


Public Function LoadString(ByVal file As String)
    ' ouvre un fichier et construit une unique chaîne de caractères à partir de son contenu
    Dim res As String
    Dim sLine As String
    Open file For Input As #1
    Do While Not EOF(1)
        Line Input #1, sLine
        res = res & sLine & vbCrLf  ' on ajoute les sauts de lignes qui sont oubliés lors de la lecture
    Loop
    Close #1
    LoadString = res
End Function

Public Function WriteString(ByVal s As String, ByVal file As String)
    ' on écrit une unique chaîne de caractères dans un fichier
    Open file For Output As #1
        Print #1, s
    Close #1
End Function

Public Sub UpdatePythonCode()
    ' code la macro
    Dim range1 As String
    Dim par As String
    Dim res As String
    python = LoadString("excel_sample.py")
    python = Replace(python, "__PLAGE__", "'A2:A25'")
    python = Replace(python, "__PAR__", "'C2'")
    python = Replace(python, "__RES__", "'C3'")
    WriteString python, "temp.py"
    Shell ("c:\python25\pythonw temp.py")
End Sub

File: chap4_vba_python.tex, line 115


tab = __PAR0__                 # ligne 11
par = celluple (__PAR1__)      # ligne 12
res = celluple (__RES0__)      # ligne 13

File: chap4_vba_python.tex, line 124


Public Sub RunPythonScript(ByVal script As String, ByVal par As String, ByVal res As String)
    Dim p As Variant
    Dim r As Variant
    Dim python As String
    Dim i As Long
    Dim temp As String
    
    p = Split(par)  ' on découpe la liste des plages d'entrées séparées par des espaces
    r = Split(res)  ' on découpe la liste des plages de sorties séparées par des espaces
    
    python = LoadString(script)   ' on charge le script Python
    
    ' on remplace les paramètres d'entrée par les bonnes plages
    For i = 0 To UBound(p)
        temp = "__PAR" & Val(i) & "__"
        python = Replace(python, temp, "'" & p(i) & "'")
    Next i
    
    ' on remplace les paramètres de sortie par les bonnes plages
    For i = 0 To UBound(r)
        temp = "__RES" & Val(i) & "__"
        python = Replace(python, temp, "'" & r(i) & "'")
    Next i
    
    ' la fin est identique, on écrit le fichier temp.py puis on l'exécute
    WriteString python, "temp.py"
    Shell ("c:\python25\pythonw temp.py")
End Sub

Public Sub UpdatePythonCode()
    RunPythonScript "excel_sample2.py", "A2:A25 C2", "C3"
End Sub

File: chap4_vba_python.tex, line 168


import scipy.linalg
import numpy
import random
m = [ [ random.gauss (0,1) for i in range (0,3) ] for i in range (0,3) ]
mat = numpy.array (m)
mat = mat + mat.transpose ()
l,v = scipy.linalg.eig (mat)
print l
print v

fonctions usuelles pour la communication entre \pythons et \textit{Excel

numToAlpha = 'abcdefghijklmnopqrstuvwxyz'.upper ()
def celluple (s) :
    """convertit une cellule en couple ligne,colonne"""
    if len (s) <= 1 : return 1,1
    if "0" <= s [1] <= "9" : return int (s [1:]), numToAlpha.find (s [0])+1
    else : return int (s [1:]), (numToAlpha.find (s [0])) * 26 + numToAlpha.find (s [1]) + 1
        
def nombre_colonne (plage) :
    """retourne le nombre de colonnes d'une plage"""
    p = plage.split (":")
    return celluple (p [1]) [1] - celluple (p [0]) [1] + 1
        
def lit_matrice (plage, feuille) :
    """transcrit une plage de la feuille Excel en matrice"""
    temp = [ v [0].Value for v in feuille.Range (plage) ]
    nc   = nombre_colonne (plage)
    nl   = len (temp) / nc
    res  = [ [ temp [i*nc+j] for j in range (0,nc) ] for i in range (0,nl) ]
    return res

def ecrit_matrice (valeur, vecteur, plage, feuille) :
    """transcrit une matrice vers une plage d'une feuille Excel"""
    # on calcule la premiere cellule de la plage
    if ":" in plage : i,j = celluple (plage.split (":") [0]) 
    else :            i,j = celluple (plage)   
    # les valeurs propres sont complexes
    for l in range (0, len (valeur)) :
        if valeur [l].imag != 0 :  feuille.Cells (i, j + l).Value = str (valeur [l])
        else : feuille.Cells (i, j + l).Value = valeur [l].real
    # les vecteurs propres sont reels
    for k in range (0, len (vecteur)) :
        for l in range (0, len (vecteur [k])) :
            feuille.Cells (i + k + 2, j + l).Value = str (vecteur [k][l])

calcul des valeurs propres

from excel_function import *
import win32com.client
excel = win32com.client.Dispatch ('Excel.Application')

mat = __PAR0__ # = 'A1:C3' ajout pour debugger
res = __RES0__ # = 'A5'    ajout pour debugger

feuille = excel.ActiveSheet

try :
    import scipy.linalg
    import numpy
    mat = numpy.array (lit_matrice (__PAR0__, feuille))
    valeur,vecteur = scipy.linalg.eig (mat)
    ecrit_matrice (valeur, vecteur, __RES0__, feuille)
except Exception, e :
    if ":" in res : i,j = celluple (res.split (":") [0]) 
    else :          i,j = celluple (res)                 
    feuille.Cells (i, j).Value = str (e)

File: chap4_vba_python.tex, line 194


Public Sub UpdatePythonCode()
    RunPythonScript "excel_eig.py", "A1:C3", "A5"
End Sub

File: chap4_vba_python.tex, line 203


Option Explicit  ' rend explicite les déclarations de variables

Private Const PROCESS_QUERY_INFORMATION As Long = &H400
Private Const STILL_ACTIVE As Long = &H103
Public gszErrMsg As String

' utilisation d'une fonction OpenProcess remplaçant Shell, elle ne fait pas partie du langage VBA
' mais elle fait partie d'une DLL système de Windows
' la ligne qui suit déclare la fonction OpenProcess et l'ajoute à la liste de celles disponibles
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
                                                     ByVal bInheritHandle As Long, _
                                                     ByVal dwProcessId As Long) As Long
                                                     
' permet d'obtenir un code d'erreur après l'exécution de OpenProcess                                                    
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, _
                                                            lpExitCode As Long) As Long

' remplacement de la fonction Shell
' retourne True si l'exécution s'est bien passée, False sinon
' les paramètres d'entrée sont les mêmes que ceux de la fonction Shell
Private Function ShellWait(ByVal szCommandLine As String, _
                           Optional ByVal iWindowState As Integer = vbHide) As Boolean

    Dim lTaskID As Long
    Dim lProcess As Long
    Dim lExitCode As Long
    Dim lResult As Long
    
    On Error GoTo ErrorHandler  ' si une erreur se produit, aller au label ErrorHandler

    ' exécute la ligne de commande szCommandLine
    lTaskID = Shell(szCommandLine, iWindowState)
    
    ' vérifie qu'il n'y a pas d'erreur
    If lTaskID = 0 Then Err.Raise 9999, , "Shell function error."
    
    ' attrape le processus lancé par Shell et qui est en cours d'exécution
    lProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0&, lTaskID)
    
    ' regarde s'il y a des erreurs
    If lProcess = 0 Then Err.Raise 9999, , "Unable to open Shell process handle."
    
    ' attend la fin de l'exécution du script
    Do
        ' lExitCode est égale à STILL_ACTIVE tant que le script continue d'être exécuté
        lResult = GetExitCodeProcess(lProcess, lExitCode)
        DoEvents
    Loop While lExitCode = STILL_ACTIVE
    
    ShellWait = True
    Exit Function
    
ErrorHandler:
    ' gestion des erreurs (gszErrMsg conserve le message d'erreur)
    gszErrMsg = Err.Description
    ShellWait = False
End Function

File: chap4_vba_python.tex, line 293


library (tseries)  

File: chap4_vba_python.tex, line 299


x=get.hist.quote("AXA", quote = c("Open", "High", "Low", "Close"), retclass = "ts")
x100=window(x,start=end(x)[1]-100)
plotOHLC(x100,ylab="prix",main="AXA")

File: chap4_vba_python.tex, line 307


x=get.hist.quote("AXA", quote = c("Open", "High", "Low", "Close"), retclass = "ts")
x100=window(x,start=end(x)[1]-100)
png ("c:\\temp\\essai2.png", width=700, height=500)  # enregistrement au format png
plotOHLC(x100,ylab="prix",main="AXA")
dev.off ()                                           # fin de l'enregsitrement

File: chap4_vba_python.tex, line 324


	Date	Open	High	Low	Close	Volume
20/03/08	56.01	56.75	55.26	55.84	2434000
19/03/08	57.53	57.95	56.40	56.77	2714400
18/03/08	58.85	58.99	57.13	57.61	3265900
...

File: chap4_vba_python.tex, line 333


r <- read.table ("edf.txt", header = TRUE, row.names = 1)

File: chap4_vba_python.tex, line 338


r [[1]]            # accède à la colonne 1 en tant que vecteur
r [["Open"]]       # accède à la colonne Open en tant que vecteur
row.names (r)      # retourne le nom des lignes
length(r)          # retourne le nombre de colonnes
length (r [[1]])   # retourne le nombre de lignes
ts(r)              # convertit r en une série temporelles

File: chap4_vba_python.tex, line 352


from rpy import *    # importer le module rpy

# définition du programme R
code = """library (tseries)
x=get.hist.quote("AXA", quote = c("Open", "High", "Low", "Close"), retclass = "ts")
x100=window(x,start=end(x)[1]-100)
png ("essai2.png", width=700, height=500)
plotOHLC(x100,ylab="prix",main="AXA")
dev.off ()"""

r(code)   # exécution du code

File: chap4_vba_python.tex, line 372


from rpy import *
code = """library (tseries)
x=get.hist.quote("AXA", quote = c("Open", "High", "Low", "Close"), retclass = "ts")
x100=window(x,start=end(x)[1]-100)
plotOHLC(x100,ylab="prix",main="AXA")
r(code)

dessin du cours d'une action avec \codes{rpy

# partie R
from rpy import *
code = """library (tseries)
x=get.hist.quote("AXA", quote = c("Open", "High", "Low", "Close"), retclass = "ts")
x100=window(x,start=end(x)[1]-100)
png ("essai2.png", width=700, height=500)
plotOHLC(x100,ylab="prix",main="AXA")
dev.off ()"""
r(code)

# partie HTML
html = """<html><body><h1>depuis R</h1><img src="NAME"/></body></html>"""
html = html.replace ("NAME", "essai2.png")
f = open ("essai2.html", "w")
f.write (html)
f.close ()

File: chap4_vba_python.tex, line 396


ActiveSheet.Pictures.Insert("essai2.png").Select

dessin du cours d'une action avec \textit{Excel

def finance (action, last, image = "temp.png") :
    # dessin de la série
    from rpy import *
    code = """library (tseries)
    x=get.hist.quote(""" + "\"" + action + "\"" + """, 
               quote = c("Open", "High", "Low", "Close"), retclass = "ts")
    x100=window(x,start=end(x)[1]-""" + str (last) + """)
    png ("c:\\\\essai2.png", width=1000, height=500)
    plotOHLC(x100,ylab="prix",main=""" + "\"" + action + "\"" + """)
    dev.off ()"""
    r(code)

    # extraction avec volume pour export vers Excel
    code = """x=get.hist.quote(""" + "\"" + action + "\"" + """, 
                    quote = c("Open", "High", "Low", "Close", "Volume"), retclass = "ts")
    x100=window(x,start=end(x)[1]-""" + str (last) + """)"""
    r (code)

    # conversion en python
    series = r ("x100")
    return series
    
def copie_tableau (series, i,j) :
    """recopie un tableau dans un feuille"""
    for xi in range (0, len (series)) :
        for xj in range (0, len (series [xi])) :
            feuille.Cells (i + xi, j + xj).Value = series [xi][xj]

import win32com.client
from celluple import *
excel = win32com.client.Dispatch ('Excel.Application')

act = celluple (__PAR0__)
par = celluple (__PAR1__)
res = celluple (__RES0__)

feuille = excel.ActiveSheet
action  = str (feuille.Cells (act [0], act [1]).Value)
param   = float (feuille.Cells (par [0], par [1]).Value)

try :
    series = finance (action, param)
    copie_tableau (series, res [0], res [1])
except Exception, e :
    feuille.Cells (res [0], res [1]).Value = str (e)

File: chap4_vba_python.tex, line 428


' charge un fichier texte
Public Function LoadString(ByVal file As String)
    Dim res As String
    Dim sLine As String
    Open file For Input As #1
    Do While Not EOF(1)
        Line Input #1, sLine
        res = res & sLine & vbCrLf
    Loop
    Close #1
    LoadString = res
End Function

' écrit un fichier texte
Public Function WriteString(ByVal s As String, ByVal file As String)
    Open file For Output As #1
        Print #1, s
    Close #1
End Function

' exécute un script Python
Public Sub RunPythonScript(ByVal script As String, ByVal par As String, ByVal res As String)
    Dim p As Variant
    Dim r As Variant
    Dim python As String
    Dim i As Long
    Dim temp As String
    
    p = Split(par)
    r = Split(res)
    
    python = LoadString(script)
    
    For i = 0 To UBound(p)
        temp = "__PAR" & Val(i) & "__"
        python = Replace(python, temp, "'" & p(i) & "'")
    Next i
    For i = 0 To UBound(r)
        temp = "__RES" & Val(i) & "__"
        python = Replace(python, temp, "'" & r(i) & "'")
    Next i
    
    WriteString python, "temp.py"
    ShellWait ("c:\python25\pythonw temp.py")
End Sub

' lance l'exécution d'un script Python puis charge une image
Public Sub UpdatePythonCode()
    RunPythonScript "rplot2.py", "C3 C4", "B7"
    ActiveSheet.Pictures.Insert("essai2.png").Select
End Sub

' cette dernière fonction est celle attachée à la pression du bouton "dessiner"
Private Sub dessiner_Click()
    UpdatePythonCode
End Sub

File: usb.tex, line 18


class copie_usb (object):
    """recopie des fichiers sur une clé USB"""
    
    def __init__(self,ch1,ch2,accept = ".*",refuse = "") :
        """initialisation,
        @param      ch1         répertoire source
        @param      ch2         répertoire destination
        @param      accept      filtre pour les fichiers acceptés pour la copie
        @param      refuse      pour refuser des fichiers parmi ceux déjà acceptés"""
        
    def accepter (self, fichier) :
        """dit si un fichier est accepté à la copie ou non,
        retourne un booléen"""
        
    def liste_fichier_repertoire (self,repertoire):
        """récupération de la liste des répertoires et celle des fichiers, 
        inclus dans le répertoire repertoire"""
        
    def copie (self) :
        """effectue la copie"""
        
        # première étape
        # récupération de la liste des répertoires et fichiers

        # seconde étape
        # élimination des importuns
        
        # troisième étape
        # on créé les répertoires s'ils n'existent pas
                
        # quatrième étape
        # on recopie les fichiers
        

# petit exemple d'utilisation
c = copie_usb (ch1, ch2, filtre_accept, filtre_refuse)
c.copie ()

File: usb.tex, line 103


import re
t = re.compile (".*[.]htm$", re.IGNORECASE)
if re.match (t, "inDex.htm") : print True
else : print False
if re.match (t, "inDex.html") : print True
else : print False

File: usb.tex, line 114


print re.match (t, "inDex.htm")  # affiche <_sre.SRE_Match object at 0x008712C0>
print re.match (t, "inDex.html") # affiche None

copie de fichiers vers une clé USB

# coding: cp1252
"""copie de fichiers sur une clé USB"""

import re       # pour les expressions régulières
import os       # pour les fichiers et répertoires
import os.path  # pour les noms de fichiers et noms de répertoires
import copy
import shutil   # pour la copie de fichiers

class copie_usb (object):
    """recopie des fichiers sur une clé USB"""
    
    def __init__(self,ch1,ch2,accept = ".*",refuse = "") :
        """initialisation,
        @param      ch1         répertoire source
        @param      ch2         répertoire destination
        @param      accept      filtre pour les fichiers acceptés pour la copie
        @param      refuse      pour refuser des fichiers parmi ceux déjà acceptés"""
        self.ch1     = ch1
        self.ch2     = ch2
        self.accept  = re.compile (accept, re.IGNORECASE) # création des motifs
        self.refuse  = re.compile (refuse, re.IGNORECASE) # création des motifs
        
    def accepter (self, fichier) :
        """dit si un fichier est accepté à la copie ou non"""
        r = re.match (self.accept, fichier)
        if not r : return False
        r = re.match (self.refuse, fichier)
        return not r
        
    def aide (self) :
        """retourne une aide sur les formats d'expression"""
        help (re.engine)
        
    def liste_fichier_repertoire (self,repertoire):
        """récupération de la liste des répertoires et celle des fichiers, 
        inclus dans le répertoire repertoire"""
        rep     = []
        file    = []
        list    = os.listdir (repertoire)
        
        for cc in list :
            c = repertoire + "\\" + cc
            if os.path.isfile (c) : file.append (cc)
            if os.path.isdir (c) : rep.append (cc)
        
        rep2 = copy.copy (rep)
        for chemin in rep2 :
            r,f = self.liste_fichier_repertoire (repertoire + "\\" + chemin)
            for x in r :
                rep.append (chemin + "\\" + x)
            for x in f :
                file.append (chemin + "\\" + x)
            
        return rep,file
        
    def repertoire_selectionne (self, r, file_clean) :
        """dit si la liste file_clean contient au moins un fichier 
        inclus dans le repertoire r"""
        t = re.compile ("^" + r + "\\\\.*", re.IGNORECASE)
        for l in file_clean :
            if re.match (t,l) : return True
        return False
        
    def copie (self) :
        """effectue la copie"""
        
        # récupération de la liste des répertoires et fichiers
        rep,file = self.liste_fichier_repertoire (self.ch1)
        # élimination des importuns
        file_clean = [ f for f in file if self.accepter (f) ]
        
        # facultatif, exclue les répertoires pour lesquels 
        # aucun fichier n'est sélectionné
        rep_clean = [ r for r in rep if self.repertoire_selectionne (r, file_clean) ]
        
        # on créé les répertoires s'il n'existent pas
        if not os.path.exists (self.ch2) :
            print "création du répertoire ", self.ch2
            os.mkdir (self.ch2)

        for r in rep_clean :
            c = self.ch2 + "\\" + r
            if not os.path.exists (c) :
                print "création du répertoire ", r
                os.mkdir (c)
                
        # on recopie les fichiers
        for f in file_clean :
            s = self.ch1 + "\\" + f
            c = self.ch2 + "\\" + f
            print "copie du fichier ", f
            shutil.copy (s, c)
        

if __name__ == "__main__" :
    print "copie de fichiers vers une clé USB"
    ch1             = "C:\\Documents and Settings\\Dupré\\" \
                        "Mes documents\\informatique\\support\\python_td"
    ch2             = "c:\\temp\\copie_usb"
    filtre_accept   = ".*[.].*"
    filtre_refuse   = ".*[.]pdf$|.*[.]html$|.*[.]bmp|programme\\\\.*[.]zip$"
    
    # filtre_accept accepte tout type de fichier
    # filtre_refuse refuse tous les fichiers dont l'extension est pdf, html ou 
    # inclus dans le répertoire programme et ayant l'extension zip
    
    c = copie_usb (ch1, ch2, filtre_accept, filtre_refuse)
    c.copie ()


File: html_recherche.tex, line 13


p = HTMLParser ()
p.feed (text)
p.close ()

File: html_recherche.tex, line 24


<a href="bresenham_ligne4.html"> tracé d'une ligne</a>

File: html_recherche.tex, line 30


def handle_starttag (self, tag,attr) :
    print "balise ", tag
    for i,j in attr :
        print i,j
        if i == "href" :
           # ...

File: html_recherche.tex, line 39


def handle_data (self, data) :
    d = data.replace ("\n", "")

File: html_recherche.tex, line 47


class HTML_explore (HTMLParser.HTMLParser) :

    def __init__ (self, list, url, text) :
        html_parser_script.HTMLParserScript.__init__(self)
        self.list           = list
        self.url            = url
        self.text           = text

File: html_recherche.tex, line 60


adr = urlparse.urljoin ("http://www.lemonde.fr/", "web/article/")

File: html_recherche.tex, line 69


try :
    f       = urllib.urlopen (url)
    d       = f.read ()
    whole   = d
except Exception, exc:
    print "    exception lecture ", exc, "\t -- ", url
    error.append (url)
    continue 

File: html_recherche.tex, line 83


p       = HTML_explore (adr, url, text)
p.feed (whole)
p.close ()

File: html_recherche.tex, line 93


s               = ".*Bush.*"
ex              = re.compile (s, re.IGNORECASE)
if ex.match (contenu) : 
    # ...

File: html_recherche.tex, line 104


url         = "http://www.lemonde.fr/"
# on appelle la fonction process_file pour récupérer les informations
# inscrites dans le fichier XML
s               = ".*ukraine.*"
ex              = re.compile (s, re.IGNORECASE)
li,error,nb     = process_file (url, ex, 3, -10)

recherche de mot-clés sur Internet (1)

# coding: cp1252
"""recherche de mot-clés dans des pages HTML, 
ce programme ne peut lire pour l'instant que le format HTML 2.0
et pas HTML 4.01, format utilisé par la plupart des sites."""

import urllib               # accéder une adresse internet
import urlparse             # manipuler les adresses internet
import re                   # expression à chercher
import html_parser_script   # classe de parser HTML modifiée pour éviter les scripts

class HTML_explore (html_parser_script.HTMLParserScript) :
    """parcour un fichier HTML"""
    
    def __init__ (self, list, text, url, niveau, niveau_max) :
        html_parser_script.HTMLParserScript.__init__(self)
        self.list           = list
        self.niveau         = niveau
        self.niveau_max     = niveau_max
        self.url            = url
        self.text           = text
        
    def cherche (self,url) :
        """recherche un url dans la liste"""
        for n,u in self.list :
            if u == url : return True
        return False
        
    def diese (self,adr) :
        """simplifie les liens avec le symboles #"""
        p = adr.find ("#")
        if p == -1 : return adr
        else : return adr [0 : p]

    def handle_starttag (self, tag,attr) :
        """nouveau tag ou balise"""
        if self.niveau >= self.niveau_max : return
        self.tag = tag
        if self.tag == "a" or self.tag == "area" :
            for i,j in attr :
                if (i == "aref" or i == "href") and len (j) > 0 and j [0] != "#" :
                    adr = self.diese (j)
                    if len (adr) > 4 and (adr [0:4] == "http" or adr == "ftp") :
                        if not self.cherche (adr) :
                            self.list.append ((self.niveau, adr))
                    elif len (adr) > 5 and adr [0:6] != "mailto" :
                        adr = urlparse.urljoin (self.url, adr)
                        if not self.cherche (adr) :
                            self.list.append ((self.niveau, adr))
        
    def handle_endtag (self, tag) :
        """fin d'un tag ou balise"""
        pass
        
    def handle_data (self, data) :
        """texte compris entre le début et la fin d'un tag"""
        d = data.replace ("\n", "")
        if len (d) > 3 :
            self.text.append (data)
        
        
def process_file (url, exp, niveau_max = 5, nbmax = -1) :
    """parcours un fichier HTML et retourne la liste des url
    qui contiennent l'expression, la liste des 
    adresses qui n'ont pas pu être atteinte ainsi que le nombre d'adresses
    explorées, cette fonction n'explore pas plus de 
    nbmax pages sauf si nbmax == -1"""
    
    res     = []
    error   = []

    # création d'une classe qui va parcourir le fichier XML
    adr     = [(0, url)]
    text    = []
    errfile = 0
    nb      = 0
    
    for niv,url in adr :

        nb     += 1
        if nb > nbmax and nbmax >= 0 : break
        whole   = ""
        print "open %d/%d" % (nb,len (adr)), 
        print " found = ", len (res), " -- ", niv, " : ", url

        try :
            f       = urllib.urlopen (url)
            d       = f.read ()
            whole  += d
        except Exception, exc:
            print "    exception lecture ", exc, "\t -- ", url
            error.append (url)
            continue 
            
        try :
            text    = []
            p       = HTML_explore (adr, text, url, niv+1, niveau_max)
            # on lit le fichier file ligne par ligne,
            # chaque ligne est envoyée au parser XML 
            p.feed (whole)
            p.close ()
            
            t = ""
            for s in text : t += s + " "
            t = t.replace ("\n", " ")
            t = t.replace ("\r", " ")
            if exp.match (t) : res.append (url)
                
        except Exception, exc:
            print "    exception html ", exc, exc.__class__, "\t -- ", url
            error.append (url)
            f = open ("c:\\temp\\html_err" + str (errfile) + ".html", "w")
            f.write (whole)
            f.close ()
            errfile += 1
            continue 
    
    return res, error, len (adr)
        
    

if __name__ == "__main__" :
    # choix d'un nom de fichier
    url         = "http://www.lemonde.fr/"
    # on appelle la fonction process_file pour récupérer les informations
    # inscrites dans le fichier XML
    s               = ".*Bush.*"
    ex              = re.compile (s, re.IGNORECASE)
    li,error,nb     = process_file (url, ex, 3, -10)
    
    print "--------------------------------------------------------------------"
    print "--------------------------------------------------------------------"
    print "nombre d'adresses explorées :\t", nb
    print "nombre d'adresses sélectionnées :\t", len (li)
    print "nombre d'adresses non ouvertes ou mal lues :\t", len (error)
    print "--------------------------------------------------------------------"
    print "--------------------------------------------------------------------"
    if len (li) > 0 :
        print "url contenant l'expression ", s
        for l in li :
            print " --------- " , l

    if len (error) > 0 :
        print "url n'ayant pas pu être ouverts ou mal lus "
        for l in error :
            print " --- erreur ", l

recherche de mot-clés sur Internet (2)

# coding: cp1252
"""recherche de mot-clés dans des pages HTML, 
ce programme ne peut lire pour l'instant que le format HTML 2.0
et pas HTML 4.01, format utilisé par la plupart des sites."""

import HTMLParser       # parcourir un fichier HTML
import re
import markupbase

starttagopen = re.compile('<[a-zA-Z]')

attrfind = re.compile(
    r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*'
    r'(\"[a-z]+\"#[a-zA-Z.  ]+[.][a-zA-Z]+|\"[0-9]+\"\"|\'[^\']*\'|"[^"]*"'\
     '|([a-zA-Z_:.]+\s*\([0-9/a-zA-Z\"\',.  &;éèàùûâêîô\-_\?:!=@]*\))'\
     '(;void\(0\);)?|\"\"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~]*))?')

# si locatestarttagend est modifié, il faut penser à modifier
# également attrfind
locatestarttagend = re.compile(r"""
  <[a-zA-Z][-.a-zA-Z0-9:_]*          # tag name
  (?:\s+                             # whitespace before attribute name
    (?:[a-zA-Z_][-.:a-zA-Z0-9_]*     # attribute name
      (?:\s*=\s*                     # value indicator
        (?:([a-zA-Z_:.]+\s*\([0-9/a-zA-Z\"',.  &;éèàùûâêîô\-_\?:!=@]*\))(;void\(0\);)? #                
          |\"[0-9]+\"\"              # colspan = "2""
          |\"[a-z]+\"\#[a-zA-Z.  ]+[.][a-zA-Z]+   # "rect"#Le Monde.fr
          |\"\"                      # alt = ""
          |\"[^\"]*\"                # LIT-enclosed value
          |'[^']*'                   # # LITA-enclosed value
          |[^'\">\s]+                # bare value
         )
       )?
     )
   )*
  \s*                                # trailing whitespace
""", re.VERBOSE)

entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
charref = re.compile('&#@(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]')
incomplete = re.compile('&[a-zA-Z#]')

commentclose = re.compile(r'--\s*>|/\s*>|-- /\s*>|-\s*>')


class HTMLParserScript (HTMLParser.HTMLParser) :
    
    def parse_comment(self, i, report=1):
        rawdata = self.rawdata
        #assert rawdata[i:i+4] == '<!--', 'unexpected call to parse_comment()'
        match = commentclose.search(rawdata, i+4)
        if not match:
            print "-------------------------------------------------------"
            print rawdata[i:i+250]
            print "-------------------------------------------------------"
            print end
            print "-------------------------------------------------------"
            return -1
        if report:
            j = match.start()
            self.handle_comment(rawdata[i+4: j])
        j = match.end()
        return j
        
    def _scan_name(self, i, declstartpos):
        rawdata = self.rawdata
        n = len(rawdata)
        if i == n:
            return None, -1
        m = markupbase._declname_match(rawdata, i)
        if m:
            s = m.group()
            name = s.strip()
            if (i + len(s)) == n:
                return None, -1  # end of buffer
            return name.lower(), m.end()
        else:
            self.updatepos(declstartpos, i)
            print "-------------------------------------------------------"
            print rawdata[i:i+250]
            print "-------------------------------------------------------"
            print end
            print "-------------------------------------------------------"
            self.error("expected name token")
            
    def parse_starttag(self, i):
        self.__starttag_text = None
        endpos = self.check_for_whole_start_tag(i)
        if endpos < 0:
            return endpos
        rawdata = self.rawdata
        self.__starttag_text = rawdata[i:endpos]

        # Now parse the data between i+1 and j into a tag and attrs
        attrs = []
        match = HTMLParser.tagfind.match(rawdata, i+1)
        assert match, 'unexpected call to parse_starttag()'
        k = match.end()
        self.lasttag = tag = rawdata[i+1:k].lower()

        while k < endpos:
            m = attrfind.match(rawdata, k)
            if not m:
                break
            attrname, rest, attrvalue = m.group(1, 2, 3)
            if not rest:
                attrvalue = None
            elif attrvalue[:1] == '\'' == attrvalue[-1:] or \
                 attrvalue[:1] == '"' == attrvalue[-1:]:
                attrvalue = attrvalue[1:-1]
                attrvalue = self.unescape(attrvalue)
            attrs.append((attrname.lower(), attrvalue))
            k = m.end()

        end = rawdata[k:endpos].strip()
        if end not in (">", "/>"):
            lineno, offset = self.getpos()
            if "\n" in self.__starttag_text:
                lineno = lineno + self.__starttag_text.count("\n")
                offset = len(self.__starttag_text) \
                         - self.__starttag_text.rfind("\n")
            else:
                offset = offset + len(self.__starttag_text)
            print "-------------------------------------------------------"
            print rawdata[i:i+250]
            print "-------------------------------------------------------"
            print end
            print "-------------------------------------------------------"
            self.error("junk characters in start tag: %s"
                       % `rawdata[k:endpos][:20]`)
        if end.endswith('/>'):
            # XHTML-style empty tag: <span attr="value" />
            self.handle_startendtag(tag, attrs)
        else:
            self.handle_starttag(tag, attrs)
            if tag in self.CDATA_CONTENT_ELEMENTS:
                self.set_cdata_mode()
        return endpos
        
    def check_for_whole_start_tag(self, i):
        rawdata = self.rawdata
        m = locatestarttagend.match(rawdata, i)
        if m:
            j = m.end()
            next = rawdata[j:j+1]
            if next == ">":
                return j + 1
            if next == "/":
                if rawdata.startswith("/>", j):
                    return j + 2
                if rawdata.startswith("/", j):
                    # buffer boundary
                    return -1
                # else bogus input
                self.updatepos(i, j + 1)
                self.error("malformed empty start tag")
            if next == "":
                # end of input
                return -1
            if next in ("abcdefghijklmnopqrstuvwxyz=/"
                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
                # end of input in or before attribute value, or we have the
                # '/' from a '/>' ending
                return -1
            #if next in "'" :
            #    return -1
            print "------------------------------------"
            print next
            print m.groups ()
            print "------------------------------------"
            print rawdata [i: i + 250]
            print "...................................."
            print rawdata [j: j + 30]
            self.updatepos(i, j)
            self.error("malformed start tag")
        raise AssertionError("we should not get here!")
        
    def goahead(self, end):
        if not self.__dict__.has_key ("_script") :
            self._script    = False         # ajout
            self._nb_script = 0             # ajout
        rawdata = self.rawdata
        i = 0
        n = len(rawdata)
        while i < n:
            match = self.interesting.search(rawdata, i) # < or &
            if match:
                j = match.start()
            else:
                j = n
            if i < j: self.handle_data(rawdata[i:j])
            i = self.updatepos(i, j)
            if i == n: break
            startswith = rawdata.startswith

            if self._script :                           # ajout
                if startswith('</script>', i):          # ajout
                    k = i + len ('</script>')           # ajout
                    self._script = False                # ajout
                    i = self.updatepos(i, k)
                elif startswith('</SCRIPT>', i):       # ajout
                    k = i + len ('</SCRIPT>')           # ajout
                    self._script = False                # ajout
                    i = self.updatepos(i, k)
                else:
                    k = i + 1
                    i = self.updatepos(i, k)
            elif startswith('<', i):
                if startswith("<script", i):
                    self._nb_script += 1
                    k = i + len ("<script")
                    self._script = True
                elif startswith("<SCRIPT", i):
                    self._nb_script += 1
                    k = i + len ("<SCRIPT")
                    self._script = True
                elif starttagopen.match(rawdata, i): # < + letter
                    k = self.parse_starttag(i)
                elif startswith("</", i):
                    k = self.parse_endtag(i)
                elif startswith("<!--", i):
                    k = self.parse_comment(i)
                elif startswith("<!-", i):
                    k = self.parse_comment(i)
                elif startswith("<!/", i):
                    k = self.parse_comment(i)
                elif startswith("<!-- /", i):
                    k = self.parse_comment(i)
                elif startswith("<?", i):
                    k = self.parse_pi(i)
                elif startswith("<!", i):
                    k = self.parse_declaration(i)
                elif (i + 1) < n:
                    self.handle_data("<")
                    k = i + 1
                else:
                    break
                if k < 0:
                    if end:
                        print "######################################### (1)"
                        print rawdata [i:i+250]
                        self.error("EOF in middle of construct")
                    break
                i = self.updatepos(i, k)
            elif startswith("&#", i):
                match = charref.match(rawdata, i)
                if match:
                    name = match.group()[2:-1]
                    self.handle_charref(name)
                    k = match.end()
                    if not startswith(';', k-1):
                        k = k - 1
                    i = self.updatepos(i, k)
                    continue
                else:
                    break
            elif startswith('&', i):
                match = entityref.match(rawdata, i)
                if match:
                    name = match.group(1)
                    self.handle_entityref(name)
                    k = match.end()
                    if not startswith(';', k-1):
                        k = k - 1
                    i = self.updatepos(i, k)
                    continue
                match = incomplete.match(rawdata, i)
                if match:
                    # match.group() will contain at least 2 chars
                    if end and match.group() == rawdata[i:]:
                        print "######################################### (2)"
                        print rawdata [i:i+250]
                        self.error("EOF in middle of entity or char ref")
                    # incomplete
                    break
                elif (i + 1) < n:
                    # not the end of the buffer, and can't be confused
                    # with some other construct
                    self.handle_data("&")
                    i = self.updatepos(i, i + 1)
                else:
                    break
            else:
                assert 0, "interesting.search() lied"
        # end while
        if end and i < n:
            self.handle_data(rawdata[i:n])
            i = self.updatepos(i, n)
        self.rawdata = rawdata[i:]

fond d'écran

"""panorama avec images"""
import pygame
import os
import time
from PIL import Image
import random

def attendre_touche () :
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONUP : return "clic"
        elif event.type == pygame.KEYDOWN : 
            if event.key == 275 : return "right"
            elif event.key == 276 : return "left"
            elif event.key == 273 : return "up"
            elif event.key == 274 : return "down"
            elif event.key == 27 : return "quit"
            elif event.key == 32 : return "pause"
            else :
                pass
                #print "key ", event.key
        else :
            #print event
            pass
    return ""
       

def get_image_list (dir = ".") :
    li = os.listdir (dir)
    res = []
    for l in li :
        s = l.lower ()
        if "jpg" in s or "png" in s or "jpeg" in s :
            res.append (l)
    res.sort ()
    return res
    
def image_resize (im, size, pil = True) :
    s = im.get_size ()
    rapx = float (size [0]) / s [0]
    rapy = float (size [1]) / s [1]
    
    rap = min (rapx, rapy)
    rap = min (rap, 2.0)
    
    size2 = ( int (s [0] * rap), int (s [1] * rap) )
    
    if not pil :
        res = pygame.transform.scale (im, size2)
    else :
        # scale from pygame is not good, use PIL's one
        s = pygame.image.tostring (im, "RGBX")
        temp = Image.fromstring ("RGBX", im.get_size (), s)
        tu = (0,0, im.get_size () [0]-1, im.get_size () [1] - 1)
        temp = temp.transform (size2, Image.EXTENT,  tu, Image.BICUBIC)
        mode = temp.mode
        size = temp.size
        data = temp.tostring()
        res = pygame.image.fromstring (data, size, mode)    
    return res
    
def load_image (file) :
    try :
        im = pygame.image.load (file)
    except Exception, e :
        print "unable to load image ", file, " error ", e
        return None
    return im
    
def display (sur, im) :
    im = image_resize (im, sur.get_size ())
    sur.fill ( (0,0,0) )
    
    x = (sur.get_size () [0] - im.get_size () [0]) / 2
    y = (sur.get_size () [1] - im.get_size () [1]) / 2
    
    sur.blit (im, (x,y))
    
def loop (sur, li, d = 500, rnd = True, transition = True) :
    
    already = { }
    for i in range (0, len (li)) : already [i] = - len (li) 
    
    print "number of images ", len (li)
    lo = 0
    i = 0
    while i < len (li) or rnd :
        
        lo += 1
        if rnd : 
            i = random.randint (0, len (li)-1)
            while lo - already [i]  < len (li) / 2 :
                i = random.randint (0, len (li)-1)
        im = li [i]
        already [i] = lo
        
        
        ti = pygame.time.get_ticks ()
        
        s = load_image (im)
        if s == None : continue
            
        display (sur, s)
        
        if not transition :
            pygame.display.flip ()
        else :
            ts = sur.get_size ()
            for i in xrange (0, ts [0], 20) :
                r = pygame.Rect (i, 0, i+100, ts [1])
                pygame.display.update (r)
                pygame.time.delay (10)
        
        
        ti = ti - pygame.time.get_ticks ()
        
        ti = max (0, d - ti)
        pygame.time.delay (ti)
        
        if pygame.event.peek () :
            t = attendre_touche ()
            if t == "quit" : return 
            elif t == "left" : i -= 1
            elif t == "right" : i += 1
            elif t == "up" : i += 10
            elif t == "down" : i += 10
            elif t == "pause" :
                while attendre_touche () != "pause" :
                    pass
        i += 1
        i = max (i, 0)
        
    print "stop at ", i
            
    
if __name__ == "__main__" :
    li = get_image_list ()
    
    pygame.init ()
    pygame.display.set_mode ((1280,800), pygame.FULLSCREEN)
    #pygame.display.set_mode ((1280,800)) #, pygame.FULLSCREEN)
    s = pygame.display.get_surface ()
    
    loop (s, li)

    pygame.time.delay (1000)

popularité avec des moteurs de recherche

#!/usr/bin/python
# coding: latin-1
import urllib
 
from recherche_voila_popularite import *


class Acteur :
    def __init__ (self, nom, prenom, age, nationalite, sexe) :
        self.nom            = nom
        self.prenom         = prenom
        self.age            = age
        self.nationalite    = nationalite
        self.sexe           = sexe
        
        s = "\"" + prenom + " " + nom + "\""
        self.voila          = combien_voila (s)
        self.bing           = combien_bing (s)
        self.ebay           = combien_ebay (s)
        
    def liste_compteur (self) :
        return [ self.voila, self.bing, self.ebay ]
        
print "commencement"        
act = []
act.append ( Acteur ("foster", "jodie", 40, "us", "f") )
act.append ( Acteur ("depardieu", "gerard", 55, "fr", "h") )
act.append ( Acteur ("deneuve", "catherine", 60, "fr", "f") )
act.append ( Acteur ("harrison", "ford", 60, "us", "h") )
if False :  # False pour corriger le programme plus rapidement, True sinon
    act.append ( Acteur ("redford", "robert", 60, "us", "h") )
    act.append ( Acteur ("depp", "johnny", 40, "us", "h") )
    act.append ( Acteur ("eastwoord", "clint", 75, "us", "h") )
    act.append ( Acteur ("sarandon", "susan", 60, "us", "f") )
    act.append ( Acteur ("dunst", "kirsten", 20, "us", "f") )
    act.append ( Acteur ("portman", "nathalie", 25, "us", "h") )
    act.append ( Acteur ("roberts", "julia", 40, "us", "f") )
    act.append ( Acteur ("tautou", "audrey", 30, "fr", "f") )
    act.append ( Acteur ("cotillard", "marion", 30, "fr", "f") )
    act.append ( Acteur ("binoche", "juliette", 40, "fr", "f") )
    act.append ( Acteur ("berry", "richard", 50, "fr", "h") )
    act.append ( Acteur ("bruel", "patrick", 45, "fr", "h") )

def ajoute_liste (l1, l2) :
    for i in range (0, len (l1)) :
        l1 [i] += l2 [i]
    
def divise_liste (l1, s) :
    for i in range (0, len (l1)) :
        l1 [i] /= s
    

# france contre etats - unis
fr = [ 0,0,0 ]
us = [ 0,0,0 ]
nb_fr = 0
nb_us = 0
for a in act :
    print "cherche ", a.nom,
    l = a.liste_compteur ()
    print l
    if a.nationalite == "fr" :
        nb_fr += 1
        ajoute_liste (fr, l)
    if a.nationalite == "us" :
        nb_us += 1
        ajoute_liste (us, l)

divise_liste (us, nb_us) 
divise_liste (fr, nb_fr) 

print "------------------------------"
print "compteur nb_us = ", nb_us, " nb_fr : ", nb_fr
for i in range (0, len (us)) :
    print "us : ", us [i], " \t fr : ", fr [i]

# homme contre femme
f = [ 0,0,0 ]
h = [ 0,0,0 ]
nb_f = 0
nb_h = 0
for a in act :
    print "cherche ", a.nom,
    l = a.liste_compteur ()
    print l
    if a.sexe == "f" :
        nb_f += 1
        ajoute_liste (f, l)
    if a.sexe == "h" :
        nb_h += 1
        ajoute_liste (h, l)

divise_liste (h, nb_h) 
divise_liste (f, nb_f) 

print "------------------------------"
print "compteur nb_h = ", nb_h, " nb_f : ", nb_f
for i in range (0, len (us)) :
    print "h : ", h [i], " \t f : ", f [i]


occurrences dans une liste

# question 2
def lit_fichier (file) :
    f = open (file, "r")  # ouverture du fichier en mode lecture "r"
    li = f.readlines ()     # lecture des lignes du fichier texte
    f.close ()               # fermeture du fichier, l'acces est libre pour d'autres applications
    
    # on enleve les separateurs de fin de lignes, 
    # caracteres invisibles qui permettent aux editeurs de texte (Scite, Notepad) 
    # de se retrouver dans les lignes
    res = []
    for l in li :
        s = l.replace ("\n", "")
        res.append (s)
    return res
    
# question 3
def compte_A (li) :
    nb = 0
    for l in li :
        if l [0] == "A" : nb += 1
    return nb
    
# question 4
def compte (li, lettre) :
    nb = 0
    for l in li :
        if l [0] == lettre : nb += 1
    return nb
    
# question 5
def compte_toute (li) :
    alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    res = []
    for a in alpha :
        n = compte (li, a)
        res.append (n)
    return res
    
# question 6
def compte_dico (li) :
    res = { }
    for l in li :
        a = l [0]
        if a in res : res [a] += 1
        else : res [a] = 1
    return res
    
    
lis = lit_fichier ("td_note_texte.txt")

a = compte_A (lis)
print a  # donne 65

a = compte (lis, "A")
print a  # donne 65

all = compte_toute (lis) 
print len (all), all # affiche 26 [65, 16, 69, 46, 53, 39, ...

res = compte_dico (lis)
print res  # {'A': 65, 'C': 69, 'B': 16, 'E': 53,  ...

# question 7
"""
cout fonction compte_toute : 26 * cout fonction compte = 26 * longueur de la liste
cout fonction compte_dico :    longueur de la liste * cout recherche dichotomique 
                                       = longueur de la liste * ln(26)/len(2)
"""

# question 8
def compte_8 (li) :
    res = [ ]
    nb = 1
    le = li [0][0]
    for i in range (1, len (li)) :
        if li [i][0] != li [i-1][0] :
            res.append ( (le, nb) )
            nb = 1
            le = li [i][0]
        else : 
            nb += 1
    res.append ( (le, nb) )
    return res
    
res = compte_8 (lis)
print res  # [('A', 65), ('B', 16), ('C', 69), ('D', 46), ('...
    


star

# question 1,2
#
# extrait du fichier une matrice de n lignes et deux colonnes
# separateur de ligne \n
# separateur de colonne \t
#
def lit_fichier (file) :
    f = open (file, "r")
    li = f.readlines ()   # separation en lignes
    f.close ()
    
    mat = []
    for l in li :
        s = l.replace ("\n", "")
        s = s.split ("\t")  # separation en colonne
        if len (s) == 2 :
            # ce test est ajoute pour verifier qu'on ajoute pas 
            # des lignes vides dans la matrice
            # les lignes vides ne contiennent pas de separateur \t 
            # et ne contiennent qu'une colonne
            mat.append (s)
    return mat
    
# question 3    
def prenom_frequent (mat) :
    # les prenoms sont en colonne 0
    res = { }
    for i in range (0, len (mat)) :
        p = mat [i][0]
        if p in res : res [p] += 1
        else : res [p] = 1
            
    # on recherche le maximum : maximum sur toutes les valeurs
    mx = max ( res.values () )
    
    # on recherche tous les prenoms qui sont aussi frequent que mx
    freq = []
    for p in res :
        if res [p] == mx : freq.append (p)
            
    return freq,mx
    
# question 4
def family_group (mat) :
    # on choisit de representer les familles sont la forme d'un dictionnaire de listes
    # cle : parents (colonne 1 de mat)
    # valeur : liste de prenoms (colonne 0 de mat)
    res = { }
    for i in range (0, len (mat)) :
        pr = mat [i][0]
        pa = mat [i][1]
        if pa in res : res [pa].append (pr) # on ajoute le prenom a la liste
        else : res [pa] = [ pr ]   # liste d'un seul prenom
    return res
    
# question 5
def moyenne_mediane (dico) :
    # on repart du resultat de la fonction family_group
    # et on construit la liste des tailles de familles
    taille = []
    for pa in dico :
        taille.append ( len (dico [pa] ) )
    
    moyenne = float (sum (taille)) / len (taille)
    taille.sort ()
    mediane = taille [ len (taille) / 2 ]
    return moyenne, mediane
    
# test    
mat = lit_fichier ("star.txt")
freq,mx = prenom_frequent (mat)
print "prenom frequents ", freq
print "present ", mx, " fois"
fam = family_group (mat)
moyenne, mediane = moyenne_mediane (fam)
print "moyenne ", moyenne, " mediane ", mediane

for pa in fam :
    print pa
    for pr in fam [pa] :
        print "    ", pr
        

tri classique


def tri(l):
    """effectue le tri classique : 
    on recherche le minimum, on le place en premiere
    position et on recommence avec les elements restant"""
    for k in range (0,len (l)-1) :
        # recherche du minimum
        p = k
        for n in range (k+1, len (l)) : 
            if l [n] < l [p] :
                p = n
        # echange
        ech     = l [k]
        l [k]     = l [p]
        l [p]     = ech

k=[2,8,9,5,15,4,56,78,85,15,45,3]
print "non triee ", k
tri(k)
print "triee ",k


tri fusion

def fusion(a,b):
    """fonction fusionnant les deux listes a,b supposees triees,
    retourne une liste triee.
    
    a chaque passage dans la boucle, on ajoute un element
    provenant de l'une des deux listes, on conserve pour ces 
    deux listes l'indice de l'element suivant a inserer 
    dans la liste resultat : k pour la liste a, n pour la liste b
    
    a chaque passage, on choisit le plus petit, 
       si c'est celui de la liste a, on incremente k,
       si c'est celui de la liste b, on incremente n
       
       il faut faire attention lorsqu'on a ajouter les elements d'une liste,
       parce que l'indice k ou n ne designe aucun element, de plus,
       cela signifie qu'on doit ajouter les derniers elements
       de l'autre liste.
    """
    c=[]
    l=len(a)+len(b)
    k=0
    n=0
    while len(c)<l:
        if k==len(a):     # liste a terminee
            c.extend (b[n:])
        elif n==len(b):   # liste b terminee
            c.extend(a[k:])
        elif a[k]<b[n]:   # element de la liste plus petit
            c.append(a[k])
            k=k+1
        else :            # element de la liste b plus petit
            c.append(b[n])
            n=n+1
    return c

def tri(l):
    """effectue le tri par fusion, coupe la liste en deux,
    appelle recursivement le tri par fusion sur chacun des
    deux morceaux puis assemble les deux listes triees
    
    le cout de cette fonction depend de n : 
        - fusionner de liste a un cout en O(n)
        - on appelle la fonction fusion sur :
                - le tableau initial : n elements
                - sur deux moities : 2 * n/2
                - sur quarts quarts : 4 * n/4
                - ...
                - sur n/2 sous-liste de 2 elements : n/2 * 2
    le cout du tri par fusion est n * autant de fois
    qu'on peut divisier n par 2 : O(n log (n))"""
    if len(l)>1:
        n=int(len(l)/2)
        a=l[n:len(l)]  # premiere moitie
        b=l[0:n]       # seconde moitie
        tri(a)         # tri de la premier moitie
        tri(b)         # tri de la seconde moitie
        t=fusion(a,b)  # fusion des deux listes triees
        for i in range(0,len(l)):  # on recopie la liste triee dans la 
            l[i]=t[i]              # liste initiale
        # on ne peut pas ecrire que :
        #   l = t
        # car dans ce cas, on sert du nom l pour stocker autre chose
        # que la liste l, cette ligne attribuerait le nom l a une autre liste
        # qui serait perdue a la fin de la fonction

k=[2,8,9,5,15,4,56,78,85,15,45,3]
print "non triee ", k
tri(k)
print "triee ",k

tracé d'une ligne

# coding: cp1252
"""ce module contient la fonction trace_ligne qui retourne l'ensemble des pixels
concernés par le tracé d'une ligne en 8-connexité entre deux pixels"""
import pygame                 # pour les affichages
import random

def trace_ligne_simple (x1,y1,x2,y2):
    """trace une ligne entre les points de coordonnées (x1,y1) et (x2,y2),
    on suppose que x2 > x1, y2 >= y1, 
    retourne la ligne sous la forme d'un ensemble de pixels (x,y)"""
    
    if y2 - y1 <= x2 - x1 :  # droite en dessous de la première bissectrice
        vx = x2 - x1
        vy = y2 - y1
        b  = vx / 2
        y  = y1
        x  = x1
        
        ligne = []
        while x <= x2 :
            ligne.append ((x,y))
            b -= vy
            x += 1
            if b < 0:
                b += vx
                y += 1
        return ligne
    else :                   # droite au dessus de la première bissectrice
        vx = x2 - x1
        vy = y2 - y1
        b  = vy / 2
        y  = y1
        x  = x1
        
        ligne = []
        while y <= y2 :
            ligne.append ((x,y))
            b -= vx
            y += 1
            if b < 0:
                b += vy
                x += 1
        return ligne
    
def trace_ligne (x1,y1,x2,y2):
    """trace une ligne entre les points de coordonnées (x1,y1) et (x2,y2),
    aucune contrainte sur les coordonnées,
    retourne la ligne sous la forme d'un ensemble de pixels (x,y)"""
    
    if x1 == x2 :
        if y1 <= y2: return [ (x1, i) for i in xrange (y1,y2+1) ]
        else : return [ (x1, i) for i in xrange (y2,y1+1) ]
        
    if y1 == y2 :
        if x1 <= x2: return [ (i, y1) for i in xrange (x1,x2+1) ]
        else : return [ (i, y1) for i in xrange (x2,x1+1) ]
    
    if x1 < x2 :
        if y1 < y2 : 
            return trace_ligne_simple (x1,y1,x2,y2)
        else :
            ligne = trace_ligne_simple (x1,y2,x2,y1)
            return [ (x,y1 + y2 - y) for (x,y) in ligne ]
        
    if x2 < x1 :
        if y1 < y2 : 
            ligne = trace_ligne_simple (x2,y1,x1,y2)
            return [ (x1 + x2 - x, y) for (x,y) in ligne ]
        else :
            ligne = trace_ligne_simple (x2,y2,x1,y1)
            return [ (x1 + x2 - x, y1 + y2 - y) for (x,y) in ligne ]

def display_ligne (ligne, screen):
    """affiche une ligne à l'écran"""
    color = 0,0,0
    for p in ligne:
        pygame.draw.line (screen, color, p,p)
    pygame.display.flip ()
    
    
def attendre_clic (screen):
    """attend la pression d'un clic de souris pour continuer"""
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break

if __name__ == "__main__" :
    pygame.init ()
    
    size      = width, height = x,y = 200, 200
    black     = 0, 0, 0
    white     = 255,255,255
    screen    = pygame.display.set_mode(size)
    screen.fill (white)
    
    print trace_ligne (0,0, 7,3)  
    # affiche [(0, 0), (1, 0), (2, 1), (3, 1), (4, 2), (5, 2), (6, 3), (7, 3)]
    
    for n in xrange (0,10):
        x1      = random.randint (0,x-1)        
        y1      = random.randint (0,y-1)        
        x2      = random.randint (0,x-1)        
        y2      = random.randint (0,y-1)        
        ligne   = trace_ligne (x1,y1,x2,y2)
        display_ligne (ligne, screen)

    attendre_clic (screen)

interface graphique avec Tkinter

import Tkinter as T
root = T.Tk ()

# moitie gauche de la fenetre
f1 = T.Frame ()
f1.grid (column = 0, row = 0)

# moitie droite de la fenetre
f2 = T.Frame ()
f2.grid (column = 1, row = 0)

# creation d'une zone de texte dans la moitie gauche (f1)
l1 = T.Label (f1, text = "f(x) = ")
l1.grid (column = 0, row = 0)

# creation d'une zone de texte dans la moitie droite (f2)
lf2 = T.Label (f2, text = "dessin de la fonction")
lf2.grid (column = 0, row = 0)

# creation d'une zone de saisie
fonction = T.Entry (f1)
fonction.grid (column = 1, row = 0)
fonction.insert (0, "x**2 + x * math.cos (x)")

# creation d'une zone de dessin
dessin = T.Canvas (f2, width = 400, height = 400)
dessin.grid (column = 0, row = 1)
dessin.create_line (0,200,400,200, fill = "blue", width = 2)
dessin.create_text (10,210, text = "-5", fill = "black", font = "arial")

# creation d'un bouton quitter
bouton = T.Button (f1, text = "quitter")
bouton.grid (column = 0, row = 6)
bouton.config (command = root.destroy)

# creation d'un autre bouton
bouton = T.Button (f1, text = "dessin")
bouton.grid (column = 0, row = 2)

# on associe le bouton a une fonction
import random
def fonction_bouton_dessin () :
    dessin.create_line (0,0, random.randint (0,400), random.randint (0,400))

bouton.config (command = fonction_bouton_dessin)

root.mainloop ()

File: window.tex, line 43


import math
x = 0
print eval ("math.cos (x) + math.exp (x)")  # affiche 2

interface graphique avec Tkinter

# on importe le module Tkinter avec le pseudonyme T
import Tkinter as T
import math

# on cree la fenetre principale sans l'afficher
# la fenetre est vide, on lui ajoute des elements par la suite
root = T.Tk ()

# taille de l'ecran (carre)
ecran = 400

# moitie gauche de la fenetre
f1 = T.Frame ()
f1.grid (column = 0, row = 0)

# moitie droite de la fenetre
f2 = T.Frame ()
f2.grid (column = 1, row = 0)

# creation d'une zone de texte dans la moitie gauche (f1)
l1 = T.Label (f1, text = "f(x) = ")
l1.grid (column = 0, row = 0)

# creation d'une zone de texte dans la moitie droite (f2)
lf2 = T.Label (f2, text = "dessin de la fonction")
lf2.grid (column = 0, row = 0)

# creation d'une zone de saisie pour la fonction
fonction = T.Entry (f1)
fonction.grid (column = 1, row = 0)
fonction.insert (0, "x**2 + x * math.cos (x)")

# creation d'une zone de dessin
dessin = T.Canvas (f2, width = ecran, height = ecran)
dessin.grid (column = 0, row = 1)

# creation des quatre zones de texte et de saisie
# pour les limitesdu graphiques
lxmin = T.Label (f1, text = "xmin")
lxmax = T.Label (f1, text = "xmax")
lymin = T.Label (f1, text = "ymin")
lymax = T.Label (f1, text = "ymax")
xmin = T.Entry (f1)
xmax = T.Entry (f1)
ymin = T.Entry (f1)
ymax = T.Entry (f1)
lxmin.grid (column = 0, row = 2)
lxmax.grid (column = 0, row = 3)
lymin.grid (column = 0, row = 4)
lymax.grid (column = 0, row = 5)
xmin.grid (column = 1, row = 2)
xmax.grid (column = 1, row = 3)
ymin.grid (column = 1, row = 4)
ymax.grid (column = 1, row = 5)
xmin.insert (0, "-5")
xmax.insert (0, "5")
ymin.insert (0, "-5")
ymax.insert (0, "5")

# creation d'une zone de texte dans la moitie droite (f2)
lcouleur = T.Label (f1, text = "couleur")
lcouleur.grid (column = 0, row = 6)

# creation d'une zone de saisie pour la couleur
couleur = T.Entry (f1)
couleur.grid (column = 1, row = 6)
couleur.insert (0, "blue")

# creation d'un bouton quitter
bouton = T.Button (f1, text = "quitter")
bouton.grid (column = 0, row = 7)
bouton.config (command = root.destroy)

# creation d'un bouton dessiner
bouton = T.Button (f1, text = "dessin")
bouton.grid (column = 1, row = 7)

# dessin de la fonction 
def fonction_bouton_dessin () :

    # on recupere les bornes du graphique converties en reels
    rxmin = float (xmin.get ())
    rxmax = float (xmax.get ())
    rymin = float (ymin.get ())
    rymax = float (ymax.get ())
    
    # on recupere la fonction
    f    = fonction.get ()
    
    # on recupere la couleur
    c    = couleur.get ()
    
    # tout le probleme consiste a convertir des coordonnees
    # reelles en pixels, c'est un changement de repere
    t    = (rxmax - rxmin) / ecran  # un pixel correspond a t
    
    # on va relier les points ( rxmin + n t, f ( rxmin + n t )
    # pour tous les n compris entre 0 et ecran
    x    = rxmin
    
    # tant que x de depasse pas rxmax
    while x <= rxmax :
    
        # on evalue la fonction f
        y  = eval (f)
        
        # on convertit le point (x, f(x)) en pixels (ix, iy)
        ix = int ((x - rxmin) / (rxmax - rxmin) * ecran) 
        iy = ecran - int ((y - rymin) / (rymax - rymin) * ecran) 
        
        if x == rxmin :
            # si c'est le premier point du graphe, 
            dessin.create_line (ix,iy,ix,iy, fill = c, width = 1)
        else :
            # s'il y a deja eu d'autres points traces (ix_, iy_),
            # on les relie a ix, iy
            dessin.create_line (ix_,iy_,ix,iy, fill = c, width = 1)
            
        # on memorise ix,iy dans ix_,iy_
        ix_,iy_ = ix,iy
        
        # on passe au pixel suivant
        x += t
        
# on associe le bouton dessin a la fonction fonction_bouton_dessin
bouton.config (command = fonction_bouton_dessin)

# on lance la fenetre principale
root.mainloop ()

trois objets Tkinter

# coding:latin-1
import Tkinter                          # import du module des interfaces graphiques

# fenêtre principale
root = Tkinter.Tk ()

# on place un label
l = Tkinter.Label (text = "label")      # on crée l'objet
l.pack ()                               # on l'insère dans la fenêtre principale

# on place une zone de saisie
e = Tkinter.Entry ()                    # on crée l'objet
e.pack ()                               # on l'insère dans la fenêtre principale

# on place un bouton
b = Tkinter.Button (text = "bouton")    # on crée l'objet
b.pack ()                               # on l'insère dans la fenêtre principale

# on affiche la fenêtre
root.mainloop ()

File: pendu.tex, line 27


def fonction () :
    # faire quelque chose ici
b.config (command = fonction)

File: pendu.tex, line 35


l.config (text = "nouvel intitulé")  # changer l'intitulé
contenu = e.get ()                   # récupérer le contenu de la zone de saisie

trois objets Tkinter (2)

# coding:latin-1
import Tkinter                          # 
root = Tkinter.Tk ()                    #   
l = Tkinter.Label (text = "label")      # même programme que précédemment
l.pack ()                               # 
e = Tkinter.Entry ()                    # 
e.pack ()                               # 
b = Tkinter.Button (text = "bouton")    # 
b.pack ()                               # 
   
def fonction () :                       #
    contenu = e.get ()                  #
    l.config (text = contenu)           # lignes insérées
b.config (command = fonction)           #

root.mainloop ()                        # même programme que précédemment

trois objets Tkinter (2) (correction)

# coding:latin-1
import Tkinter
root = Tkinter.Tk ()
l = Tkinter.Label (text = "label")
l.pack ()
e = Tkinter.Entry ()
e.pack ()
b = Tkinter.Button (text = "bouton")
b.pack ()

coup = 0
   
def fonction () :
    global coup
    coup += 1
    contenu = e.get ()
    message = "coup " + str (coup) + " saisie " + contenu
    l.config (text = message)
b.config (command = fonction)

root.mainloop ()

jeu du pendu avec Tkinter

# coding:latin-1
import Tkinter

mot_a_trouve = "pendu"
nb_coup      = 0

# dessin de la fenêtre
root = Tkinter.Tk ()

coup = Tkinter.Label ()
coup.pack ()

jeu = Tkinter.Label ()
jeu.pack ()

lettre = Tkinter.Entry ()
lettre.pack ()

b = Tkinter.Button (text = "jouer")
b.pack ()

# fonction pour le pendu
def blanc_souligne (mot, lettres) :
    res = ""
    for m in mot :
        if m in lettres : res += m
        else : res += "_"
    return res
    
def fonction_jouer () :
    global mot_a_trouve
    global nb_coup
    global coup
    global jeu
    global lettre
    
    nb_coup += 1
    m = blanc_souligne (mot_a_trouve, lettre.get ())
    
    if "_" in m :
        coup.config (text = "nombre de coups " + str (nb_coup))
    else :
        coup.config (text = "gagné")
    
    jeu.config (text = m)
    
b.config (command = fonction_jouer)

# root
root.mainloop ()

File: girafe.tex, line 26


import pygame
pygame.init ()    
image  = pygame.image.load ("girage.jpg")
sizeim = image.get_size ()
size   = (sizeim[0]*3, sizeim[1])
screen = pygame.display.set_mode (size)
screen.blit (image, (0,0))
pygame.display.flip () 

File: girafe.tex, line 40


def attendre_clic (screen,x,y):
    while True:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                return None

File: girafe.tex, line 55


import time
time.sleep (0.1)

File: girafe.tex, line 65


son = pygame.mixer.Sound ("bomb.wav")
son.play ()

File: girafe.tex, line 70


son = pygame.mixer.Sound ("bomb.wav")
son.play ()
son = pygame.mixer.Sound ("bomb.wav")
son.play ()

File: girafe.tex, line 79


font = pygame.font.Font ("freesansbold.ttf", 15) 
text = font.render ("message en blanc à la position 100,100", True, (255,255,255))
screen.blit(text, (100,100)) 
pygame.display.flip ()

File: girafe.tex, line 90


def attendre_touche () :
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONUP : return "clic"
        elif event.type == pygame.KEYDOWN : 
            if event.key == 275 : return "right"
            elif event.key == 276 : return "left"
            elif event.key == 273 : return "up"
            elif event.key == 274 : return "down"
            elif event.key == 27 : return "quit"
            else :
                pass
                #print "key ", event.key # on imprime quand on ne connaît pas le code des touches
        else :
            #print event
            pass
    return "" 

jeu avec des girafes

# coding: latin-1
import pygame
import time

def attendre_touche () :
    """cette fonction retourne différente valeur selon la touche pressée :
       - right : pour la flèche droite
       - gauche : pour la flèche gauche
       - up : pour la flèche haut
       - down : pour la flèche bas
       - quit : pour la touche ESC ou ECHAP
       - '' : chaîne vide pour aucune touche pressée
    """
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONUP : return "clic"
        elif event.type == pygame.KEYDOWN : 
            if event.key == 275 : return "right"
            elif event.key == 276 : return "left"
            elif event.key == 273 : return "up"
            elif event.key == 274 : return "down"
            elif event.key == 27 : return "quit"
            else :
                pass
                #print "key ", event.key
        else :
            #print event
            pass
    return ""
       
       
class ImagePosition :
    """chaque image présente sur le disque dur doit être chargée en
    mémoire (self.image), cette image est affichée à l'écran (self.screen),
    à une position donnée (self.pos),
    si cette image est en fait un motif sur fond blanc, on peut préciser
    à l'ordinateur que ce fond blanc doit laisser apparaître le fond de l'écran
    """
    def __init__ (self, image, pos, screen, transparent = False) :
        """initialisation
           - image : nom d'image
           - pos : position ou afficher l'image
           - screen : variable modélisant l'écran
           - transparent : l'image est-elle un motif dont le fond blanc
                           doit être transparent ?
        """
        self.image  = pygame.image.load (image)
        self.x      = pos [0]
        self.y      = pos [1]
        self.screen = screen
        if transparent : 
            # on précise ici que la couleur blanche (255,255,255)
            # doit être transparent
            self.image.set_colorkey ((255,255,255))
        
    def display (self, transparent = False) :
        """affiche l'image à une position donnée sur l'écran"""
        screen.blit (self.image, (self.x, self.y))
        
def affiche (images) :
    """affiche une liste d'image dans l'ordre dans lequel elles
    apparaissent dans la liste"""
    white  = (255,255,255)
    images [0].screen.fill (white) # met tout en blanc avant de dessiner les images
    for i in images :
        i.display ()
        
def deplacer_avion (images, avion, explosion, sounds, limitx) :
    """jeu, sans pression d'aucun touche, l'avion se déplace 
    vers les deux girafes et fait tout exploser, on peut ralentir
    l'approche de l'avion en :
        - pressant les touches de directions
        - en frappant sans s'arrêter et alternativement les touches gauche droite
    """
    pair = 0   # pair : il faut presser la flèche gauche, impair, flèche droite
    tour = 0   # compte le nombre de tour d'attente, sert à réduire 
               # l'impact des touches pressées par le joueur
    
    # séquence de trois instructions affichant le jeu
    affiche (images)    # on affiche le ciel et les girafes
    avion.display ()    # on affiche l'avion
    pygame.display.flip ()  # on rafraîchit l'écran
    
    # on regarde si une touche a été pressée
    t = attendre_touche ()  
    
    # pour afficher le score
    font = pygame.font.Font ("freesansbold.ttf", 15)    
    
    # le jeu s'arrête lorsqu'on presse la touche ECHAP ou si l'avion
    # touche les girafes
    while t != "quit" and avion.x < limitx :
    
        # on compte le nombre de tours
        tour += 1    
        # en fonction de ce nombre de tour, on détermine l'impact d'une 
        # séquence gauche droite
        dx    = max ((400 - tour) / 100, 1)
        
        # si une touche a été pressée, alors :
        if t == "left" : # flèche gauche
            avion.x -= 1
            if pair % 2 == 0 : 
                avion.x -= dx
                pair += 1
                
        elif t == "right" :  # flèche droite
            avion.x += 1
            if pair % 2 == 1 :
                avion.x -= dx
                pair += 1
                
        elif t == "up" :   # flèche haut
            avion.y -= 1
            
        elif t == "down" : # flèche bas
            avion.y += 1
            
            
        # quelque soit la touche pressée, on actualise le jeu
        # c'est la même séquence de trois touches qu'au début de la fonction
        affiche (images)
        avion.display ()
        
        # on affiche le score également à l'écran
        text = font.render ("score " + str (avion.y), True,(255,255,255))
    
        screen.blit(text, (100,100)) 
            
        pygame.display.flip ()
        
        # le programme attend 50 millisecondes avant de continuer
        time.sleep (0.05)
        
        # on déplace l'avion de force
        avion.x += 2
        avion.y += 1
        
        # on regarde si une touche a été pressée
        t = attendre_touche ()
        
    # on est sorti de la boucle : c'est l'explosion
    # on affiche l'image et on rafraîchit l'écran
    explosion.display ()
    pygame.display.flip ()
    
    # on joue quelques sons
    for i in range (0, len (sounds)) :
        sounds [i].play ()
        time.sleep (1.0*i)  # on attend un peu avant de passer au son suivant
                            # il est possible de ne pas attendre et de tous les 
                            # lancer en même temps
                            
    # on rejoue les sons d'explosion 2 fois séparées de 2 secondes
    for i in range (0, 2) :
        sounds [0].play ()
        sounds [1].play ()
        time.sleep (2.0)

    # on affiche le score : plus l'avion descend, meilleur on est
    print "score ", avion.y
    
    # on affiche le score également à l'écran
    text = font.render ("score " + str (avion.y), True,(255,255,255))
    
    screen.blit(text, (100,100)) 
    pygame.display.flip ()
        
    # on attend la pression de la touche ECHAP avant de quitter le programme
    while t != "quit" :
        t = attendre_touche ()
        

if __name__ == "__main__" :
    
    # initialisation du module pygame
    pygame.init ()

    # on récupère la taille de l'image de la girafe
    sizeim = pygame.image.load("girafe.jpg").get_size ()
    
    # on définit la taille de l'écran comme 3 fois plus large que celle de la girafe
    size   = ( sizeim [0] * 3, sizeim [1])
    screen = pygame.display.set_mode (size)
    
    # on définit l'image de l'avion
    avion       = ImagePosition ("avion.PNG", (0,0), screen, True)
    
    # on définit l'image de l'explosion
    explosion   = ImagePosition ("explosion.jpg", (0,0), screen)
    
    # on estime la limite au delà de laquelle l'avion explose
    limitx      = size [0] - sizeim [0] + sizeim [0] / 3 - avion.image.get_size () [0]
        
    # on définit les sons qui doivent être joués à la fin du jeu
    soundname   = ["bomb.wav", "explosion.wav", "explosion2.wav", "missile.wav", "sheep.wav"]
    sounds = []
    for s in soundname :
        try :
            # exception au cas où le son ne pourrait pas être lu
            sounds.append ( pygame.mixer.Sound (s) )
        except Exception, e :
            print "impossible de charger ", s
            print e

    # on construit la liste des images qui doivent être affichées à chaque fois
    images = []
    images.append ( ImagePosition ("ciel.jpg", (0,0), screen) )
    images.append ( ImagePosition ("girafe.jpg", (size [0] - sizeim [0], 0), screen) )
    
    # on joue
    deplacer_avion (images, avion, explosion, sounds, limitx)
    

manipulation de données dans une table

#coding:utf8
"""
@file
@brief  Contains TableFormulaCore.
"""
import copy, os, os.path, sys, datetime, random, math, numpy, locale, codecs, json

from .. import HalLOG, fLOG, str_to_datetime, EXf, EXs, EXw, EXxw, open_excel
from ..database.database_main import Database
fileprint = HalLOG



class TableFormulaCore :
    """
    
    .. requires numpy
    
    This class aims at representating a table, it provides 
    some "SQL like" functionalities such groupby or innerjoin, select, where...
    
    The class provides an easy to go through the row table by converting each row
    in a dictionary { column_name: value } on the run, Example:
    
    @code
    tbl = TableFormulaCore ( ... )
    newtbl = tbl.filter ( lambda v : v["criteria"] == 5 )
    @endcode
    
    see op __init__ for others ways to create a table.
    
    @var    header      list of column names
    @var    values      list of rows (each row contains as many value as the number of columns)
    @var    index       dictionary { column name : position }, changing ``header`` means also changing ``header``.
    
    Example:
    @code
    TableFormula = TableFormulaCore
    
    table = TableFormula ("name d_a d_b d_c#A 1 2 3#A 1.1 2.1 3.1#B 3 4 5".replace(" ", "\t").replace("#","\n"))
    print (table)
    print ("one value 0,1:", table[0,1])


    print ("---------")
    dist = table.get_distinct_values("name")
    for k in sorted(dist) : print ("*%d : %s"%(int(dist[k]),k))
        
    print ("---------")
    table.add_column ( "has_A", lambda v : 1. if "A" in v["name"] else 0. )
    print (table)

    x = 1./3
    print ("------------- smoothing", x)
    table.add_column_smooth("has_A_smooth", lambda v : v["has_A"], [ -1,0,1], [x,x,x] )
    print (table)
        
    print ("--------- filter")
    fil = table.filter ( lambda v : v["d_b"] == 2)
    print (fil)

    print ("--------- random")
    rnd = table.random( 5)
    print (rnd)

    print ("--------- random unique")
    rnd = table.random( 1, True)
    print (rnd)

    print ("--------- filter quantile")
    fil = table.filter_quantile ( lambda v : v["d_b"], 0, 0.4 )
    print (fil)

    print ("--------- aggregate_column")
    total = table.aggregate (lambda v : v["d_c"])
    print (total)
        
    print ("--------- sort")
    table.sort (lambda v: v["d_b"] + v["d_c"] )
    print (table)
        
    print ("--------- union")
    union = table.union (table)
    print (union)
        
    print ("--------- group sum")
    group = table.groupby ( lambda v: v["name"],
                            [ lambda v: v["d_a"],
                              lambda v: v["d_b"] ],
                            [ "name", "sum_d_a", "sum_d_b"] )
    print (group)
      
    print ("--------- group max")
    groupmax = table.groupby ( lambda v: v["name"],
                            [ lambda v: v["d_a"],
                              lambda v: v["d_b"] ],
                            [ "name", "max_d_a", "max_d_b"],
                            [ max, max ] )
    print (groupmax)
    
    print ("--------- group sum with weights")
    group = table.groupby ( lambda v: v["name"],
                            [ lambda v: v["d_a"] ],
                            [ "name", "weight", "sum_d_a"],
                            [ lambda vec,w :  sum(vec) / w ],
                            lambda v : v ["d_b"])

    print ("--------- innerjoin")
    innerjoin = table.innerjoin (group, lambda v : v["name"], 
                                        lambda v : v["name"], "group" )
    print (innerjoin)

    
    print ("------------- extraction")
    ext = table.extract_columns(["name", "d_a"] )
    print (ext)
    
    print ("------------- remove")
    ext = table.remove_columns(["d_a"] )
    print (ext)
    
    print ("------------- todict")
    d = table.todict( lambda v: v["name"], lambda v: v["d_b"], True)
    print (d)
    
    print ("------------- select")
    d = table.select( lambda v: (v["name"], v["d_b"]))
    print (list(d))
    
    print ("------------- use of an index")
    table.create_index( lambda v : (v["name"], v["d_a"]) )
    row = table.get ( ('A', 1.1) )
    print (row)
    value = table.get ( ('A', 1.1), 2 )
    print (value)
    
    print ("------------- multiply_column_by_row_instance ")
    table = TableFormula ("name d_a d_b d_c#A 1 2 3#A 1.1 2.1 3.1#B 3 4 5".replace(" ", "\t").replace("#","\n"))
    table.add_column ("key_add", lambda v:"unique")
    print (table)
    mul = table.multiply_column_by_row_instance ( 
                        lambda v: v["key_add"],
                        lambda v: v["name"])
    print (mul)
 
    if os.path.exists ("BNP.PA.txt") :
        print ("--------------- financial stock")
        table = TableFormula ("BNP.PA.txt", sep=",")
        table.sort( lambda v : v["Date"] )
        print (table[:10])
        
    print ("--------------- groupby_implicit")
    table = TableFormula ("key_name sum_a len_b avg_c#A 1 2 3#A 1.1 2.1 3.1#B 3 4 5".replace(" ", "\t").replace("#","\n"))
    print (table)
    gr = table.groupby_implicit ( lambda v : v ["key_name"] )
    print (gr)

    print ("--------------- covariance")
    values = [ random.random() for i in range(0,100) ]
    values = [ [ x, x + random.random()/2 ] for x in values ]
    tbl = TableFormula ( ["x", "y"], values).values_to_float()
    cov = tbl.covariance ()
    print (cov)
    
    print ("--------------- histogram")
    hist = tbl.histogram (lambda v : (v["x"],1), 10)
    print (hist)

    print ("--------------- histogram")
    hist = tbl.values_to_float().histograms (["x", "y"], 10)
    print (hist)

    print ("--------------- unions of columns")
    hist = tbl.values_to_float().union_columns(["x", "y"])
    print (hist)
    
    
    @endcode
    """
    
    def add_header_if_not_present(filename, header, encoding = None, logFunction = fileprint) :
        """the function checks if the first line contains the column in header
        otherwise, it modifies the file and add them on the first line
        @param      filename        filename
        @param      header          list of column name (all strings)
        @param      encoding        encoding
        @param      logFunction     use this function to log information about what is happening
        """
        if encoding == None :
            with open(filename, "r") as f : firstline = f.readline().strip("\n\r ")
            su = sum ( map (lambda _ : 1 if _ in header else 0, firstline.split("\t") ) )
            if su < len(header)/2.0 :
                fileprint ("add_header_if_not_present: adding header (%f<%f)"  % (su, len(header)/2) + str(header) + " to " + filename + " firstline " + firstline)
                with open(filename, "r") as f : text = f.read()
                text = "\t".join(header) + "\n" + text
                fileprint ("add_header_if_not_present: writing")
                with open(filename,"w") as f : f.write(text)        
                fileprint ("add_header_if_not_present: complete")
        else :
            with open(filename, "r", encoding = encoding) as f : firstline = f.readline().strip("\n\r ")
            su = sum ( map (lambda _ : 1 if _ in header else 0, firstline.split("\t") ) )
            if su < len(header)/2.0 :
                fileprint ("add_header_if_not_present: adding header (%f<%f)"  % (su, len(header)/2) + str(header) + " to " + filename + " firstline " + firstline)
                with open(filename, "r", encoding = encoding) as f : text = f.read()
                text = "\t".join(header) + "\n" + text
                fileprint ("add_header_if_not_present: writing")
                with open(filename,"w", encoding=encoding) as f : f.write(text)        
                fileprint ("add_header_if_not_present: complete")
    add_header_if_not_present = staticmethod(add_header_if_not_present)
    
    def random_split_file (filename, outfileprefix, nb, has_header = True, encoding = None, logFunction = fileprint) :
        """
        split a file in nb buckets by random (lines are sent to a random file as they come)
        @param      filename        filename to split
        @param      nb              number of buckets
        @param      outfileprefix   output files will start with outfileprefix + '%04d.txt' % i
        @param      encoding        encoding
        @param      has_header      the header will be replicated in each created file
        @param      logFunction     to display information
        @return                     list of created files
        """
        firstline = None
        if has_header :
            if encoding == None :
                with open(filename, "r") as f : firstline = f.readline().strip("\n\r ")
            else :
                with open(filename, "r", encoding = encoding) as f : firstline = f.readline().strip("\n\r ")
        
            fileprint ("random_split_file: file %s has header %s" % (filename, firstline))
        
        fileprint ("random_split_file: split %s in %d parts" % (filename, nb))
        fileName = [ outfileprefix + (".%04d.txt" % n) for n in range(0,nb) ]
        nbline   = 0
        
        if encoding == None :
            filesP = [ open(_, "w") for _ in fileName ]
            if firstline != None :
                for _ in filesP : _.write(firstline + "\n")
            with open(filename, "r") as f : 
                line = f.readline()
                if firstline != None : line = f.readline()
                while line != None and len(line) > 0 :
                    h = random.randint(0,nb-1)
                    filesP[h].write (line)
                    line = f.readline()
                    nbline += 1
                    if nbline % 1000000 == 0 : fileprint ("random_split_file: processed %d lines" % nbline)
        else :
            filesP = [ open(_, "w", encoding = encoding) for _ in fileName ]
            if firstline != None :
                for _ in filesP : _.write(firstline + "\n")
            with open(filename, "r", encoding = encoding) as f : 
                line = f.readline()
                if firstline != None : line = f.readline()
                while line != None and len(line) > 0 :
                    h = random.randint(0,nb-1)
                    filesP[h].write (line)
                    line = f.readline()
                    nbline += 1
                    if nbline % 1000000 == 0 : fileprint ("random_split_file: processed %d lines" % nbline)
                
        for _ in filesP : _.close()
        fileprint ("random_split_file: end")
        return fileName
    random_split_file = staticmethod(random_split_file)
        
    def ratio (x,y) : 
        """
        return a ratio between two real values or an empty string if the denominateur is null
        @return   a real of an empty string
        """
        return x*1.0/y if y != 0 else (0 if x == 0 else "")
    ratio = staticmethod(ratio)
    
    def bootstrap (values, function, nbdraws = -1, alpha = 0.05) :
        """
        return a confidence interval for a statistics
        @param      values      values
        @param      function    produces the statistics over a random set of observations chosen in values
        @param      nbdraws     number of draws, if it is equal to -1, is equal to len(values)
        @param      alpha       confidence level
        @return                 average, min, lower bound, higher bound, max
        """
        stat = [ ]
        N    = len(values)-1
        if nbdraws == -1 : nbdraws = len(values)
        for i in range(nbdraws) :
            randset = [ values[ random.randint(0,N) ] for i in range(N+1) ]
            s       = function(randset)
            stat.append(s)
        stat.sort()
        lv = len(stat)
        alpha = alpha/2
        i1 = int(lv * alpha + 0.5)
        i2 = int(lv * (1-alpha) + 0.5)
        i2 = min (i2, len(stat)-1)
        av = sum(stat) / len(stat)
        return av, min(stat), stat[i1], stat[i2], max(stat)
    bootstrap = staticmethod(bootstrap)
    
    def correlation_bicolumn (values, deviations = False, noCenter = False) :
        """
        assume values is a matrix with two columns
        @param          values      2 column matrix
        @param          deviations  if True, returns cor, sigma1, sigma2
        @param          noCenter    if True, do not remove the average before computing the covariance,
                                    it means we assume variables are already centered
        @return                     correlation factor or correlation, sigma1, sigma2 if deviations is True
        """
        if len(values) <= 1 :
            raise ValueError("expecting more than one observation, not %d" % len(values))
            
        mx = 0.
        my = 0.
        vx = 0.
        vy = 0.
        co = 0.
        nb = 0.
        for a,b in values :
            nb += 1
            mx += a
            my += b
            vx += a**2
            vy += b**2
            co += a*b
        mx /= nb
        my /= nb
        vx /= nb
        vy /= nb
        co /= nb
        if not noCenter :
            vx -= mx**2
            vy -= my**2
            co -= mx*my
        vx  = vx**0.5
        vy  = vy**0.5
        v = vx*vy
        if v != 0 : co /= v
        if deviations : return co,vx,vy 
        else : return co
    correlation_bicolumn = staticmethod(correlation_bicolumn)
    
    def _private_getclass (self) :
        """
        the class often creates another class of the same type,
        this function returns the class object
        """
        return self.__class__
    
    def __init__ (self, file, 
                        numeric_column  = [], 
                        sep             = "\t", 
                        encoding        = None,
                        read_n_lines    = -1,
                        sheet           = 0,
                        **options) :
        """
        constructor, it can either take a filename, an object TableFormulaCore,
        a list of columns and values.
        
        @param      file                filename or a list of column names or a dictionary,
                                        file can also be a `pandas DataFrame <http://pandas.pydata.org/pandas-docs/dev/dsintro.html#dataframe>`_.
        @param      numeric_column      depends on file types (see below examples)
        @param      sep                 column separator if file is a filename
        @param      read_n_lines        read the first n lines (or all if it is -1)
        @param      sheet               in case the file is an Excel file, this parameter precises the sheet number or name
        @param      suffix_nb           if True, adds an integer to the column name if it is a duplicate
        
        Example:
        @code
        table = TableFormula ("name d_a d_b d_c#A 1 2 3#A 1.1 2.1 3.1#B 3 4 5"
                             .replace(" ", "\\t").replace("#","\\n"))
        @endcode
        or
        @code
        table = TableFormula ("file.txt", ["nb"])
        @endcode
        or
        @code
        table  = TableFormula (["date", "Y", "Y2", "xl"], values)
        @endcode
        or
        @code
        data = [ { "one":1, "two":2 }, {"two":2.1, "three":3 } ]
        table = TableFormula (data)
        @endcode
        or
        @code
        data = { 1:{ "one":2.3, "two":2.2 }, 2:{"one":2.1, "two":3 }
        table = TableFormula ("__byrow__", data)
        @endcode
        or
        @code
        table = TableFormula ( numpy.matrix ( ... ))
        @endcode
        or
        @code
        table = TableFormula ( numpy.array ( ... ))
        @endcode
        
        @warning In this second case, rows and header are not copied.
        
        """
        if isinstance(file, str) :
            if os.path.exists (file) : 
                self._read_file (file, numeric_column, sep, encoding, read_n_lines, sheet = sheet)
            elif file == "__byrow__" and isinstance (numeric_column, dict) :
                self._fill_by_row(numeric_column)
            else :
                lines = file.split("\n")
                if len(lines) == 1 :
                    raise FileNotFoundError("a file was probably expected but was not found: " + file)
                self._readlines(lines, numeric_column, sep)
                
        elif isinstance(file, list) :
            if len(file) == 0 :
                raise ValueError("empty data and columns are not allowed")
                
            if isinstance(file[0], dict) :
                self.index = { }
                self.values = []
                for row in file :
                    for k,v in row.items() :
                        if k not in self.index : 
                            self.index[k] = len(self.index)
                    
                # we sort the labels to avoid instabilities
                labels = [ k for k,v in self.index.items() ]
                labels.sort()
                self.index = { }
                for l in labels : self.index[l] = len(self.index)
                            
                for row in file :
                    line = [ None for k in self.index ]
                    for k,v in row.items() :
                        line [ self.index[k] ] = v
                    self.values.append(line)
                    
                self.header = [ None for k in self.index ]
                for k,v in self.index.items () :
                    self.header [ v ] = k
                    
                n = len(self.index)
                for row in self.values :
                    while len(row) < n : row.append(None)
                
            elif isinstance (numeric_column, numpy.matrix) :
                self.header = file
                self.index = { }
                for (i,h) in enumerate (self.header) :
                    self.index [h] = i
                self.values = [ [ float(numeric_column[i,j]) \
                                        for j in range(numeric_column.shape[1]) ] \
                                        for i in range(numeric_column.shape[0]) ] 
            elif isinstance (numeric_column, numpy.ndarray) :
                self.header = file
                self.index = { }
                for (i,h) in enumerate (self.header) :
                    self.index [h] = i
                self.values = [ [ float(numeric_column[i,j]) \
                                        for j in range(numeric_column.shape[1]) ] \
                                        for i in range(numeric_column.shape[0]) ] 
            elif isinstance(file[0], list) :
                if len(file) == 1 :
                    self.header = file[0]
                    self.values = file[1:] + numeric_column
                    self.index = { }
                    for (i,h) in enumerate (self.header) :
                        self.index [h] = i
                else :
                    self.header = file[0]
                    self.values = file[1:]
                    self.index = { }
                    for (i,h) in enumerate (self.header) :
                        self.index [h] = i
            elif isinstance (file[0], str) :
                self.header = file
                self.values = numeric_column
                self.index = { }
                for (i,h) in enumerate (self.header) :
                    self.index [h] = i
                    
            else :
                raise RuntimeError ("this case should not happen " + str(type(file[0])))
                
        elif isinstance( file, numpy.matrix) :
            self.header = [ "c%d" % d for d in range(file.shape[1]) ]
            self.index = { }
            for (i,h) in enumerate (self.header) :
                self.index [h] = i
            self.values = [ [ float(file[i,j]) \
                                    for j in range(file.shape[1]) ] \
                                    for i in range(file.shape[0]) ] 
            
        elif isinstance( file, numpy.ndarray) :
            self.header = [ "c%d" % d for d in range(file.shape[1]) ]
            self.index = { }
            for (i,h) in enumerate (self.header) :
                self.index [h] = i
            self.values = [ [ float(file[i,j]) \
                                    for j in range(file.shape[1]) ] \
                                    for i in range(file.shape[0]) ] 
            
        else :
            try :
                import pandas 
            except ImportError :
                raise TypeError("file has an unexpected type: " + str(type(file)))
                    
            if isinstance (file, pandas.DataFrame) :
                def convert(x) : 
                    return None if isinstance(x, float) and numpy.isnan (x) else x
                df = file
                self.header = [ _ for _ in df.columns ]
                hi = 'index'
                while hi in self.header : hi += "_"
                self.header.insert(0,hi)
                self.values = []
                for i,row in enumerate(df.values) :
                    row = [ df.index[i] ] + [ convert(x) for x in row ]
                    self.values.append(row)
                    
                self.index = { }
                for (i,h) in enumerate (self.header) :
                    self.index [h] = i
                    
            else :
                raise TypeError("file has an unexpected type: " + str(type(file)))
            
        unique = { }
        for i,c in enumerate(self.header) : 
            if c in unique : 
                if options.get("suffix_nb",False) :
                    c = "%s_%d" % (c,i)
                    self.header [ i ] = c
                else :
                    raise KeyError("column " + c + " already exists in %s" % str(self.header))
            unique [c] = True
            
    def __add__ (self, other) :
        """do an addition, add values if types are matching
        @param   other      matrix or float or string
        @return             new matrix, keep the header of the first matrix
        """
        if len(self) != len(other) : raise ValueError("both matrices should have the same number of rows")
        if len(self.header) != len(other.header) : raise ValueError("both matrices should have the same number of columns")
        values = []
        for row,rowo in zip (self.values, other.values) :
            r = []
            for a,b in zip(row,rowo) :
                if type(a) == type(b) :
                    x = a + b
                else :
                    x = None
                r.append(x)
            values.append(r)
        return self._private_getclass() (self.header, values )
        
    def __mul__ (self, other) :
        """do a multiplication (by a number)
        @param   other      matrix or float or string
        @return             new matrix, keep the header of the first matrix
        """
        if not isinstance (other, float) and not isinstance (other, int) :
            raise TypeError("other should be a number")
        values = []
        for row in self.values :
            r = []
            for a in row :
                if a != None : x = a * other
                else : x = None
                r.append(x)
            values.append(r)
        return self._private_getclass() (self.header, values )
        
    def multiplication_term_term (self, other) :
        """do a multiplication term by term (similar to an addition), 
        add values if types are matching
        @param   other      matrix or float or string
        @return             new matrix, keep the header of the first matrix
        """
        if len(self) != len(other) : raise ValueError("both matrices should have the same number of rows")
        if len(self.header) != len(other.header) : raise ValueError("both matrices should have the same number of columns")
        values = []
        for row,rowo in zip (self.values, other.values) :
            r = []
            for a,b in zip(row,rowo) :
                if type(a) == type(b) and not isinstance (a, str) :
                    x = a * b
                else :
                    x = None
                r.append(x)
            values.append(r)
        return self._private_getclass() (self.header, values )
        
    def replicate (self, times) :
        """replicates all rows a given number of times
        @param   times      number of multiplication
        @return             new matrix, keep the header of the first matrix
        """
        values = []
        for i in range (0,times) :
            values.extend (copy.copy(self.values))
        return self._private_getclass() (self.header, values )

    @property 
    def size(self) :
        """returns the size (nb rows, nb columns)
        """
        return len(self), len(self.header)
        
    @property
    def shape(self):
        """returns the size (nb rows, nb columns)
        """
        return self.size
        
    def _fill_by_row(self, values) :
        """
        fill the table
        @param      values      dictionary { <int_row_index>: { <column name>: value} }
        """
        mx = max (values.keys())+1
        self.index  = { }
        self.header = []
        for k,v in values.items () :
            for col in v :
                if col not in self.index :
                    self.index[col] = len(self.index)
                    self.header.append (col)
        self.values = [ [ None for h in self.header ] for k in range(mx) ]
        for k,v in values.items () :
            for col,to in v.items() :
                self.values [ k ] [ self.index [col] ] = to

    def __getitem__ (self, irow) :
        """operator [], accepts slices
        @param      irow        integer, tuple, slice or list
        @return                 depends on irow
                                    - int --> a table with one row
                                    - slice --> a table with several rows
                                    - list --> a table with the selected rows
                                    - tuple --> a value
        """
        if isinstance( irow, int ) :
            return self._private_getclass() (self.header, [self.values[irow] ] )
        elif isinstance( irow, slice ) :
            return self._private_getclass() ( self.header,
                    [self.values[ii] for ii in range(*irow.indices(len(self)))])
        elif isinstance( irow, list ) :
            return self._private_getclass() ( self.header, [self.values[ii] for ii in irow])
        elif isinstance (irow, tuple) :
            if isinstance(irow[1], str) :
                row = self.values[irow[0]]
                v = self._interpret_row(row)
                return v [irow[1]]
            else :
                return self.values[irow[0]][irow[1]]
        else:
            raise TypeError ("Invalid argument type: " + str(type(irow)))
           
    def __setitem__ (self, irow, value) :
        """operator [], just accepts tuple (to change a value)
        @param      irow        2-uple
        @param      value       new value
        """
        if isinstance (irow, tuple) :
            if isinstance(irow[1], str) :
                row = self.values[irow[0]]
                v = self._interpret_row(row)
                v [irow[1]] = value
            else :
                self.values[irow[0]][irow[1]] = value
        else:
            raise TypeError ("Invalid argument type (only tuple accepted): " + str(type(irow)))
           
    def __len__ (self) :
        """returns the number of rows
        """
        return len(self.values)
            
    def __copy__ (self) :
        """operator copy
        """
        return self._private_getclass() (self.header, self.values)
        
    def __deepcopy__ (self, memo) :
        """operator deepcopy
        """
        return self._private_getclass() (copy.deepcopy (self.header, memo),
                                         copy.deepcopy(self.values, memo))
    
    def copy(self) :
        """call copy.deepcopy(self)
        """
        return copy.deepcopy(self)
        
    def delta (self, other) :
        """
        returns a list of differences between self and others
        
        @param      other       TableFormula
        @return                 list of differences (first one)
        """
        if other == None : return False
        if not isinstance (other, TableFormulaCore) : 
            raise TypeError("other is not a table: " + str(type(other)))
        if len(self.header) != len(other.header) : 
            return [ "different number of columns" ]
        for a,b in zip (self.header, other.header) :
            if a != b : return [ "different columns"]
        if len(self.values) != len(other.values) : 
            return ["different number of rows" ]
        line = 0
        for r,s in zip (self.values, other.values) :
            if len(r) != len(s) : 
                return ["different number of values on row %d" % line ]
            col = 0
            for a,b in zip (r,s) :
                if a != b : 
                    return ["different value on cell %d,%d: %s!=%s (type %s, %s)" % (line, col, a,b, str(type(a)), str(type(b))) ]
                col += 1
            line += 1
        return []   
        
    def __eq__ (self, other) :
        """
        check if two tables are equal by value
        @param      other       other table
        @return                 boolean
        """
        if other == None : 
            return False
        if not isinstance (other, TableFormulaCore) : 
            return False
        if len(self.header) != len(other.header) : 
            return False
        for a,b in zip (self.header, other.header) :
            if a != b : 
                return False
        if len(self.values) != len(other.values) : 
            return False
        for r,s in zip (self.values, other.values) :
            if len(r) != len(s) : 
                return False
            for a,b in zip (r,s) :
                if a != b : 
                    return False
        return True
        
    def __str__ (self) :
        """
        convert the table into a string
        @return     string
        """
        rows = [ "\t".join (self.header) ]
        for row in self.values :
            s = "\t".join ( [ str(_) for _ in row ] )
            rows.append (s)
        return "\n".join(rows)
        
    def __html__ (self, class_table = None, class_td = None, class_tr = None, class_th = None) :
        """
        convert the table into a html string
        
        @param  class_table     adds a class to the tag ``table`` (None for none)
        @param  class_td        adds a class to the tag ``td`` (None for none)
        @param  class_tr        adds a class to the tag ``tr`` (None for none)
        @param  class_th        adds a class to the tag ``th`` (None for none)
        """
        clta = ' class="%s"' % class_table  if class_table != None else ""
        cltr = ' class="%s"' % class_tr     if class_tr != None else ""
        cltd = ' class="%s"' % class_td     if class_td != None else ""
        clth = ' class="%s"' % class_th     if class_th != None else ""
        
        rows= [ "<table%s>" % clta ]
        rows.append (  ("<tr%s><th%s>" % (cltr, clth)) + ("</th><th%s>" % clth).join (self.header) + "</th></tr>" )
        septd = "</td><td%s>" % cltd
        strtd = "<tr%s><td%s>" % (cltr, cltd)
        for row in self.values :
            s = septd.join ( [ str(_) for _ in row ] )
            rows.append ( strtd + s + "</td></tr>")
        rows.append ("</table>")
        rows.append("")
        return "\n".join(rows)
        
    def __rst__ (self, add_line = True):
        """
        convert the table into rst format
        @code
        +------------------------+------------+----------+----------+
        | Header row, column 1   | Header 2   | Header 3 | Header 4 |
        | (header rows optional) |            |          |          |
        +========================+============+==========+==========+
        | body row 1, column 1   | column 2   | column 3 | column 4 |
        +------------------------+------------+----------+----------+
        | body row 2             | ...        | ...      |          |
        +------------------------+------------+----------+----------+        
        @endcode
        
        @param      add_line        add a line separator between each row
        """
        tbl     = self.values_to_str()
        length  = [ len(_) for _ in tbl.header ]
        for row in tbl.values :
            for i,v in enumerate(row) :
                length[i] = max ( length[i], len(v) )
        length = [ _+ 2 for _ in length ]
        line   = [ "-" * l for l in length ]
        lineb  = [ "=" * l for l in length ]
        sline  = "+%s+" % ("+".join(line))
        slineb = "+%s+" % ("+".join(lineb))
        res    = [ sline ]
        
        def complete(cool) :
            s,i = cool
            i -= 2
            if len(s) < i : s += " " * (i-len(s))
            return s
        
        res.append ( "| %s |" % " | ".join (map (complete, zip(tbl.header, length)) ) )
        res.append (slineb)
        res.extend ( [ "| %s |" % " | ".join ( map(complete, zip(row,length) )) for row in tbl.values ] )
        if add_line :
            t = len(res)
            for i in range(t-1,3,-1) : 
                res.insert(i, sline)
        res.append (sline)
        return "\n".join(res) + "\n"
        
    def strtype (self) :
        """displays the type of values (not the values)
        """
        rows = [ "\t".join (self.header) ]
        for row in self.values :
            s = "\t".join ( [ str(type(_)) for _ in row ] )
            rows.append (s)
        return "\n".join(rows)
        
    def _read_file (self, file, numeric_column, sep, encoding, read_n_lines, sheet = 0) :
        """
        private
        """
        ext = os.path.splitext(file)[-1].lower()
        if ext in [".xls", ".xlsx"] :
            lines = list( open_excel(file, sheet = sheet ))
            # removing empty column (assuming first row is the header)
            ind = [ i for i,n in enumerate(lines[0]) if len(n) > 0 ]
            if len(ind) < len(lines[0]) :
                lines = [  [ _[i] for i in ind  ] for _ in lines ]
        else :
            if sys.version_info.major >= 3 or encoding == None :
                if encoding == None : f = open (file,"r")
                else : f = open (file,"r", encoding = encoding)
            else :
                f = codecs.open (file, "r", encoding)
        
            if read_n_lines > 0 :
                lines = [ ]
                for line in f :
                    if len(lines) >= read_n_lines : break
                    lines.append(line)
            else :
                lines = f.readlines ()
                
            f.close()
            
        self._readlines(lines, numeric_column, sep)
        
    def change_header (self, new_header) :
        """
        change the column names
        @param      new_header      a list or a function which modifies the header
        
        Example:
        @code
        tbl.change_header ( lambda h : h if h != "column" else "new_name" )
        @endcode
        
        @warning Do not do that yourself, the class holds a dictionary up to date with the column index.
        
        """
        if isinstance (new_header, list) :
            self.header = new_header
            self.index = { }
            for (i,h) in enumerate (self.header) :
                self.index [h] = i
        else :
            he = [ new_header(h) for h in self.header ]
            self.change_header(he)
            
    def rename_column (self, old_name, new_name) :
        """
        rename a column
        @param      old_name    old name
        @param      new_name    new name
        """
        header = [ {old_name:new_name}.get(_,_) for _ in self.header ]
        self.change_header(header)
        
    def save (self, filename, sep = "\t", encoding = None, newline = "\n") :
        """
        saves the tables in a text file, first row is the column names
        @param      filename        filename
        @param      sep             column separator
        @param      encoding        encoding
        @param      newline         line separator
        """
        if sys.version_info.major >= 3 or encoding == None :
            if encoding == None :
                f = open(filename, "w", newline = newline)
            else :
                f = open(filename, "w", encoding = encoding, newline = newline)
        else :
            f = open( filename, "w", encoding = encoding)
            
        f.write (sep.join(self.header))
        f.write("\n")
        for row in self.values :
            f.write (sep.join( [ str(_) for _ in row ] ))
            f.write("\n")
        f.close()
        
    def _readlines(self, lines, numeric_column, sep) :
        """private"""
        if isinstance (lines[0], str) :
            lines = [ _.replace ("\ufeff", "").replace("\xef\xbb\xbf", "") \
                        .strip("\n\r ").split(sep) for _ in lines if len(_) > 0 ]
            self.header = lines[0]
            self.values = lines[1:]  
            self.index = { }
            for (i,h) in enumerate (self.header) :
                self.index [h] = i
        elif isinstance(lines[0], list) :
            self.header = lines[0]
            self.values = lines[1:]  
            self.index = { }
            for (i,h) in enumerate (self.header) :
                self.index [h] = i
        else :
            raise Exception("unexpected format: " + str(type(lines[0])))
            
        self._auto_conversion (numeric_column)
            
    def _auto_conversion (self, others_columns) :
        """
        private
        set up the column type based on the column name
        """
        for i,k in enumerate (self.header) :
            if k == "Date" :
                for row in self.values :
                    if isinstance(row[i], str) :
                        row[i] = datetime.datetime.strptime(row [i], '%Y-%m-%d')
                    elif isinstance(row[i], float) :
                        row[i] = datetime.datetime.utcfromtimestamp(row [i])
                    else :
                        raise Exception("unable to extract a date from type {0}".format(type(row[i])))
            elif k.startswith ("sum_") or k.startswith ("pos_") or \
                k.startswith ("avg_") or \
                k.startswith ("len_") or \
                k.startswith ("nb_") or \
                k.startswith ("max_") or \
                k.startswith ("min_") or \
               k.startswith ("d_") or k in others_columns or \
               k in ["Open","High","Low","Close","Volume","Adj Close"] or \
               k in ["distance", "nb", ] \
               :
                for row in self.values :
                    row[i] = float (row [i] )
            else :
                for row in self.values :
                    if isinstance(row[i],str) and row[i] == "None" :
                        row[i] = None
        
    def get_column_values (self, col) :
        """
        private
        returns all values for one column
        """
        i = self.index [col]
        return [ row [ i ] for row in self.values ]
    
    def get_distinct_values (self, col) :
        """private"""
        row = self.get_column_values (col)
        dis = { }
        for r in row : dis [r] = dis.get(r,0) + 1
        return dis
    
    def _interpret_row (self, row) :
        """private
        returns each row as a dictionary { column_name:value }
        """
        values = { }
        for a,b in zip(self.header, row) :
            values [a] = b
        return values
        
    def __iter__(self):
        """
        iterator on all rows, it returns a dictionary { column:value }
        @return     dictionary
        """
        for row in self.values :
            yield self._interpret_row(row)
        
    def add_column (self, colname, function, position = -1) :
        """
        add a column
        @param      colname     column name or columns name if it is a list or a tuple
        @param      function    function which will gives the values (or a list of functions, or a function which return a tuple)
        @param      position    where to insert the column, -1 for the end
        
        Example:
        @code
        table.add_column ( "has_A", lambda v : 1 if "A" in v["name"] else 0, 0 )
        
        table.add_column ( ("has_A", "has_B"), (lambda v : 1 if "A" in v["name"] else 0, 
                                                lambda v : 1 if "B" in v["name"] else 0 ))
                                                
        table.add_column ( ("has_A", "has_B"), (lambda v : (1 if "A" in v["name"] else 0, 1 if "B" in v["name"] else 0 ))
        @endcode
        """
        if isinstance(colname, str) :
            if position == -1 :
                self.index [colname] = len(self.index)
                for row in self.values :
                    v = self._interpret_row (row)
                    x = function (v)
                    row.append (x)
                self.header.append (colname)
                return self
            else :
                for row in self.values :
                    v = self._interpret_row (row)
                    x = function (v)
                    row.insert(position,x)
                self.header.insert (position, colname)
                self.index = { v:i for i,v in enumerate(self.header) }
                return self
                
        elif isinstance(function, list) :
            if len(colname) != len(function) :
                raise ValueError("unable to continue, colname and function do not have the same number of elements")
            if position == -1 : position = [-1] * len(colname)
            elif isinstance(position, int) : position = [position ] * len(colname)
            else :
                if len(position) != len(colname) :
                    raise RuntimeError("unable to continue, colname and position do not have the same number of elements")
            dec = 0
            for a,b,c in zip(colname, function, position):
                self.add_column(a, b, c + dec)
                dec += 1
        
        else :
            # we assume here, the function returns a tuple
            if not isinstance(position, int) : 
                raise TypeError("we expect an int for position for this case")
                
            if position == -1 :
                for row in self.values :
                    v = self._interpret_row (row)
                    x = function (v)
                    row.extend(x)
                self.header.extend(colname)
                
            else :
                for row in self.values :
                    v = self._interpret_row (row)
                    x = function (v)
                    for i,_ in enumerate(x) :
                        row.insert (position+i, _)
                for i,c in enumerate(colname) :
                    self.header.insert (position+i, c)

            self.index = { v:i for i,v in enumerate(self.header) }
        
    def add_column_index (self, colname = "index", start = 0) :
        """
        Example:
        @code
        table.add_column ( "index_row" )
        @endcode
        """
        self.index [colname] = len(self.index)
        for i,row in enumerate(self.values) :
            row.append (i + start)
        self.header.append (colname)
        return self
        
    def addc (self, colname, function, position = -1) :
        """
        @see me add_column
        """
        return self.add_column(colname, function, position)
        
    def add_column_recursive (self, colname, functionValue, functionAgg) :
        """
        Example:
        @code
        table.add_column_recursive ( lambda v : v ["norm_%s" % loi],
                        lambda li, v : li[-1] + v )
        @endcode
        """
        self.index [colname] = len(self.index)
        values = []
        for row in self.values :
            v = self._interpret_row (row)
            x = functionValue (v)
            y = functionAgg (values, x)
            row.append (y)
            values.append(y)
        self.header.append (colname)
        return self
        
    def add_column_recursive_row (self, colname, functionAgg) :
        """
        Example:
        @code
        table.add_column_recursive_row ("w_%s" % loi, 
                        lambda li, v : li[-1] + v ["norm_%s" % loi] \
                        if len(li)> 0 else v ["norm_%s" % loi] )
        @endcode
        """
        self.index [colname] = len(self.index)
        values = []
        for row in self.values :
            v = self._interpret_row (row)
            y = functionAgg (values, v)
            row.append (y)
            values.append(y)
        self.header.append (colname)
        return self
        
    def add_column_vector (self, colname, vector) :
        """
        add a column defined by vector (list of values for each row)
        
        @param      colname     column to add
        @param      vector      (list) list of values to add to each row
        @return                 self
        """
        if len(vector) != len(self) :
            raise ValueError("vector and table have different length")
        for vec,row in zip (vector, self.values) :
            row.append (vec)
        self.index [colname] = len(self.index)
        self.header.append (colname)
        return self
    
    def add_column_smooth (self, colname, function, position, weights) :
        """
        Example:
        @code
        x = 1./3
        table.add_column_smooth("has_A_smooth", lambda v : v["has_A"], [ -1,0,1], [x,x,x] )
        @endcode
        """
        if len(position) != len(weights) :
            raise ValueError("position and weights must have the same length")
        self.index [colname] = len(self.index)
        column = [ function ( self._interpret_row (row) ) for row in self.values ]
        tw     = sum(weights)
        couple = list(zip (position, weights))
        for p,row in enumerate (self.values) :
            sx = 0.
            sw = 0.
            ms = 0
            for i,w in couple :
                pi = p+i
                if 0 <= pi < len(self) :
                    sx += column[pi] * w
                    sw += w
                else :
                    ms += 1
                   
            if ms == 0 : row.append (sx)
            elif sw != 0 : row.append (sx * tw / sw)
            else : row.append(sx)
        self.header.append (colname)
        return self
            
    def aggregate_column (self, colname, aggregated_function = sum) :
        """
        Example:
        @code
        total = table.aggregate_column ("d_c", sum)
        @endcode
        """
        function = lambda v : v[colname]
        return self.aggregate (function, aggregated_function)
       
    def aggregate (self, function, aggregated_function = sum) :
        """
        Example:
        @code
        total = table.aggregate_column (lambda v : v["d_c"], len)
        @endcode
        """
        return aggregated_function ( 
                [ function ( self._interpret_row(row)) \
                      for row in self.values ] )

    def where (self, condition_function) :
        """@see me filter
        """
        return self.filter (condition_function)
        
    def filter (self, condition_function) :
        """
        Example:
        @code
        fil = table.filter ( lambda v : v["d_b"] == 2)
        @endcode
        
        @warning Rows are not copied.
        
        """
        newv = []
        for row in self.values :
            v = self._interpret_row (row)
            x = condition_function (v)
            if x : newv.append (row)
        final = self._private_getclass() (self.header,newv)
        return final
        
    def groupby_implicit (self,  functionKey, functionWeight = None, logging = None ) :
        """
        use prefix of a column name to know which function to use
        as an aggregated (sum, avg, len, key, none, max, min)
        Example:
        @code
        group = table.groupby_implicit ( lambda v: v["name"] )
        @endcode
        """
        def identical (col, v) : return v [col]
        def first (vec) : return vec[0]
        def avg (vec) : return TableFormulaCore.ratio (sum(vec), len(vec))
       
        functions       = [ ]
        labels          = [ "key"]
        functionsAgg    = [ ]
        keys            = { }
        for col in self.header :
            if col.startswith ("key") :
                values = self.select ( lambda v : (v [col], functionKey(v)) )
                dd = { }
                for v in values :
                    if v[1] not in dd : dd[v[1]] = {}
                    dd[v[1]] [ v[0]] = 1
                for k in dd : dd[k] = len(dd[k])
                keep = []
                for k,v in dd.items () :
                    if v > 1 : keep.append ( (k,v) )
               
                if len(keep) == 0 :
                    functions.append ( lambda v, col=col : identical (col, v) )
                    labels.append (col)
                    functionsAgg.append ( first )
                elif logging != None :
                    end = min (len(keep), 10)
                    mes = ",".join([str(_) for _ in keep[:end]])
                    logging ("removing column " + col + " no unique value : " + str(len(dd)) + ": " + mes)
            elif col.startswith ("sum") :
                    functions.append ( lambda v, col=col : identical (col, v) )
                    labels.append (col)
                    functionsAgg.append ( sum )
            elif col.startswith ("len") :
                    functions.append ( lambda v, col=col : 1 )
                    labels.append (col)
                    functionsAgg.append ( len )
            elif col.startswith ("min") :
                    functions.append ( lambda v, col=col : 1 )
                    labels.append (col)
                    functionsAgg.append ( min )
            elif col.startswith ("max") :
                    functions.append ( lambda v, col=col : 1 )
                    labels.append (col)
                    functionsAgg.append ( max )
            elif col.startswith ("avg") :
                    functions.append ( lambda v, col=col : identical (col, v) )
                    labels.append (col)
                    functionsAgg.append ( avg )
            elif col.startswith ("none") :
                pass
            else :
                raise RuntimeError("unable to aggregate column " + col)
               
        return self.groupby ( functionKey, functions, labels, functionsAgg, functionWeight)
               
    def groupby (self,  functionKey,
                        functionsValue,
                        columns = None,
                        functionsAgg = None,
                        functionWeight = None) :
        """
        Example:
        @code
        group = table.groupby ( lambda v: v["name"],
                                [ lambda v: v["d_a"],
                                  lambda v: v["d_b"] ],
                                [ "name", "sum_d_a", "sum_d_b"] )
        @endcode
        or
        @code
        groupmax = table.groupby ( lambda v: v["name"],
                                [ lambda v: v["d_a"],
                                  lambda v: v["d_b"] ],
                                [ "name", "max_d_a", "max_d_b"],
                                [ max, max ] )
        @endcode
        """
        if not isinstance (functionsValue, list) :
            functionsValue = [ functionsValue ]
        if functionsAgg == None :
            functionsAgg = [ sum for f in functionsValue ]
        if functionWeight == None :
            if columns != None and len(columns) != len(functionsValue) + 1 :
                raise Exception ("columns should have %d names not (%d)"% (len(functionsValue) + 1, len(columns)))
        else :
            if columns != None and len(columns) != len(functionsValue) + 2 :
                raise Exception ("columns should have %d names not (%d)"% (len(functionsValue) + 2, len(columns)))
        if columns != None and not isinstance(columns[0], str) :
            raise TypeError ("expecting type str not %s in columns" % (str(type(columns[0]))))
         
        hist = { }
       
        if functionWeight != None :
            histWeight = { }

            for row in self.values :
                v   = self._interpret_row (row)
                key = functionKey (v)
                w   = 1. if functionWeight == None else functionWeight (v)
               
                if key not in hist :
                    histWeight [key] = [ w ]
                    hist [ key ] = [ [f(v)*w] for f in functionsValue ]
                else :
                    histWeight [key].append (w)
                    h = hist [ key ]
                    for i,f in enumerate (functionsValue) :
                        h[i].append( f (v)*w )
                      
            for key in hist :
                h = hist[key]
                w = sum( histWeight [key] )
                for i in range(0, len(h)) :
                    h[i] = functionsAgg[i] (h[i], w)
               
            f = hist.items if sys.version_info.major >= 3 else hist.iteritems
            histValues = [ [k,sum(histWeight[k])] + v for k,v in f () ]
         
            if columns == None :
                columns = ["key", "weight"] + [ "val%d" % i for i,f in enumerate (functionsValue) ]
            ret = self._private_getclass() (columns, histValues)
            return ret       
        else :
            for row in self.values :
                v   = self._interpret_row (row)
                key = functionKey (v)
                if key not in hist :
                    hist [ key ] = [ [f(v)] for f in functionsValue ]
                else :
                    h = hist [ key ]
                    for i,f in enumerate (functionsValue) :
                        h[i].append( f (v) )
                      
            for key in hist :
                h = hist[key]
                for i in range(0, len(h)) :
                    h[i] = functionsAgg[i] (h[i])
               
            f = hist.items if sys.version_info.major >= 3 else hist.iteritems
            histValues = [ [k,] + v for k,v in f () ]
         
            if columns == None :
                columns = ["key"] + [ "val%d" % i for i,f in enumerate (functionsValue) ]
            ret = self._private_getclass() (columns, histValues)
        return ret
            
    def sort (self, functionValue, reverse = False) :
        """
        Example:
        @code
        table.sort (lambda v: v["d_b"] + v["d_c"] )
        @endcode
        """
        values = [ (functionValue ( self._interpret_row (row)),i) for i,row in enumerate(self.values) ]
        values.sort (reverse = reverse)
        self.values = [ self.values[_[1]] for _ in values ]
        return self
            
    def extract_columns (self, listColumns) :
        """
        extract some columns
        
        @param      listColumns     list of columns to remove or a function
                                    which returns True if the column has to be extracted
                                    based on its name
        @return                     table
        
        Example:
        @code
        ext = table.extract_columns(["name", "d_a"] )        
        @endcode
        """
        if isinstance(listColumns,list) :
            indexes = [ (self.index [col] if isinstance(col,str) else col)  \
                            for col in listColumns ]
            header  = listColumns
            values  = [ [ row[i] for i in indexes ] for row in self.values ]
            return self._private_getclass() (header, values)
        else :
            header =  [ _ for _ in self.header if listColumns(_) ]
            return self.extract_columns(header)
        
    def remove_columns (self, listColumns) :
        """
        remove some columns
        
        @param      listColumns     list of columns to remove or a function
                                    which returns True if the column has to be removed
                                    based on its name
        @return                     table
        
        Example:
        @code
        rem = table.remove ("d_a")
        @endcode
        """
        if isinstance(listColumns, list) :
            cols = [ _ for i,_ in enumerate(self.header) \
                    if _ not in listColumns and i not in listColumns ]
            return self.extract_columns (cols)
        elif isinstance(listColumns, str) :
            cols = [ _ for _ in self.header if _ != listColumns ]
            return self.extract_columns (cols)
        else :
            cols = [ _ for _ in self.header if not listColumns(_) ]
            return self.extract_columns (cols)

    def innerjoin (self, table, 
                            functionKey1, 
                            functionKey2,
                            nameKey         = "key",
                            addSuffixAnyWay = False,
                            prefixToAdd     = None,
                            full            = False,
                            keepKey         = True,
                            putKeyInColumn  = None,
                            missingValue    = None,
                            uniqueKey       = False) :
        """
        @param      table           other table to join with
        @param      functionKey1    key for the first table (a function)
        @param      functionKey2    key for the second table (a function) innerjoin .... ON ...
        @param      addSuffixAnyWay add a suffix to every column from the second table even if names are different (suffix is "+")
        @param      prefixToAdd     prefix to add the the columns of the second table
        @param      full            add all items even if there is no common keys (FULL OUTER JOIN), otherwise keep only common keys
        @param      keepKey         keep the key as a column in the result (column is key), otherwise not
        @param      putKeyInColumn  private parameter: keepKey has to be true and in this case, put the key in this column (integer)
        @param      missingValue    when there is not key on one side, this default value will be put in place
        @param      uniqueKey       if True, the function assumes there is a bijection between rows and keys (one row <--> one key) on both tables,
                                    otherwise, it will not.
        @return                     a table
        
        Example:
        @code
        innerjoin = table.innerjoin (group, lambda v : v["name"],
                                            lambda v : v["name"], "group" )
        @endcode
        """
        defaultVal1 = [ missingValue for k in self.header ]
        defaultVal2 = [ missingValue for k in table.header ]

        if uniqueKey :
            keys = { }
            for row in self.values :
                v = self._interpret_row (row)
                key = functionKey1 (v)
                keys [key] = (row, None)
               
            for row in table.values :
                v = table._interpret_row (row)
                key = functionKey2 (v)
                if key in keys : keys [key] = (keys[key][0], row)
                elif full : keys[key] = (None, row)
                
            if not full :
                d = []
                for k,v in keys.items() :
                    if None in v : d.append(k)
                for _ in d : del keys[_]
            else :
                for k in keys :
                    v = keys[k]
                    if   v[0] == None : keys[k] = (defaultVal1, v[1])
                    elif v[1] == None : keys[k] = (v[0], defaultVal2)
                    
            if keepKey :
                columns = [nameKey]
                for x in self.header :
                    while x in columns : x += "~"
                    columns.append (x)
               
                for x in table.header :
                    if prefixToAdd != None : x = prefixToAdd + x
                    elif addSuffixAnyWay : x += "+"
                    while x in columns : x += "+"
                    columns.append (x)
               
                f = keys.items if sys.version_info.major >= 3 else keys.iteritems
                values = [ [k] + v[0] + v[1] for k,v in f() if len(v) == 2 ]
                return self._private_getclass() (columns, values)
            else :
                columns = []
                for x in self.header :
                    while x in columns : x += "~"
                    columns.append (x)
               
                for x in table.header :
                    if prefixToAdd != None : x = prefixToAdd + x
                    elif addSuffixAnyWay : x += "+"
                    while x in columns : x += "+"
                    columns.append (x)
               
                f = keys.items if sys.version_info.major >= 3 else keys.iteritems

                if putKeyInColumn == None :
                    values = [ v[0] + v[1] for k,v in f() if len(v) == 2 ]
                else :
                    values = []
                    for k,v in f():
                        if len(v) == 2 :
                            nr = v[0] + v[1]
                            nr[putKeyInColumn] = k
                            values.append(nr)
                           
                return self._private_getclass() (columns, values)
        else :
            keys = { }
            for row in self.values :
                v = self._interpret_row (row)
                key = functionKey1 (v)
                if key in keys:  
                    keys [key][0].append(row) 
                else :
                    keys [key] = ( [row] , None )
               
            for row in table.values :
                v = table._interpret_row (row)
                key = functionKey2 (v)
                if key in keys : 
                    if keys[key][1] == None : 
                        keys [key] = (keys[key][0], [row])
                    else :
                        keys [key][1].append(row) 
                elif full : 
                    keys[key] = (None, [row])
                
            if not full :
                d = []
                for k,v in keys.items() :
                    if None in v : d.append(k)
                for _ in d : del keys[_]
            else :
                for k in keys :
                    v = keys[k]
                    if   v[0] == None : keys[k] = ( [ defaultVal1 ], v[1])
                    elif v[1] == None : keys[k] = (v[0], [ defaultVal2 ] )
                    
            if keepKey :
                columns = [nameKey]
                for x in self.header :
                    while x in columns : x += "~"
                    columns.append (x)
               
                for x in table.header :
                    if prefixToAdd != None : x = prefixToAdd + x
                    elif addSuffixAnyWay : x += "+"
                    while x in columns : x += "+"
                    columns.append (x)
               
                f = keys.items if sys.version_info.major >= 3 else keys.iteritems
                
                values = []
                for k,v in f():
                    if len(v) == 2 :
                        for ka in v[0] :
                            for kb in v[1] :
                                values.append (  [k] + ka + kb  )
                return self._private_getclass() (columns, values)
            else :
                columns = []
                for x in self.header :
                    while x in columns : x += "~"
                    columns.append (x)
               
                for x in table.header :
                    if prefixToAdd != None : x = prefixToAdd + x
                    elif addSuffixAnyWay : x += "+"
                    while x in columns : x += "+"
                    columns.append (x)
               
                f = keys.items if sys.version_info.major >= 3 else keys.iteritems

                if putKeyInColumn == None :
                    values = [ v[0] + v[1] for k,v in f() if len(v) == 2 ]
                else :
                    values = []
                    for k,v in f():
                        if len(v) == 2 :
                            for ka in v[0] :
                                for kb in v[1] :
                                    nr = ka + kb
                                    nr[putKeyInColumn] = k
                                    values.append(nr)
                           
                return self._private_getclass() (columns, values)
            
    def filter_quantile (self, function, alpha_min = 0.025, alpha_max = 0.025) :
        """
        sort all rows using criteria defined by function and remove
        rows at the extremes
        
        @param      function        values used to estimate the quantiles
        @param      alpha_min       lower quantile 
        @param      alpha_max       higher quantile 
        @return                     a table containing all the rows where the criterium
                                    is within the two quantiles
        
        Example:
        @code
        fil = table.filter_quantile ( lambda v : v["d_b"], 0, 0.4 )
        @endcode
        
        @warning Rows are not copied.
        
        """
        values = [ ]
        for row in self.values :
            v = self._interpret_row (row)
            val = function (v)
            values.append ( (val, row) )
        values.sort ()
        lv = len(values)
        i1 = int(lv * alpha_min + 0.5)
        i2 = int(lv * (1-alpha_max) + 0.5)
        i1 = max(i1,0)
        i1 = min(i1, lv)
        i2 = max(i1,i2)
        i2 = min(i2, lv)
        if i2 == i1 :
            raise RuntimeError("unable to extract quantile, the table is either " +
                            "empty or chosen quantile are not correct")
        values = [_[1] for _ in values[i1:i2] ]
        return self._private_getclass() (self.header, values )        
            
    def union (self, table) :
        """
        @param      table       table
        @return                 table (with the same number of columns)
        
        concatenates two tables by rows, they must have the same header, rows of both tables are merged into a single matrix
        Example:
        @code
        union = table.union (table2)
        @endcode
        """
        if len(self.header) != len(table.header) :
            raise ValueError("tables do not have the same number of columns\ntbl1: %s\ntbl2: %s" % ( ",".join(self.header), ",".join(table.header)))
        for a,b in zip(self.header, table.header) :
            if a != b :
                raise ValueError("tables do not have the same column names")
        return self._private_getclass() (self.header, self.values + table.values)
        
    def concatenate (self, table, addPrefix = "") :
        """
        concatenates two tables by columns
        @param      table       table
        @param      addPrefix   add a prefix to each column from table    
        @return                 table  (with the same number of rows as the longest one)
        """
        maxr   = max (len(self), len(table))
        header = self.header + [ addPrefix + h for h in table.header ]
        values = [ ]
        for i in range(0,maxr) :
            r1 = self.values[i]  if i < len(self)  else [ None ] * len(self.header)
            r2 = table.values[i] if i < len(table) else [ None ] * len(self.table)
            values.append (r1 + r2)
        return self._private_getclass() (header, values)

    def random (self, n, unique = False) :
        """
        select n random row from the table, returns a table
        @param      n       number of desired random rows
        @param      unique  draws unique rows or non unique rows
                            (tirage sans remise ou avec remise)
        @return             a table
        
        Example:
        @code
        rnd = table.random(10)
        @endcode
        """
        if unique :
            if n > len(self) :
                raise ValueError("number of desired random rows is higher " + \
                                "than the number of rows in the table")
            index = { }
            while len(index) < n :
                h = random.randint(0,len(self)-1)
                index[h] = 0
            values = [ self.values[h] for h in index ]
            return self._private_getclass() (self.header, values)
        else :
            values = []
            for i in range(0,n) :
                h = random.randint(0,len(self)-1)
                values.append (self.values[h])
            return self._private_getclass() (self.header, values)
            
    def todict (self, functionKey, functionValue, useList = False) :
        """
        convert the table as a dictionary { key:value }
        each of them is defined by functions.
        
        @param      functionKey     defines the key
        @param      functionValue   defines the value
        @param      useList         if there are multiple rows sharing the same key, it should be true,
                                    all values are stored in a list
        @return                     a dictionary { key:row } or { key: [ row1, row2, ...] }
        
        Example:
        @code
        d = table.todict( lambda v: v["name"], lambda v: v["d_b"], True)
        @endcode
        """
        res = {}
        if useList :
            for row in self.values :
                v = self._interpret_row(row)
                key = functionKey(v)
                val = functionValue(v)
                if key in res : res[key].append (val)
                else : res[key] = [ val ]
        else :
            for row in self.values :
                v = self._interpret_row(row)
                key = functionKey(v)
                val = functionValue(v)
                res[key] = val
        return res
        
    def reduce_dict (self, functionKey, functionValue, useList = False) :
        """
        @see me todict
        """
        return todict (functionKey, functionValue, uselist)
        
    def select (self, functionRow) :
        """
        @param      functionRow   fonction
        @return                   table
        
        Example:
        @code
        d = table.select( lambda v: (v["name"], v["d_b"]))
        print (list(d))
        @endcode
        """
        for row in self.values :
            v = self._interpret_row (row)
            nr = functionRow(v)
            yield nr
            
    def modify_all (self, modification_function) :
        """
        apply the same modification to every number
        @param      modification_function       modification to apply to every number
        @return                                 new table
        
        The signature of the function is the following one:
        @code
        def function (value, column_name) :
            # ....
            return new_value
        @endcode
        
        Example:
        @code
        tbl = tbl.modify_all(lambda v,c : {"string":"", "numerical":0}.get (c,None) if v == None else v )
        @endcode
        """
        values = []
        for row in self.values :
            r = [ ]
            for v,h in zip( row, self.header) :
                r.append (modification_function (v,h) )
            values.append ( r ) 
        return self._private_getclass() (self.header, values)
        
    def dcast (self, 
                        functionKey, 
                        functionInstance,
                        full = True) :
        """
        @see me multiply_column_by_row_instance
        """
        return self.multiply_column_by_row_instance (functionKey, functionInstance, full)

    def multiply_column_by_row_instance (self, 
                        functionKey, 
                        functionInstance,
                        full = True) :
        """
        @param      functionKey         defines a key (function)
        @param      functionInstance    defines a second key (will be moved to the columns dimension)
        @param      full                introduces missing values for not found combinations
        @return                         a table
        
        If a column contains a finite set of value, for example,
        we have the temperature for several cities organized like if
        it were a table from a database: city, date, temperatue.
        We would like to get another table where we have:
        date temparature_city1 temperature_city2...
        
        Then we would type:
        Example:
        @code
        mul = table.multiply_column_by_row_instance (
                            lambda v: v["date"],
                            lambda v: v["city"])
        @endcode
        The input table would be like:
        @code
        city   date
        A      jan
        A      feb
        B      feb
        @endcode
        It returns:
        @code
        KEY	    A|city	A|date	B|city	B|date
        feb	    A	    feb	    B	    feb
        jan	    A	    jan	    None	None
        @endcode
        """
        values = [ functionInstance ( self._interpret_row(row)) for row in self.values ]
        distinct = { }
        for v in values : distinct[v] = 0
        distinct = [ _ for _ in distinct ]
        distinct.sort()
        table1 = copy.deepcopy (self)
        table  = None
        header = copy.copy(table1.header)
        orig   = len (header)
        nameKey = "~KEY~"
        while nameKey in header : nameKey += "*"
        nbJoin = 0
       
        for val in distinct :
            table2 = table1.filter ( lambda v : functionInstance(v) == val )
            if table == None :
                table = table2.copy()
            else :
                colkey = table.header[0]
                table = table.innerjoin (  table2,
                                           functionKey if nbJoin == 0 else \
                                                    lambda v :v [colkey],
                                           functionKey,
                                           nameKey          = nameKey,
                                           prefixToAdd      = str(val) + "|",
                                           full             = full,
                                           keepKey          = nbJoin == 0,
                                           putKeyInColumn   = None if nbJoin == 0 else 0,
                                           uniqueKey        = True)
                                          
                if nbJoin == 0 :
                    head = []
                    nb = 0
                    for h in table.header :
                        if not h.endswith("~") and nb < orig :
                            head.append ( "%s|%s" % (distinct[0], h)  )
                            nb += 1
                        else : head.append (h)
                    header = ["KEY"] + head[1:]
                    table = self._private_getclass() (header, table.values)
               
                nbJoin += 1
               
        if nbJoin == 0 :
            head = []
            nb = 0
            for h in table.header :
                if not h.endswith("~") and nb < orig :
                    head.append ( "%s|%s" % (distinct[0], h)  )
                    nb += 1
                else : head.append (h)
            values = []
            for row in self.values :
                v = self._interpret_row(row)
                r = [ functionKey (v) ] + row
                values.append (r)
            header = ["KEY"] + head
            table = self._private_getclass() (header, values)

        return table
        
    def create_index (self, functionIndex) :
        """
        this method creates an index,
        to get an indexes row, use method get
        Example:
        @code
        table.create_index( lambda v : (v["name"], v["d_a"]) )
        row = table.get ( ('A', 1.1) )
        value = table.get ( ('A', 1.1), 2 )
        @endcode
        """
        self.indexspecial = { }
        for row in self.values :
            v = self._interpret_row (row)
            nr = functionIndex(v)
            if nr in self.indexspecial :
                raise KeyError("unable to add %s because it is already present" % str (nr))
            self.indexspecial [nr] = row
        return self
        
    def get (self, rowIndex, column = None) :
        """
        use the index created by method create_index
        Example:
        @code
        table.create_index( lambda v : (v["name"], v["d_a"]) )
        row = table.get ( ('A', 1.1) )
        value = table.get ( ('A', 1.1), 2 )
        @endcode
        """
        if "indexspecial" not in self.__dict__ :
            raise Exception("no index was created")
        row = self.indexspecial [rowIndex]
        if column == None : return row
        elif isinstance (column, int) : return row[column]
        else : return row [ self.index [column] ]
                
    def avg_std (self, functionValue, 
                       functionWeight = lambda v : 1) :
        """
        returns the average and standard deviation
        """
        avg = 0.
        std = 0.
        n   = 0.
        for i,row in enumerate(self.values) :
            v    = self._interpret_row(row)
            x    = float (functionValue(v))
            w    = functionWeight(v)
            avg += x * w
            std += x*x * w
            n   += w
            
            #check  = std/n - (avg/n)**2        
            #if check < 0 :
            #    raise Exception("float error i=%d issue with %f avg %f x2 %f var %d" % (i,x, avg/n, std/n, check)) 
        
        if n != 0 :
            avg /= n
            std /= n
            std -= avg*avg
            std  = math.sqrt(std)
        else :
            avg = 0.
            std = 0.
        return avg, std
            
    def add_column_cumulative ( self,
                                column_index,
                                column_name,
                                functionIndex,
                                functionValue,
                                normalize = False,
                                reverse = False,
                                cumulative = True,
                                functionSort = None) :
        """
        also called the Gini function
        Example:
        @code
        table.add_column_cumulative ( "index_%s" % col,
                                      "dist_%s" % col,
                                    lambda v : v["sum_nbclient"],
                                    lambda v : v[col],
                                    functionSort = lambda v : v [col] / v["sum_nbclient"],
                                    normalize = True)       
        @endcode
        """
       
        if functionSort == None :
            functionSort = functionValue
       
        val = [ ]
        for row in self.values :
            v = self._interpret_row (row)
            i = functionIndex (v)
            s = functionSort(v)
            v = functionValue(v)
            val.append ( (s,i,v) )
           
        val.sort (reverse = reverse)

        if cumulative :
            res = [ (0.,0.)]
            for s,i,v in val :
                res.append ( ( i + res[-1][0], v + res[-1][1] ) )
            del res[0]
           
            if normalize :
                sumi = res[-1][0]
                sumv = res[-1][1]
                if sumi != 0 and sumv != 0 :
                    res = [ (_[0] / sumi, _[1] / sumv) for _ in res ]
                else :
                    raise ZeroDivisionError ("cannot divide by zero, all indexes or all values are null")
           
        else :
            res = [ (i,v) for s,i,v in val ]
       
            if normalize :
                sumi = sum ( [_[0] for _ in res ] )
                sumv = sum ( [_[1] for _ in res ] )
                if sumi != 0 and sumv != 0 :
                    res = [ (_[0] / sumi, _[1] / sumv) for _ in res ]
                else :
                    raise ZeroDivisionError ("cannot divide by zero, all indexes or all values are null")

        for row,add in zip (self.values, res) :
            row.extend (add)
        self.index [column_index] = len(self.index)
        self.index [column_name] = len(self.index)
        self.header.append (column_index)
        self.header.append (column_name)
        return self        

    def transpose (self, labelC = None, labelAsRow = True) :
        """
        computes the transpose
        @param      labelC          proposes labels for the column,
                                    if None, take "r%d" % i,
                                    if it is a string, the function assumes it is a column name
        @param      labelAsRow      add the label as a row
        @return                     new table
        """
        if labelC == None :
            label = ["r%d" % i for i in range (0, len(self.values)) ]
            if labelAsRow : label = ["rowheader"] + label
            rem = None
        elif isinstance(labelC, str):
            label = list(self.select(lambda v:v[labelC]))
            rem = label
        else :
            rem = None
            label = labelC
            
        values = [ ]
        for i in range (0, len(self.header)) :
            if rem != None and self.header[i] == labelC :
                continue
            row = [ _[i] for _ in self.values ]
            if labelAsRow : row = [self.header[i]] + row 
            values.append(row)
        return self._private_getclass()(label, values)
        
    def covariance(self) :
        """
        computes the covariance matrix, the first column
        will contains the column names
        @return         new table
        """
        for i,x in enumerate(self.values[0]) :
            if not isinstance(x, float) :
                raise TypeError("expecting a float on column %d" % i)
        values = self.np_matrix
        N = values.shape[0]
        sums   = numpy.sum (values, axis=0) / N
        for i in range(0, values.shape[1]) :
            values[:,i] -= sums[0,i]
        cov    = values.transpose () * values
        cov   /= N
        head   = [ "var" ]+ self.header
        size = cov.shape
        values = [ [ self.header[i] ] +  [ float(cov[i,j]) \
                          for j in range(0,size[1]) ] \
                    for i in range(0,size[0]) ]
        tbl = self._private_getclass()(head, values)
        return tbl
        
    def correlation_col (self, col1, col2, noCenter = False) :
        """
        computes the correlation between two columns
        @param      col1        column 1
        @param      col2        column 2
        @param      noCenter    does the computation without removing the average
        @return                 float (covariance)
        """
        values  = [ [ self._interpret_row(row)[col1],
                      self._interpret_row(row)[col2] ] for row in self.values ] 
            
        if len(values) <= 1 :
            raise ValueError("expecting more than one observation, not %d" % len(values))
            
        mx = 0.
        my = 0.
        vx = 0.
        vy = 0.
        co = 0.
        nb = 0.
        for a,b in values :
            nb += 1
            mx += a
            my += b
            vx += a**2
            vy += b**2
            co += a*b
        mx /= nb
        my /= nb
        vx /= nb
        vy /= nb
        co /= nb
        if not noCenter :
            vx -= mx**2
            vy -= my**2
            co -= mx*my
        vx  = vx**0.5
        vy  = vy**0.5
        v = vx*vy
        if v != 0 : co /= v
        return co
        
    def covariance_col (self, col1, col2, noCenter = False) :
        """
        computes the correlation between two columns
        @param      col1        column 1
        @param      col2        column 2
        @param      noCenter    does the computation without removing the average
        @return                 float (covariance)
        """
        values  = [ [ self._interpret_row(row)[col1],
                      self._interpret_row(row)[col2] ] for row in self.values ] 
            
        if len(values) <= 1 :
            raise ValueError("expecting more than one observation, not %d" % len(values))
            
        mx = 0.
        my = 0.
        co = 0.
        nb = 0.
        for a,b in values :
            nb += 1
            mx += a
            my += b
            co += a*b
        mx /= nb
        my /= nb
        co /= nb
        if not noCenter :
            co -= mx*my
        return co
        
    def correlation_row (self, row1, row2, noCenter = False) :
        """
        computes the correlation between two columns
        @param      row1        row 1 (integer)
        @param      row2        row 2 (integer)
        @param      noCenter    does the computation without removing the average
        @return                 float (covariance)
        """
        values  = [ [a,b] for a,b in zip ( self.values[row1], self.values[row2] ) ]
            
        if len(values) <= 1 :
            raise ValueError("expecting more than one observation, not %d" % len(values))
            
        mx = 0.
        my = 0.
        vx = 0.
        vy = 0.
        co = 0.
        nb = 0.
        for a,b in values :
            nb += 1
            mx += a
            my += b
            vx += a**2
            vy += b**2
            co += a*b
        mx /= nb
        my /= nb
        vx /= nb
        vy /= nb
        co /= nb
        if not noCenter :
            vx -= mx**2
            vy -= my**2
            co -= mx*my
        vx  = vx**0.5
        vy  = vy**0.5
        v = vx*vy
        if v != 0 : co /= v
        return co
        
    def covariance_row (self, row1, row2, noCenter = False) :
        """
        computes the correlation between two columns
        @param      row1        row 1 (integer)
        @param      row2        row 2 (integer)
        @param      noCenter    does the computation without removing the average
        @return                 float (covariance)
        """
        values  = [ [a,b] for a,b in zip ( self.values[row1], self.values[row2] ) ]
            
        if len(values) <= 1 :
            raise ValueError("expecting more than one observation, not %d" % len(values))
            
        mx = 0.
        my = 0.
        co = 0.
        nb = 0.
        for a,b in values :
            nb += 1
            mx += a
            my += b
            co += a*b
        mx /= nb
        my /= nb
        co /= nb
        if not noCenter :
            co -= mx*my
        return co
        
    def correlation(self, useBootstrap      = False, 
                          collapseFormat    = True,
                          nbdraws           = -1,
                          alpha             = 0.05,
                          functionKeepValue = lambda val,low,high : "%f|%f,%f" % (bo[0], bo[2],bo[3])) :
        """
        computes the correlation matrix, the first column
        will contains the column names
        @param      useBootstrap            if True, use a bootstrap method to estimate the correlation
        @param      collapseFormat          if True and useBootstrap is True, produces a format average|lower bound|higher bound (at a definite confidence level)
        @param      nbdraws                 number of draws (if -1, then it will be equal to the number of observations)  
        @param      alpha                   confidence level
        @param      functionKeepValue       if collapseFormat is True, this function is used to collapse val,low,high in a single string
        @return                             new table
        """
        
        if useBootstrap :
            head   = [ "var" ]+ self.header
            values = [ [i] + [ 0. for r in self.header ] for i in self.header ]
            for i in range(len(self.header)) :
                fileprint("TableFormulaCore.correlation (useBootstrap=True) [row=%d/%d]" % (i, len(self.header)))
                values[i][0] = self.header[i]
                for j in range(len(self.header)) :
                    vs = [ [row[i], row[j]] for row in self.values ]
                    bo = TableFormulaCore.bootstrap (vs, 
                                        function = TableFormulaCore.correlation_bicolumn, 
                                        nbdraws  = nbdraws, 
                                        alpha    = alpha)
                    if collapseFormat :
                        st             = functionKeepValue (bo[0],bo[2],bo[3])
                        values[i][j+1] = st
                    else :
                        raise NotImplementedError("collapseFormat False is not implemented yet")
            tbl = self._private_getclass()(head, values)
            return tbl
        else :
            for i,x in enumerate(self.values[0]) :
                if not isinstance(x, float) :
                    raise TypeError("expecting a float on column %d" % i)
                    
            values = self.np_matrix
            N = values.shape[0]
            sums   = [ sum(values[:,i]) / N for i in range(0,values.shape[1]) ]
            
            for i in range(0, values.shape[1]) :
                values[:,i] -= sums[i]
                
            cov    = values.transpose () * values
            cov   /= N
            diag   = [ cov[i,i]**0.5 for i in range(cov.shape[0]) ]
            for i in range(cov.shape[0]) :
                if diag [i] > 0 :
                    cov [i,:] /= diag[i]
                    cov [:,i] /= diag[i]
            
            head   = [ "var" ]+ self.header
            size = cov.shape
            values = [ [ self.header[i] ] +  [ float(cov[i,j]) \
                              for j in range(0,size[1]) ] \
                        for i in range(0,size[0]) ]
            tbl = self._private_getclass()(head, values)
            return tbl
        
    def values_to_float(self, only_if_possible = False, subset_columns = None) :
        """
        converts all values into float
        @param    only_if_possible      if True, converts all possible values and catches exception,
                                        if False, converts everything, raises an exception when not possible
        @param    subset_columns        if None, takes all of them, otherwise, try to convert
                                        only for the listed columns
        @return                         table
        """
        tbl = self.copy()
        if subset_columns != None :
            subset = { i:True for i,v in enumerate(self.header) if v in subset_columns }
        if only_if_possible :
                
            for row in tbl.values :
                for i in range(0,len(row)) :
                    if subset_columns == None or i in subset :
                        try :
                            v = float(row[i])
                            row[i] = v
                        except (ValueError, TypeError) :
                            continue
        else :
            for row in tbl.values :
                for i in range(0,len(row)) :
                    if subset_columns == None or i in subset :
                        row[i] = float(row[i])
        return tbl
        
    def values_to_str(self, subset_columns = None, format = None) :
        """
        converts all values into str
        @param    subset_columns        if None, takes all of them, otherwise, try to convert
                                        only for the listed columns
        @param    format                format for the conversion, by None by default but it could be for exemple %1.2f.
        @return                         table
        """
        tbl = self.copy()
        if subset_columns != None :
            subset = { i:True for i,v in enumerate(self.header) if v in subset_columns }
               
        if format == None :
            for row in tbl.values :
                for i in range(0,len(row)) :
                    if subset_columns == None or i in subset :
                        row[i] = str(row[i])
        else :
            for row in tbl.values :
                for i in range(0,len(row)) :
                    if (subset_columns == None or i in subset) and isinstance (row[i],float) :
                        row[i] = format % row[i]
        return tbl
        
    def values_to_date(self, format = None, only_if_possible = False, subset_columns = None) :
        """
        converts all values into dates
        @param    only_if_possible      if True, converts all possible values and catches exception,
                                        if False, converts everything, raises an exception when not possible
        @param    format                date format see fn str_to_datetime
        @param    subset_columns        if None, takes all of them, otherwise, try to convert
                                        only for the listed columns
        @return                         table
        """
        tbl = self.copy()
        if subset_columns != None :
            subset = { i:True for i,v in enumerate(self.header) if v in subset_columns }
        if only_if_possible :
            if subset_columns != None :
                subset = { i:True for i,v in enumerate(self.header) if v in subset_columns }
                
            for row in tbl.values :
                for i in range(0,len(row)) :
                    if subset_columns == None or i in subset :
                        try :
                            v = str_to_datetime(row[i], format)
                            row[i] = v
                        except (ValueError, TypeError) :
                            continue
        else :
            for row in tbl.values :
                for i in range(0,len(row)) :
                    if subset_columns == None or i in subset :
                        row[i] = float(row[i])
        return tbl
        
    def histogram (self,    functionValue, 
                            nbDiv                = 100, 
                            secondColumnIsWeight = False,
                            normalize            = True,
                            removeExtreme        = 0.05) :
        """
        computes an histograms on one vector
        @param      functionValue           function which produces the value to histogram
        @param      nbDiv                   number of divisions for this histograms (boundaries are min and max)
        @param      secondColumnIsWeight    if True, the second column is the weight
        @param      normalize               if True, normalize by the sum of weights
        @param      removeExtreme           remove extreme values at both sides (0.05 means 0.025 on each side)
        @return                             table with two columns
        """
        values  = list ( [ functionValue (self._interpret_row(row)) for row in self.values ] )
        if removeExtreme != None and removeExtreme > 0 :
            values.sort ()
            al = int (len(values) * removeExtreme / 2)
            if al == 0 :
                raise Exception("removeExtreme has no impact (%d,%f)" % (len(values),len(values)*removeExtreme/2))
            if al*2 < len(values) :
                values = values [al:len(values)-al]
            
        mi      = min(values)
        ma      = max(values)
        
        if isinstance (values[0], tuple) or isinstance(values[0], list) :
            # weight
            W    = 0.
            div  = (ma[0]-mi[0]) / nbDiv
            hist = [ [ mi[0]+n*div, 0.] for n in range (0,nbDiv+1) ]
            for v in values :
                x = int ((v[0] - mi[0]) // div)
                hist[x][1] += v[1]
                W += v[1]
            mi = mi[0]
        else :
            W    = len(values)
            div  = (ma-mi) / nbDiv
            hist = [ [ mi+n*div, 0.] for n in range (0,nbDiv+1) ]
            for v in values :
                x = int ((v - mi) // div)
                if 0 <= x < len(hist) : 
                    hist[x][1] += 1.
    
        if normalize and W > 0 :
            for i in range(len(hist)) :
                hist[i][1] /= W
                
        values = [ [mi+n*div, hist[n]] for n in range(len(hist)) ]
        tbl = self._private_getclass()(["x", "hist(x)"], hist)
        return tbl
        
    def histograms (self,   columnsSet,
                            nbDiv                = 100, 
                            secondColumnIsWeight = False,
                            normalize            = True,
                            removeExtreme        = 0.05,
                            histxName            = "histKey") :
        """
        computes a common histograms on all columns
        @param      columnsSet              set of columns
        @param      nbDiv                   number of divisions for this histograms (boundaries are min and max)
        @param      secondColumnIsWeight    if True, the second column is the weight
        @param      normalize               if True, normalize by the sum of weights
        @param      removeExtreme           remove extreme values at both sides (0.05 means 0.025 on each side)
        @param      histxName               column name given to the x axis shared by every histogram
        @return                             table with two columns
        
        @warning The function skips any NaN of Inf value.
        
        """
        values  = [] 
        for row in self.values : 
            temp = self._interpret_row(row)
            for t in columnsSet : 
                values.append (temp[t])
            
        if removeExtreme != None and removeExtreme > 0 :
            values.sort ()
            al = int (len(values) * removeExtreme / 2)
            if al == 0 :
                raise Exception("removeExtreme has no impact (%d,%f)" % (len(values),len(values)*removeExtreme/2))
            if al*2 < len(values) :
                values = values [al:len(values)-al]
            
        mi      = min(values)
        ma      = max(values)
        W       = len(values)
        div     = (ma-mi) / nbDiv
        if div == 0 :
            raise RuntimeError("unable to continue since div is null: min,max = %f,%f" % (mi, ma))
        hist    = [ [ mi+n*div, 0.] for n in range (0,nbDiv+1) ]
        value   = { i:{histxName:hist[i][0]} for i in range(len(hist)) }
        su      = { }
        for row in self.values :
            for _ in columnsSet :
                temp = self._interpret_row(row)
                if math.isnan(temp[_]) or math.isinf (temp[_]) :
                    continue
                x = int ( (temp[_] - mi) // div )
                if x not in value : 
                    # it means extremes were removed
                    continue
                    #raise Exception("value %d,%f is not allowed min,max = [%f,%f]" % (x, temp[_], mi, ma))
                value [x][_] = value[x].get (_, 0.) + 1.
                su [_] = su.get(_, 0.) + 1.
                
        if normalize and W > 0 :
            for k,v in value.items () :
                for _ in v : 
                    if _ != histxName : v[_] /= su[_]
                
        tbl = self._private_getclass()("__byrow__", value)
        return tbl
        
    def union_columns (self, columnsSet) :
        """
        computes the union of all values from all columns present in columnSet
        @param      columnsSet      set of columns
        @return                     table
        """
        values  = [] 
        for row in self.values : 
            temp = self._interpret_row(row)
            for t in columnsSet : 
                values.append (temp[t])
        tbl = self._private_getclass()(["x"], [ [ x ] for x in values ])
        return tbl
        
    def mu_sigma (self, functionValues, removeExtreme = None) :
        """
        computes the average and the standard deviation a vector of values
        @param      functionValues      function produces the vector of values
        @param      removeExtreme       remove extreme values at both sides (0.05 means 0.025 on each side)
        @return                         (average, standard deviation)
        """
        if removeExtreme != None and removeExtreme > 0 :
            values = []
            for row in self.values :
                row = self._interpret_row(row)
                val = functionValues (row)
                values.append (val)
            values.sort()
            al = int (len(values) * removeExtreme / 2)
            if al == 0 :
                raise Exception("removeExtreme has no impact (%d,%f)" % (len(values),len(values)*removeExtreme/2))
            if al*2 < len(values) :
                values = values [al:len(values)-al]
            tbl = TableFormulaCore (["x"], [ [_] for _ in values] )
            return tbl.mu_sigma (lambda v : v ["x"], 0)
        else :
            mu = 0.
            si = 0.
            nb = 0.
            for row in self.values :
                row = self._interpret_row(row)
                val = functionValues (row)
                mu += val
                si += val**2
                nb += 1.
            mu /= nb
            si /= nb
            si -= mu**2
            return mu, si**0.5
            
    def mu_sigma_each_column (self, columnsSet = None, removeExtreme = None) :
        """
        returns a table with the average and the standard deviation for each columns
        @param      removeExtreme       remove extreme values at both sides (0.05 means 0.025 on each side)
        @param      columnsSet          set of column to deal with
        @return                         table with two rows: average and standard deviation
        """
        values = [ [], [] ]
        if columnsSet == None : columnsSet = self.header
        for col in columnsSet :
            mu,sigma = self.mu_sigma (lambda v : v [col], removeExtreme)
            values[0].append(mu)
            values[1].append(sigma)
        tbl = self._private_getclass()(columnsSet, values)
        return tbl
            
    @property 
    def np_matrix(self) :
        """
        returns the values as a numpy matrix
        @return         numpy matrix
        """
        return numpy.matrix(self.values)
        
    @property 
    def np_array(self) :
        """
        returns the values as a numpy array
        @return         numpy array
        """
        return numpy.array(self.values)
        
    @property
    def dataframe(self):
        """
        creates a pandas dataframe
        @return     pandas.dataframe
        """
        import pandas
        #
        #val = { }
        #for i,h in enumerate(self.header) :
        #    val [h] = [ row[i] for row in self.values ]
        #return pandas.DataFrame(val)
        return pandas.DataFrame(self.values, columns=self.header)
        
    @property
    def json(self):
        """
        returns a json format
        @return         string
        """
        rows = [ row for row in self ]
        return json.dumps(rows)
        
    def center_reduce (self, columnsSet     = None, 
                             op             = None, 
                             removeExtreme  = None,
                             mu_sigma       = None ) :
        """
        center and reduce a set of columns (or all if columnsSet is None)
        @param      removeExtreme       remove extreme values at both sides (0.05 means 0.025 on each side)
        @param      columnsSet          set of column to deal with
        @param      op                  if can be:
                                            - None:   substract mean and normalize,
                                            - "mean": substract mean only,
                                            - "norm": normalize only
        @param      mu_sigma            matrix with two rows (one for mean, second for sigma), if None,
                                        if computes that from the matrix self, columns must have the same order 
                                        that columnSet
        @return                         the same table (with only the considered columns)
        """
        if op not in [None, "mean", "norm"] :
            raise ValueError('expecting a value in [None, "mean", "norm"] for op')
        if columnsSet == None : columnsSet = self.header
        mus = self.mu_sigma_each_column(columnsSet, removeExtreme) if mu_sigma == None else mu_sigma
        tbl = self.extract_columns (columnsSet)
        n   = len(self.header)
        for row in tbl.values :
            if op == None or op == "mean" :
                for i in range(n) :
                    row[i] -= mus.values[0][i]
            if op == None or op == "norm" :
                for i in range(n) :
                    row[i] /= mus.values[1][i]
        return tbl
        
    def halpython(self, features, label_class):
        """
        builds table in a file which can be used to trained 
        a machine learned model using `hal_python <http://www.xavierdupre.fr/app/hal_python3/hal_python_help_html/index.html>`_.
        
        @param      features        list of columns considered as features
        @param      label_class     integer which contains the class to learn
        """
        mi      = min ( self.select ( lambda row : row [label_class] ) )
        ma      = max ( self.select ( lambda row : row [label_class] ) )
        de      = int(ma - mi + 1)
        columns = [ "keys"] + \
                  [ "x%d" % d for d in range(len(features)) ] + \
                  [ "p%d" % d for d in range(de) ]
        values = []
        def bin(e) : return 1.0 if e else 0.0
        for i,row in enumerate(self.values) :
            row = self._interpret_row(row)
            r  = [ "k%d"%i ] + [ row[c] for c in features ] 
            r += [ bin(row[label_class]-mi == c) for c in range(de) ]
            values.append(r)
        return self._private_getclass() (columns, values)
    
    @staticmethod
    def save_multiple_as_excel( filename, 
                            list_table,
                             font       = "Calibri",
                             close      = True,
                             encoding   = None):
        """
        saves multiple table in one Excel file

        @param      filename        filename (can be None)
        @param      list_table      list of 2uple ("name", tbl )
        @param      font            font name
        @param      close           if True, close the file, otherwise, the user will have to
        @param      encoding        encoding
        @return                     object Workbook
        """
        ext = os.path.splitext(filename)[-1].lower() if filename != None else None
        if ext != None and ext == ".xls" :
            font0 = EXf.Font()
            font0.name = font
            font0.bold = True
            style0 = EXs.XFStyle()
            style0.font = font0

            wb = EXw.Workbook(encoding = encoding) if encoding != None else EXw.Workbook()
            for sheetname, self in list_table :
                ws0 = wb.add_sheet(sheetname)
                
                for i,l in enumerate(self.header) :
                    ws0.write (0,i, l, style0)
                    
                fnt = EXf.Font()
                fnt.name = font
                style = EXs.XFStyle()
                style.font = fnt
                
                for irow, row in enumerate(self.values) :
                    for icol,val in enumerate(row) :
                        if isinstance (val, int) or isinstance (val, float) :
                            st = val
                        elif isinstance (val, str) :
                            if encoding != None :
                                st = val.encode(encoding).decode(encoding)
                            else : 
                                st = val
                        elif val != None :
                            st = str(val)
                        else :
                            continue
                        ws0.write(irow+1,icol, st, style)

            wb.save(filename)
            return wb
            
        elif ext == None or ext == ".xlsx" :
            wb = EXxw.Workbook(filename) if filename != None else EXxw.Workbook()
                # it does not work with xlsxwriter so, we open an existing one
                #_file = os.path.abspath(os.path.split(__file__) [0])
                #_file = os.path.join(_file, "..", "..", "code", "hofile", "unicode.xlsx")
                #if not os.path.exists (_file) :
                #    raise FileNotFoundError("unable to find a pre-existing excel file using unicode: " + _file)
                
            for sheetname, self in list_table :
                ws0 = wb.add_worksheet(sheetname)
                
                style0 = wb.add_format({'bold': True})
                style0.set_font_name(font)

                for i,l in enumerate(self.header) :
                    ws0.write (0,i, l, style0)
                    
                style = wb.add_format()
                style.set_font_name(font)
                
                for irow, row in enumerate(self.values) :
                    for icol,val in enumerate(row) :
                        if isinstance (val, int) or isinstance (val, float) :
                            st = val
                        elif isinstance (val, str) :
                            if encoding != None :
                                st = val.encode(encoding).decode(encoding)
                            else : 
                                st = val
                        elif val != None :
                            st = str(val)
                        else :
                            continue
                        ws0.write(irow+1,icol, st, style)

            if filename != None and close: 
                wb.close()
            return wb
            
        else :
            raise NameError("extension should be .xls or .xlsx for file " + filename)
        
    def save_as_excel (self, filename, 
                             font       = "Calibri",
                             sheetname  = "sheet0",
                             close      = True,
                             encoding   = None
                             ) :
        """
        saves the table as a new Excel file, you can use ``.xls`` or ``.xlsx``
        if filename is None, the function returns an object (xslx) and does not save it.
        
        @param      filename        Excel filename
        @param      sheetname       name of the sheet to add
        @param      font            font name
        @param      close           if True, close the file, otherwise, the user will have to
        @param      encoding        encoding
        @return                     object Workbook
        """
        return TableFormulaCore.save_multiple_as_excel( filename, [ (sheetname, self) ],
                    font = font, close = close, encoding = encoding)
            
    def schema_database(self, add_id = True):
        """
        returns the schema for a database which would contains this database
        
        @param      add_id      if True, adds an index "PRIMARYKEY"
        @return                 dictionary { index_column: (name, type) }
        """
        schema = { i:(l,str) for i,l in enumerate(self.header) }
        if add_id != None :
            schema [-1] = (add_id, int, "PRIMARYKEY", "AUTOINCREMENT")
            
        if len(self) > 0 :
            # we use the first row to determine type
            for i,v in enumerate(self.values[0]) :
                if not isinstance(v,str) :
                    schema [i] = (schema[i][0], type(v) )
        return schema
        
    def fill_sql_table (self, filename_or_database, tablename, add_id = "idr") :
        """
        returns a Database object, creates the database if it does not exists,
        same for the table
        
        @param      filename_or_database    filename or Database object, 
                                                in that second case, we assume method connect was called before
        @param      tablename               table name
        @param      add_id                  if != None, then the function adds an id, it first takes the 
                                            max(id) and goes on incrementing it;
        @return                             Database object (new or the one from the parameters),
                                            in both case, the database is not disconnected
        """
        
        schema = self.schema_database(add_id)
                    
        if isinstance(filename_or_database, str) :
            HalLOG("fill_sql_table: creating database ", filename_or_database)
            db = Database(filename_or_database, LOG = fLOG)
            db.connect()
            
            HalLOG ("fill_sql_table ", schema)
            if tablename not in db.get_table_list () : 
                HalLOG ("creationg of table ", schema)
                cursor = db.create_table (tablename, schema)
                db.append_values ( self.values, tablename, schema, cursor = cursor)
            else :
                db.append_values ( self.values, tablename, schema)
        else :
            db = filename_or_database
            db.append_values ( self.values, tablename, schema)
        
        return db
        

graphes sous MatPlotLib

#coding:utf8
"""
@file
@brief  Contains TableFormulaGraph which inherits from TableFormulaCore.

.. requires matplotlib

"""

from inspect import isfunction
import copy, os, os.path, sys, datetime, random, math, datetime

from  ..             import HalLOG
from .tableformula   import TableFormulaCore
fileprint = HalLOG


## constant
global_default_figsize = (10,10)



class TableFormulaGraph (TableFormulaCore) :
    """
    
    .. requires matplotlib
    
    Extension of TableFormulaCore, add graph method to the core class. 
    The class contains basic graphs for frequent graphs. I switch from 
        - matplotlib (which crashes when you ask formore than 50 graphs),
        - Gnuplot (not yet)
        - d3js  (not yet)
        - hal_python (something fast but not very appealing)
        - hal_python_mat (same graph hal_python but converted into a matplotlib graw, it may not work)
        
    You can see below some examples:

    @image hal_python_ex_img.png
    
    
        
    Example:
    @code
    print ("--------- graph XY")
    table = TableFormula ("name sum_a sum_b sum_c#A 1 2 3#A 1.1 2.1 3.1#B 3 4 5".replace(" ", "\t").replace("#","\\n"))
                         
    print ("--------- graph XY hal_python")
    table.graph_XY ( [ [ lambda v: v["sum_a"], lambda v: v["sum_b"], "xy label 1"],
                      [ lambda v: v["sum_b"], lambda v: v["sum_c"], "xy label 2"],
                        ],
                     outImage = "image_XY.hal.png",
                     layout = "hal_python").Display()
        
    table.graph_XY ( [ [ lambda v: v["sum_a"], lambda v: v["sum_b"], lambda v: str(v["sum_b"]), "xy label 1"],
                      [ lambda v: v["sum_b"], lambda v: v["sum_c"], "xy label 2"],
                        ],
                     outImage = "image_XY.hal2.png",
                     layout = "hal_python", show=True)
        
                     
    print ("--------- graph XY matplotlib")
    table.graph_XY ( [ [ lambda v: v["sum_a"], lambda v: v["sum_b"], "xy label 1"],
                      [ lambda v: v["sum_b"], lambda v: v["sum_c"], "xy label 2"],
                        ],
                     outImage = "image_XY.png")    
                     
    print ("--------- graph distribution")
    values = [ [ x*0.1, math.exp(-x*0.1) ] for x in range (0,50) ]
    table  = TableFormula (["X", "Y"], values)
    table.graph_distribution ( lambda v: v["X"], lambda v: v["Y"],
                    outImage = "image_distribution.png",
                    title = "distribution")

    print ("--------- graph XY and dates")
    values = [ [ datetime.datetime (2013,1,x,1,2,4), math.exp(-x/10.)  ] for x in range (1,32) ]
    table  = TableFormula (["date", "Y"], values)
    table.graph_XY ( [ [ lambda v: v["date"], lambda v: v["Y"], "date Y"] 
                        ],
                     outImage = "image_XY_dates.png")    

    print ("--------- graph bar")
    values = [ [ datetime.datetime (2013,1,x,1,2,4), 
                 math.exp(-x/10.),
                 math.exp(-x/5.),
                 "label %d" % x
                 ] for x in range (1,32) ]
    table  = TableFormula (["date", "Y", "Y2", "xl"], values)
    
    table.graph_bar ( None, 
                        [ [ lambda v: v["Y"], "Y"],  
                          [ lambda v: v["Y2"], "Y2"] ],
                     outImage = "image_bar.png")    

    print ("--------- graph bar, x label")
    table.graph_bar ( lambda v: v ["xl"], 
                        [ [ lambda v: v["Y"], "Y"],  
                          [ lambda v: v["Y2"], "Y2"] ],
                     outImage = "image_bar_xlabel.png")    

    print ("--------- graph bar dates")
    table.graph_bar ( lambda v: v ["date"], 
                        [ [ lambda v: v["Y"], "Y"],  
                          [ lambda v: v["Y2"], "Y2"] ],
                     outImage = "image_bar_dates.png")    
                     
    print ("--------- show the last one")
    TableFormula.importmodules()
    plt = sys.modules["matplotlib.pyplot"]
    plt.show()
    @endcode
    """

    # keep track of produced graphs
    privateGraphStory = []
    
    def __init__ (self, file, 
                        numeric_column  = [], 
                        sep             = "\t",
                        encoding        = None,
                        read_n_lines    = -1,
                        sheet           = 0,
                        **options) :
        """
        constructor, see `TableFormulaCore.__init__ <pyhome3.srcpyhome.tables.tableformulas.tableformula.TableFormulaCore.__init__>`
        """
        if isinstance(file, TableFormulaCore) :
            TableFormulaCore.__init__ (self, file.header, file.values, **options)
        else :
            TableFormulaCore.__init__ (self, file = file, 
                                             numeric_column = numeric_column, 
                                             sep = sep, 
                                             encoding = encoding,
                                             read_n_lines = read_n_lines,
                                             sheet = sheet,
                                             **options) 

    def importmodules () :
        if "pylab" not in sys.modules :
            import pylab
            import matplotlib
            import matplotlib.pyplot as plt
        if "numpy" not in sys.modules :
            import numpy
    importmodules = staticmethod(importmodules)
    
    def ShowLastGraph () :
        TableFormulaGraph.importmodules()
        plt = sys.modules["matplotlib.pyplot"]
        plt.show()           
    ShowLastGraph = staticmethod(ShowLastGraph)
    
    def privateBeginGraph () :
        TableFormulaGraph.importmodules()
        matplotlib  = sys.modules["matplotlib"]
        plt         = sys.modules["matplotlib.pyplot"]
        np          = sys.modules["numpy"]
        if len(TableFormulaGraph.privateGraphStory) > 0 :
            plt.close()
        return plt, np, matplotlib
    privateBeginGraph = staticmethod(privateBeginGraph)
        
    def privateEndGraph (plt, fig, ax, outImage, xlabel, ylabel, title) :
        if xlabel != None : plt.xlabel(xlabel)
        if ylabel != None : plt.ylabel(ylabel)
        if title  != None : ax.set_title(title)
        
        if outImage == None : 
            plt.show()
        else :
            plt.savefig(outImage)
        TableFormulaGraph.privateGraphStory.append (fig)
    privateEndGraph = staticmethod(privateEndGraph)
    
    def private_GetHalPython():
        if "hal_python" not in sys.modules : 
            import hal_python
            hal_python.Begin()
        return sys.modules["hal_python"]
    private_GetHalPython = staticmethod(private_GetHalPython)
    
    def graph_XY (self,  curves,
                        outImage    = None,
                        xlabel      = None,
                        ylabel      = None,
                        marker      = True,
                        linkPoint   = False,
                        title       = None,
                        formatDate  = "%Y-%m-%d",
                        legendLoc   = 0,
                        figsize     = global_default_figsize,
                        layout      = "matplotlib",
                        show        = False,
                        **params
                        ) :
        """
        @param      curves      list of 3-uples (generator for X, generator for Y, label)
                                for some layout, it can also be: 
                                (generator for X, generator for Y, generator for labels, label)
        @param      outImage    a filename if you want to save it as an image
        @param      xlabel      label for X axis
        @param      ylabel      label for Y axis
        @param      marker      add a marker for each point
        @param      linkPoint   link points between them
        @param      title       graph title
        @param      formatDate  if X axis is a datetime object, the function will use this format
                                to print dates
        @param      legendLoc   location of the legend
        @param      figsize     size of the figure
        @param      layout      type of graphs (could be matplotlib, gnuplot, hal_python, hal_python_mat, d3js)
        @param      show        if True, opens a window to show the graph
        @param      params      extra parameters (depends on the layout):
                                    - hal_python:
                                    - label_is_class: a color for every distinct label
        @return                 an object
        
        @warning    Only matploblib is implemented.
                                        
        
        for the legend position, see `matplotlib <http://matplotlib.org/api/legend_api.html>`_.
        
        example:
        @code
        table.graph_XY ( [ [ lambda v: v["sum_a"], lambda v: v["sum_b"], "xy label 1"],
                          [ lambda v: v["sum_b"], lambda v: v["sum_c"], "xy label 2"],
                            ],
                         outImage = "image.png")
        @endcode
        """
        
        if layout == "matplotlib" :
            HalLOG("graph_XY: layout: ", layout)
            plt, np, matplotlib = TableFormulaGraph.privateBeginGraph()
            smarker = { (True,  True) :'o-',
                        (True,  False):'o',
                        (False, True) :'-',
                        #(False, False) :''
                        } [ marker, linkPoint ]
            fig     = plt.figure(figsize = figsize)
            ax      = fig.add_subplot(111)
            allvalues = []

            for xf,yf,label in curves :
                x = [ xf (self._interpret_row(row)) for row in self.values ]
                y = [ yf (self._interpret_row(row)) for row in self.values ]
                x = [ _ for _ in x if _ != None ]
                y = [ _ for _ in y if _ != None ]
                ax.plot(x, y, smarker, label = label)
                allvalues += x

            if isinstance (allvalues[0], datetime.datetime) :
                hfmt = matplotlib.dates.DateFormatter(formatDate)
                if "%H" in formatDate or "%M" in formatDate :
                    ax.xaxis.set_major_locator(matplotlib.dates.MinuteLocator())
                ax.xaxis.set_major_formatter(hfmt)
                fig.autofmt_xdate()

            plt.legend (loc=legendLoc)
            TableFormulaGraph.privateEndGraph(plt, fig, ax, outImage, xlabel, ylabel, title)
            if show : TableFormulaGraph.ShowLastGraph()
            
        elif layout in ["hal_python", "hal_python_mat"] :
            HalLOG("graph_XY: layout: ", layout)
            hal = TableFormulaGraph.private_GetHalPython()
            pl = None
            for curve in curves :
                
                xf,yf = curve[:2]
                vx = [ xf (self._interpret_row(row)) for row in self.values ]
                vy = [ yf (self._interpret_row(row)) for row in self.values ]
                
                scatter = not isinstance(vx[0],str)
                
                if len(curve) == 4 and isfunction(curve[2]) :
                    lf = curve[2]
                    la = [ lf (self._interpret_row(row)) for row in self.values ] 
                else :
                    la = [ ]
                    
                ti   = curve[-1] 
                link = 2 if linkPoint else 1
                mark = [] if not marker else ([ 4 for _ in vx ])
                
                if params.get("label_is_class", False) :
                    if pl == None :
                        if scatter : pl = hal.PlotObject()
                        else : pl = hal.PlotObject(vx)

                    names = { }
                    for l in la : names[l] = names.get(l, len(names))
                    names = list(names.keys())
                    names.sort()
                    index = { n:i for i,n in enumerate(names) }
                    la = [ index[_] for _ in la ]
                    names = [ "%s-%s" % (ti, _) for _ in names ]
                    pl.AddClass(names, la, list(range(len(vy))), vy, 
                                        link, label = vx, size = mark)
                else :
                    if pl == None : pl = hal.PlotObject()
                    pl.Add(ti, vx, vy, link, label = la, size = mark)
                
            mpl = 0
            if layout == "hal_python_mat" : mpl = 1
            if figsize != None and figsize != global_default_figsize :  
                im = pl.GetImage(size = figsize, matplotlib = mpl)
            else : 
                im = pl.GetImage(matplotlib = mpl)
                
            if outImage != None : im.Save(outImage)
            if show : 
                im.Display()
                hal.Pause()
            return pl
            
        elif layout == "gnuplot" :
            
            """
            set term png
            set output "temp/image_gnu.png"
            set grid
            ###
            plot \\
                "temp/series0.txt" title "dec ----" with points axis x1y1,\\
                "temp/series1.txt" title "dec -no" with points axis x1y1,\\
                "temp/series2.txt" title "dec -yes" with points axis x1y1
            exit
            """
            raise NotImplementedError("layout %s is not available yet" % layout)
            
        else :
            raise NotImplementedError("layout %s is not available yet" % layout)

    def graph_distribution (self,  x, y,
                        outImage    = None,
                        xlabel      = None,
                        ylabel      = "%",
                        title       = None,
                        figsize     = global_default_figsize,
                        layout      = "matplotlib",
                        show        = False,
                        ) :
        """
        @param      x           generator for X
        @param      y           generator for Y
        @param      outImage    a filename if you want to save it as an image
        @param      xlabel      label for X axis
        @param      ylabel      label for Y axis
        @param      title       graph title
        @param      figsize     size of the figure
        @param      layout      type of graphs (could be matplotlib, gnuplot, hal_python, d3js)
        @param      show        if True, opens a window to show the graph
        
        @warning    Only matploblib is implemented.


        Example:
        @code
        table.graph_distribution (  lambda v: v["X"], 
                                    lambda v: v["Y"],
                                    outImage = "imageDistribution.png")
        @endcode
        """
        if layout == "matplotlib": 
            plt, np, matplotlib = TableFormulaGraph.privateBeginGraph()
            x       = [ x(self._interpret_row(row)) for row in self.values ]
            y       = [ y(self._interpret_row(row)) for row in self.values ]
            x       = [ _ for _ in x if _ != None ]
            y       = [ _ for _ in y if _ != None ]
            dx      = (x[-1] - x[0]) / (len(x)-1)
            left    = np.array( [ _ for _ in x ] )
            right   = np.array( [ _ for _ in x[1:] ] + [ x[-1] + dx ] )
            bottom  = np.zeros(len(left))
            top     = bottom + np.array(y)
            fig     = plt.figure(figsize = figsize)
            ax      = fig.add_subplot(111)
            XY      = np.array([[left,left,right,right], [bottom,top,top,bottom]]).T
            barpath = matplotlib.path.Path.make_compound_path_from_polys(XY)
            patch   = matplotlib.patches.PathPatch(barpath, facecolor='blue', edgecolor='gray', alpha=0.8)
            ax.add_patch(patch)
            ax.set_xlim(left[0], right[-1])
            ax.set_ylim(bottom.min(), top.max())
            TableFormulaGraph.privateEndGraph(plt, fig, ax, outImage, xlabel, ylabel, title)
            if show : TableFormulaGraph.ShowLastGraph()
        else :
            raise NotImplementedError("layout %s is not available yet" % layout)

    def graph_bar (self,  xf,
                        curves,
                        outImage    = None,
                        xlabel      = None,
                        ylabel      = None,
                        title       = None,
                        formatDate  = "%Y-%m-%d",
                        legendLoc   = 0,
                        figsize     = global_default_figsize,
                        layout      = "matplotlib",
                        show        = False,
                        ) :
        """
        @param      xf          generator for X
        @param      curves      list of 2-uples (generator for Y, label)
        @param      outImage    a filename if you want to save it as an image
        @param      xlabel      label for X axis
        @param      ylabel      label for Y axis
        @param      title       graph title
        @param      formatDate  if X axis is a datetime object, the function will use this format
                                to print dates
        @param      legendLoc   location of the legend
        @param      figsize     size of the figure
        @param      layout      type of graphs (could be matplotlib, gnuplot, hal_python, d3js)
        @param      show        if True, opens a window to show the graph
        
        @warning    Only matploblib is implemented. For the legend position, see `matplotlib <http://matplotlib.org/api/legend_api.html>`_.

        
        Example:
        @code
        table.graph_bar ( lambda v: v ["xl"], 
                            [ [ lambda v: v["Y"], "Y"],  
                              [ lambda v: v["Y2"], "Y2"] ],
                         outImage = "image_bar_xlabel.png")    
        @endcode
        """
        if layout == "matplotlib" :
            plt, np, matplotlib = TableFormulaGraph.privateBeginGraph()
            fig     = plt.figure(figsize = figsize)
            ax      = fig.add_subplot(111)
            wei     = 0.9 / len(curves)
            colors  = ['g', 'orange', 'b', 'c', 'r', 'y']
            nb      = 0
           
            for yf,label in curves :
                y = [ yf (self._interpret_row(row)) for row in self.values ]
                x = [nb*wei + _ for _ in range(0,len(y)) ]
                y = [ _ for _ in y if _ != None ]
                x = [ _ for _ in x if _ != None ]
                ax.bar(x, y, label = label, width=wei, color = colors[nb%len(colors)])
                nb += 1
            if xf != None :
                x = [ xf (self._interpret_row(row)) for row in self.values ]
                if isinstance (x[0], datetime.datetime) :
                    x = [ _.strftime(formatDate) for _ in x ]
                x = [ _ for _ in x if _ != None ]
                ax.set_xticks(range(0,len(x)))
                ax.set_xticklabels( x )
                labels = ax.get_xticklabels()
                plt.setp(labels, rotation=30, fontsize=10)
            plt.legend (loc=legendLoc)
            TableFormulaGraph.privateEndGraph(plt, fig, ax, outImage, xlabel, ylabel, title)            
            if show : TableFormulaGraph.ShowLastGraph()
        else :
            raise NotImplementedError("layout %s is not available yet" % layout)
        
        
    

résolution d'un sudoku (fonctions)



s = [[0, 0, 0, 3, 0, 0, 8, 0, 0], \
     [0, 0, 7, 9, 0, 8, 0, 0, 5], \
     [0, 0, 0, 2, 0, 4, 1, 0, 0], \
     [0, 9, 0, 8, 1, 0, 0, 4, 7], \
     [0, 4, 0, 0, 0, 0, 0, 0, 6], \
     [0, 0, 0, 0, 0, 0, 0, 0, 0], \
     [0, 1, 0, 0, 0, 5, 0, 2, 0], \
     [5, 3, 4, 0, 0, 0, 0, 0, 0], \
     [0, 0, 0, 7, 0, 0, 0, 0, 0]]




i = 0
j = 1

def chiffre_barre_ligne (s,r,i) :
    for k in range (0,9) :
        if s [i][k] > 0 :
            r [ s [i][k]-1 ] = 0

def chiffre_barre_colonne (s,r,j) :
    for k in range (0,9) :
        if s [k][j] > 0 :
            r [ s [k][j]-1 ] = 0


def chiffre_barre_carre (s,r,i,j) :
    a = i/3 * 3
    b = j/3 * 3
    for k in range (a,a+3) :
        for l in range (b,b+3) :
            if s [k][l] > 0 :
                r [ s [k][l]-1 ] = 0

def nombre_possible (s,i,j ) :
    r = [ 1,1,1,1,1,1,1,1,1]
    chiffre_barre_ligne (s,r,i)
    chiffre_barre_colonne (s,r,j)
    chiffre_barre_carre (s,r,i,j)
    return r

def meilleure_case (s ) :
    dmin = 10
    imin = jmin = -1
    rmin = []
    for i in range (0,9) :
        for j in range (0,9) :
            if s [i][j] == 0 :
                r = nombre_possible (s,i,j)
                d = sum (r)
                if d < dmin :
                    dmin = d
                    imin = i
                    jmin = j
                    rmin = r
    return imin,jmin,rmin







def resolution (s) :
    imin,jmin,rmin = meilleure_case (s)
    if imin == -1 :
        return "jackpot"
    d = sum (rmin)
    if d == 1 :
        p = rmin.index (1)
        s [imin][jmin] = p+1
        print "s modifie ",imin,jmin,p+1
        a = resolution (s)
        if a == 0 :
            s [imin][jmin] = 0
            return 0
        else :
            return 1
    elif d == 0 :
        print "on s'arrete"
        return 0
    elif d > 1 :
        print "on continue"
        for n in range (0, 9) :
            if rmin [n] == 1 :
                s [imin][jmin] = n+1
                a = resolution (s)
                if a == 0 :
                    s [imin][jmin] = 0
                else :
                    return 1
        return 0

resolution (s)

for i in range (0,9) :
    print s[i]



résolution d'un sudoku (classes)

import copy
import psyco

psyco.full ()

class Sudoku :
    """definition d'un sudoku"""
    def __init__ (self, tab) :
        """tab est soit un entier indiquant la dimension du sudoku ou
        le sudoku lui-même"""
        try :
            i = tab [0][0] 
            self.tab = tab
            self.dim = len (tab)
        except :
            self.dim = tab
            self.tab = [ [ 0 for i in range (0,self.dim) ] \
                            for j in range (0,self.dim) ]
        
        
    def __str__ (self) :
        """affiche un sudoku"""
        s = ""
        for i in range (0,self.dim) :
            if i % 3 == 0 and i > 0 : s += "\t------------------------------------------\n"
            s += "\t"
            for j in range (0,self.dim) :
                if j % 3 == 0 and j > 0 : s += "|\t" 
                if self.tab [i][j] == 0 : s += "."
                else : s += str (self.tab [i][j])
                s += "\t"
            s += "\n"
        return s
        
    def __getitem__ (self, p) :
        """retourne l'élément p [0], p [1] du sudoku"""
        return self.tab [p [0]][p [1]]
        
    def __setitem__ (self, p, v) :
        """change l'élément p [0], p [1] du sudoku"""
        self.tab [p [0]][p [1]] = v
        
    def filled (self) :
        """retourne le nombre de cases non vides"""
        n = 0
        for i in range (0, self.dim) :
            for j in range (0, self.dim) :
                if self [ (i,j) ] > 0 : n += 1
        return n
        
    def possible (self, i, j) :
        """retourne l'ensemble des nombres possibles pour 
        pour la case i,j"""
        
        # vérification des contraintes sur les lignes et les colonnes
        if self.tab [i][j] > 0 : return []
        se = []
        for k in xrange (0, self.dim) :
            if self.tab [i][k] > 0 :
                se.append (self.tab [i][k])
            if self.tab [k][j] > 0 :
                se.append (self.tab [k][j])
                
        # vérification des contraintes dans chaque petit carré
        ii = int (i / 3)
        jj = int (j / 3)
        for iii in range (ii * 3, (ii+1)*3) :
            for jjj in range (jj * 3, (jj+1)*3) :
                if self.tab [iii][jjj] > 0 :
                    se.append (self.tab [iii][jjj])
        

        sol = []
        for n in xrange (1, self.dim+1) :
            if n not in se : sol.append (n)
                
        return sol
        
    def get_best_solution (self, error = []) :
        """retourne la meilleure case à essayer, celle pour laquelle
        l'ensemble des nombres possibles est le plus petit :
         - 0 chiffre  : configuration impossible, résultat = None
         - 1 chiffre  : on avance, résultat = (i,j,[ c] )
         - n > 1 chiffres : on essaye l'ensemble le moins grand,
                    résultat = (i,j,[ c1, c2, c3, ...] )
        """
        
        # on regarde d'abord si c'est impossible
        for i in xrange (0,self.dim) :
            for j in xrange (0,self.dim) :
                if self.tab [i][j] > 0 : continue
                b = self.possible (i,j)
                if len (b) == 0 :
                    return None
                
        # sinon
        best = None
        pos = None
        
        for i in xrange (0,self.dim) :
            for j in xrange (0,self.dim) :
                if (i,j) in error : continue
                b = self.possible (i,j)
                if len (b) == 1 :
                    # une case où il y a une seule possibilité
                    return (i,j,b)
                elif len (b) > 1 :
                    # plusieurs possibilités, on prend l'ensemble le plus petit
                    if best == None or len (best) > len (b) :
                        pos = (i,j)
                        best = b

        # résultat
        if best == None : 
            return None
        else : return (pos [0], pos [1], best)
                
            
        

class EnigmeSudoku :
    """résolution d'un Sudoku"""
    
    def __init__ (self, sudoku, display = True) :
        """définition de la classe qui résoud le Sudoku"""
        self.sudoku = sudoku
        
    def __str__ (self) :
        return str (self.sudoku)
            
    def resoud (self, solutioni = None) : # solution = [ ]) :
        """resolution, exploration en profondeur,
        fonction recursive"""
        
        if solutioni == None :
            # cas simple : première itération
            solutioni = copy.deepcopy (self.sudoku)
            self.count = 0
        elif solutioni.filled () == solutioni.dim ** 2 :
            # second simple : le sudoku est terminé
            return solutioni
        
        solution = copy.deepcopy (solutioni)

        # pour compter le nombre d'itérations
        self.count += 1
            
        # retourne la case la plus sympathique
        next = solutioni.get_best_solution ()
        
        # s'il existe une case impossible
        if next == None : return None
            
        # sinon on essaye toutes les solutions pour cette case
        for n in next [2] :
            solution [ (next [0], next [1]) ] = n
            res = self.resoud (solution)
            if res != None : 
                # réussi
                return res
                    
        # toutes les solutions pour cette case mènent à une impasse
        return None
        

if __name__ == "__main__" :

    sudoku_exemple = [ \
              [5,3,0,0,7,0,0,0,0], \
              [6,0,0,1,9,5,0,0,0], \
              [0,9,8,0,0,0,0,6,0], \
              [8,0,0,0,6,0,0,0,3], \
              [4,0,0,8,0,3,0,0,1], \
              [7,0,0,0,2,0,0,0,6], \
              [0,6,0,0,0,0,2,8,0], \
              [0,0,0,4,1,9,0,0,5], \
              [0,0,0,0,8,0,0,7,9]]

    s = Sudoku (sudoku_exemple)
    print s
    print "-----------------------------\n"


    en = EnigmeSudoku (s)
    print "-----------------------------\n"
    sol = en.resoud ()
    print "-----------------------------\n"
    print "iteration ", en.count
    print sol
    print "fin"
   

File: puzzle_girafe.tex, line 72


def compatible (self, bord) :
    return self.couleur == bord.couleur and self.partie != bord.partie

File: puzzle_girafe.tex, line 102


def voisin_possible (self, p, a) :
    d = p.position - self.position
    if abs (d) == 1 and (p.position - 1) / 3 == (self.position - 1) / 3 :
        # voisin en x
        return True
    elif abs (d) == 3 :
        # voisin en y
        return True
    else :
        # pas voisin
        return False

File: puzzle_girafe.tex, line 149


HOBBBVHM
HOBBBVHM
HBBMBVHO
HMBBBVHB
BMBOHBHV
HVBMBOHM
BMBVHBHO
HVHMBBBO
BMHOHVBB

File: puzzle_girafe.tex, line 176


def piece_position (self, pos) :
    for p in self.piece :
        if p.position == pos :
            return p
    return None

File: puzzle_girafe.tex, line 192


def ensemble_voisin (self, i) :
    i -= 1
    res = []
    for x in [-1,0,1] :
        for y in [-1,0,1] :
            if abs (x) == abs (y) : continue
            if x == -1 and i % 3 == 0 : continue
            if x == 1  and i % 3 == 2 : continue
            if y == -1 and i / 3 == 0 : continue
            if y == 1  and i / 3 == 2 : continue
            j = i + x + y * 3
            if j in range (0,9) :
                res.append (j)
    return [ j+1 for j in res ]

File: puzzle_girafe.tex, line 218


def angle_possible (self, p, display = False) :
    voisin = self.ensemble_voisin (p.position)
    if display :
        print "voisin = ", voisin
    res = []
    for a in [0,90,180,270] :
        r = True
        for v in voisin :
            piece = self.piece_position (v)
            if piece != None :
                r = r and piece.voisin_possible (p, a)
        if r :
            res.append (a)
    return res

ensemble des permutations

# coding: latin-1
def echange (l, i, j) :
    """permutation des éléments i et j de la liste l"""
    t       = l [i]
    l [i]   = l [j]
    l [j]   = t
    
def applique_permutation (set, p) :
    """applique la permutation p à l'ensemble set"""
    return [ set [k-1] for k in p ] 
    
def permutation (n) :
    if n == 1 : return [ [ 1 ] ]
    else :
        per = permutation (n-1)             # permutation sur {1,...,n-1}
        set = [ i+1 for i in range (0,n) ]  # ensemble de départ
        res = []                            # résultat
        
        for i in range (0, n) :
            echange (set, 0, i)             # échange élément 0 et i
            for p in per :                  # boucle sur les permutations de {1,...,n-1}
                pr  = [ set [0] ] + applique_permutation ( set [1:], p )
                res.append (pr)             # on l'ajoute au résultat
            echange (set, 0, i)             # échange élément 0 et i
            
        return res
        
print (permutation (1)) # retourne [ [ 1 ] ]
print (permutation (2)) # retourne [[1, 2], [2, 1]]
print (permutation (3)) # retourne [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2]]

résolution d'un puzzle

# coding: cp1252
import pygame
import random
import copy
import time

class Bord :
    """définition d'un bord ou côté d'une pièce, il possède :
       - partie : une partie de la girafe (haut ou bas)
       - une couleur : la couleur de cette partie, (orange, violet, bleu clair, bleu foncé)
    """
    
    def __init__ (self, definition) :
        """definition est une chaîne de 2 caractères qui définit un bord, exemple :
            HO pour haut orange
            BB pour bas bleu
            BV pour bas violet
            HM pour haut mauve
        """
        
        if   definition [0] == "H" : self.partie = "haut" 
        elif definition [0] == "B" : self.partie = "bas"
        else :                       self.partie = definition + "###"
            
        if   definition [1] == "O" : self.couleur = "orange"
        elif definition [1] == "B" : self.couleur = "bleu clair"
        elif definition [1] == "M" : self.couleur = "violet"
        elif definition [1] == "V" : self.couleur = "bleu fonce"
        else :                       self.couleur = definition + "##"
        
    def __str__ (self) :
        """cette méthode est appelée lorsqu'on exécute l'instruction print
        avec un objet de type Bord"""
        s = self.partie + " " + self.couleur
        return s
        
    def compatible (self, bord) :
        """dit si deux bords sont compatibles, c'est à dire
        de la même couleur et de partie différente"""
        return self.couleur == bord.couleur and self.partie != bord.partie

        
class Piece :
    """définition d'une pièce du puzzle, celle-ci inclut :
      - bord : cette liste contient quatre objets de type Bord, cette liste ne changera plus
      - position    : c'est la position de la pièce dans le puzzle, ce qui nous intéresse,
                        c'est la position finale de la pièce dans le puzzle, cette information 
                        va donc bouger au fur et à mesure que nous allons essayer de 
                        résoudre le puzzle
      - orientation : de même que pour la position, une pièce peut être tournée sans changer de
                        position, c'est le résultat final qui nous intéresse
                        
    pour l'affichage, on ajoute deux informations :
      - name  : le nom de l'image de la pièce
      - image : c'est la représentation de l'image dans la mémoire de 
                    l'ordinateur pour le module pygame
    """
    
    def __init__ (self, name, definition, position, numero) :
        """ on définit la pièce
           - name : nom de l'image représentant la pièce
           - definition : chaîne de 8 caractères, c'est une suite de 4 x 2 caractères définissant 
                            chaque bord, voir la classe bord pour leur signification
           - position   : c'est la position initiale de la pièce, on suppose que 
                            l'orientation est nulle pour commencer
        
        à partir de ces informations, on construit :
          - image       : c'est la représentation en mémoire de l'image de la pièce
          - bord        : c'est une liste qui définit les 4 bords de la pièce
          - orientation : c'est l'orientation de la pièce, au début de la résolution, elle est nulle
        """
        
        self.name           = name 
        image               = pygame.image.load (name)
        self.image          = pygame.transform.scale (image, (250,250))
        s                   = self.image.get_size ()
        self.image_petite   = pygame.transform.scale (self.image,  (int(s[0]*0.7), int(s[1]*0.7)))
        self.bord           = []
        
        for i in range (0,4) :
            self.bord.append ( Bord (definition [i*2:i*2+2] ) )
            
        self.orientation    = 0
        self.position       = position
        self.numero         = numero
        
    def __str__ (self) :
        """définition ce qu'on doit afficher lorsqu'on exécute 
        l'instruction print avec un objet de type Piece"""
        s = str (self.position) + " : "
        for b in self.bord :
            s += str (b) + " - "
        s += " orientation " + str (self.orientation)
        s += " numero " + str (self.numero)
        return s
        
    def affiche (self, screen, position) :
        """affiche la pièce à l'écran en tenant compte de sa position et de son orientation"""
        if "darker" in self.__dict__ and self.darker :
            position = ( position [0] + 20, position [1] + 20 )
            image    = pygame.transform.rotate (self.image_petite, self.orientation)
            screen.blit (image, position)
        else :
            image = pygame.transform.rotate (self.image, self.orientation)
            screen.blit (image, position)
        
    def bord_angle (self, angle, orientation = None) :
        """retourne le bord connaissant l'orientation de la pièce,
        le bord demandé est celui correspondant à :
           - 0  bord droit
           - 90 bord haut
           - 180 bord gauche
           - 270 bord bas"""
        if orientation == None : return self.bord_angle (angle, self.orientation)
        else : 
            dif = (angle - orientation + 360) % 360 / 90
            return self.bord [dif]
        
    def voisin_possible (self, p, a) :
        """détermine si la pièce self peut être voisine avec la pièce p tournée de l'angle a"""
        d = p.position - self.position
        if abs (d) == 1 and (p.position - 1) / 3 == (self.position - 1) / 3 :
            # voisin en x
            if d == 1 :
                a1 = 0
                a2 = a1 + 180
            else :
                a1 = 180
                a2 = 0
        elif abs (d) == 3 :
            # voisin en y
            if d == 1 :
                a1 = 90
                a2 = 270
            else :
                a1 = 270
                a2 = 90
        else :
            # pas voisin
            return False
        
        b1 = self.bord_angle (a1)
        b2 = p.bord_angle (a2, a)
        return b1.compatible (b2)
        
        
class Puzzle :
    """définition d'une classe puzzle, elle contient simplement 
    une liste de 9 pièces dont les positions sont :
    1 2 3
    4 5 6
    7 8 9
    et les orientations choisies dans l'ensemble { 0,90,180,270 }
    """
    
    
    def __init__ (self, dir = ".") :
        """on définit le puzzle à partir des informations contenus 
        dans le répertoire dir qui doit contenir :
        - 9 images appelées piece0.png, ..., piece1.png
        - un fichier definition.txt contenant la définition de 
          chacun des 4 bords de chacune des 9 pièces
                            HOBBBVHM
                            HOBBBVHM
                            HBBMBVHO
                            HMBBBVHB
                            BMBOHBHV
                            HVBMBOHM
                            BMBVHBHO
                            HVHMBBBO
                            BMHOHVBB        
        """
        
        # on lit définition.txt
        f = open (dir + "/definition.txt")
        bo = f.readlines ()
        f.close ()
        
        # on définit chaque pièce
        self.piece = []
        for i in range (1,10) :
            name    = dir + "/piece" + str (i) + ".png"
            d       = bo [i-1]
            p       = Piece (name, d, 0, i)
            self.piece.append ( p )
            
    def __str__ (self) :
        """ce qu'on doit afficher lorsqu'on exécute 
        l'instruction print avec un objet de type Puzzle"""
        s = """1 2 3
4 5 6
7 8 9
"""
        for p in self.piece :
            s += str (p) + "\n"
        return s
            
    def pixel (self, position) :
        """retourne en fonction de la position (1 à 9) de la pièce sa position sur l'écran,
        soit deux coordonnées"""
        p       = position - 1
        ligne   = p / 3
        colonne = p % 3
        return (colonne * 250, ligne * 250)
        
    def affiche (self, screen, petite = False) :
        """affiche les pièces sur l'écran, 
        en plus petit pour celles qui ne sont pas encore placées"""
        screen.fill ((0,0,0))    
        free = [0 for i in self.piece]
        for p in self.piece :
            if p.position > 0 :
                p.darker = False
                p.affiche (screen, self.pixel (p.position))
                free [p.position-1] = 1
                
        if petite :
            em = []
            for i in range (0, len (free)) :
                if free [i] == 0 : em.append (i+1)
            i = 0
            for p in self.piece :
                if p.position == 0 :
                    p.darker = True
                    p.affiche (screen, self.pixel (em [i]))
                    i += 1
                    
        pygame.display.flip ()
            
    def meilleure_piece (self, free, pos) :
        """retourne la prochaine pièce à placer sur le puzzle,
        dans un premier temps, on peut prend la première qui vient,
        ensuite, on peut essayer un choix plus judicieux"""
        if len (free) == 0 : return None
        else : return free [0]
        
    def piece_position (self, pi) :
        """recherche la piece associée à la position pi"""
        for p in self.piece :
            if p.position == pi :
                return p
        return None
            
    def ensemble_voisin (self, i) :
        """retourne les positions voisins de la position i"""
        i -= 1
        res = []
        for x in [-1,0,1] :
            for y in [-1,0,1] :
                if abs (x) == abs (y) : continue
                if x == -1 and i % 3 == 0 : continue
                if x == 1  and i % 3 == 2 : continue
                if y == -1 and i / 3 == 0 : continue
                if y == 1  and i / 3 == 2 : continue
                j = i + x + y * 3
                if j in range (0,9) :
                    res.append (j)
        return [ j+1 for j in res ]
        
    def nb_place (self) :
        """retourne le nombre de places vides"""
        i = 0
        for p in self.piece :
            if p.position == 0 : i += 1
        return i
        
    def angle_possible (self, p, display = False) :
        """retourne l'ensemble des angles possibles pour une pièce donnée"""
        voisin = self.ensemble_voisin (p.position)
        if display :
            print "voisin = ", voisin
        res = []
        for a in [0,90,180,270] :
            r = True
            for v in voisin :
                piece = self.piece_position (v)
                if piece != None :
                    r = r and piece.voisin_possible (p, a)
            if r :
                res.append (a)
        return res
        
    def solution (self, pos = 1, screen = None) : 
        if pos == 1 :
            for p in self.piece :
                p.position = 0
            self.nb_position = 0
            self.essai = 0
            
        self.essai += 1
            
        if self.nb_position == len (self.piece) :
            time.sleep (0.2)
            return

        # le tableau free mémorise l'ensemble des pièces non encore placées
        free = []
        for p in self.piece :
            if p.position == 0 :
                free.append (p)
               
        if screen != None :
            self.affiche (screen, True)
            pygame.display.flip ()
            
        p = self.meilleure_piece (free, pos)
        # si p == None, on n'étudie pas les solutions avec les pièces placées
        # avant aux positions 1 à pos --> on n'entrera pas dans la boucle suivante
        while p != None :
            
            p.position     = pos
            angle          = self.angle_possible (p)
            
            # p est la pièce choisie, pour cette pièce
            # on passe en revue toutes les orientations
            for a in angle :
                p.orientation = a
                
                time.sleep (0.2)  # temporisation
                
                if self.nb_place () == 0 :  return True
                else : 
                    r = self.solution (pos+1, screen = screen)
                    if r : return True
                    
            p.position     = 0
            
            # on réactualise le tableau free qui aura été modifié par 
            # l'appel à self.solution et on enlève le choix précédemment testé
            free2 = free
            free  = []
            for f in free2 :
                if f.numero != p.numero : free.append (f)

            # on passe au choix suivant avec free contenant les pièces
            # placées et les pièces essayées
            p = self.meilleure_piece (free, pos)
            

def attendre_clic ():
    """attend la pression d'un clic de souris"""
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break

if __name__ == "__main__" :
    
    # taille de l'écran
    size = (750,750)
    
    # initialisation du module pygame
    pygame.init ()
    screen  = pygame.display.set_mode (size)
    
    # on définit le puzzle
    p = Puzzle ()
    
    # on affiche le puzzle avec print (format texte)
    print p
    
    # on affiche le puzzle à l'écran
    p.affiche (screen, petite = True)
    attendre_clic ()
    
    # on rafraîchit l'écran pour que le puzzle apparaissent
    pygame.display.flip ()
    
    # on trouve la solution
    r = p.solution (screen = screen)
    print "résolution ", r
    print "appelle à la méthode solution ", p.essai
    
    # on attend la pression d'un clic de souris avant de terminer le programme
    p.affiche (screen, petite = True)
    attendre_clic ()

suite de Syracuse

def syracuse (u0) :
    suite = [ ]
    ops   = [ ]
    u = u0
    while u != 1 :
        suite.append (u)
        if u % 2 == 0 :
            ops.append (1)
            u = u/2
        else :
            u = (3*u+1) / 2
            ops.append (0)
    suite.append(u)
    suite.append(0)
    ops.reverse()
    return suite, ops
    
def base2 (ops) :
    s = 0.0
    i = 1
    for k,v in enumerate(ops) :
        if v == 1 : s += i
        i *= 2
    return s
    
if __name__ == "__main__" :
    for i in range (1,30) :
        s,o = syracuse(i)
        t = max ( [ _ for _ in s if _%2 == 1] )
        n = base2(o)
        print "% 3d len % 3d %d %d suite" % (i,len(s), t, n), o,s

File: syracuse.tex, line 111


 1 len   1 suite [1]
 2 len   2 suite [2, 1]
 3 len   6 suite [3, 5, 8, 4, 2, 1]
 4 len   3 suite [4, 2, 1]
 5 len   5 suite [5, 8, 4, 2, 1]
 6 len   7 suite [6, 3, 5, 8, 4, 2, 1]
 7 len  12 suite [7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1]
 8 len   4 suite [8, 4, 2, 1]
 9 len  14 suite [9, 14, 7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1]
10 len   6 suite [10, 5, 8, 4, 2, 1]
11 len  11 suite [11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1]
12 len   8 suite [12, 6, 3, 5, 8, 4, 2, 1]
13 len   8 suite [13, 20, 10, 5, 8, 4, 2, 1]
14 len  13 suite [14, 7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1]
15 len  13 suite [15, 23, 35, 53, 80, 40, 20, 10, 5, 8, 4, 2, 1]
16 len   5 suite [16, 8, 4, 2, 1]

résolution de l'énigme d'Einstein


# http://en.wikipedia.org/wiki/Zebra_Puzzle
# http://fr.wikipedia.org/wiki/Int%C3%A9gramme

import os, sys, copy


#: definition of all possible values (French terms)
#: colors
ttcouleur     = ["jaune",   "bleu",      "rouge",     "blanc",    "vert"]
#: nationalities
ttnationalite = ["danois",  "norvegien", "anglais",   "allemand", "suedois"]
#: drinks
ttboisson     = ["eau",     "the",       "lait",      "cafe",     "biere"]
#: smoke  brand
ttcigare      = ["Dunhill", "Blend",     "Pall Mall", "Prince",   "Bluemaster"]
#: animal
ttanimal      = ["chats",   "cheval",    "oiseaux",   "poisson",  "chiens"]

#: all possibles values
ensemble      = [ ttcouleur, ttnationalite, ttboisson, ttcigare, ttanimal ]

def permutation (nb) :
    """
    Compute all permutation of set [[ 1, 2, ..., nb ]].
    Example for 3:
    @code
    [[0, 1, 2], [0, 2, 1], [1, 0, 2], 
     [1, 2, 0], [2, 0, 1], [2, 1, 0]]
    @endcode
    
    @param      nb      permutation over the set [[1..n]]
    @return             list of all possible permutation
    
    @warning  This method can be very long if nb is high (>10).
    """
    per = []
    p = [i for i in range (0,nb)]
    while p [0] < nb :
        next = False
        for i in range (1,nb) :
            if p [i] in p [0:i] : 
                next = True
                break
                
        if not next :
            per.append (copy.copy (p))
            
        p [nb-1] += 1 
        for j in range (nb-1, 0, -1) :
            if p [j] >= nb :
                p [j] = 0
                p [j-1] += 1
                
    return per
    
class Rule :
    """
    this class defines a constraint of the problem
    or a clause (see `http://en.wikipedia.org/wiki/Clause_(logic)`)
    
    There are 5 different types of clauses described by Einstein's enigma
    each of them is described by a different class. There are defined by classes:
    @ref cl RulePosition, @ref cl RuleEquivalence, @ref cl RuleVoisin,
    @ref cl RuleAvant, @ref cl RuleEnsemble.
    """
    def __init__ (self) :
        """constructor
        """
        #: name of the rule
        self.name = None
        #: set of clauses
        self.set  = None
        
    def genere (self) :
        """generates all possible clauses (list of lists)
        (l [0][0] et l [0][1]) ou (l [1][0] et l [1][1]),
        a clause is a triplet of 
        (person, (property, category) )"""
        return None
    
    def __str__ (self) :
        """display
        """
        if self.name != None : 
            if "clauses" not in self.__dict__ :
                s = self.name + " \t: "
                a = self.genere ()
                for al in a :
                    st = "\n       ou  " + str (al) 
                    if len (st) > 260 : st = st [:260] + "..."
                    s += st 
                    if len (s) > 1000 : break
                return s
            else :
                s = self.name + " \t: " + str (self.set)
                for al in self.clauses :
                    st = "\n       ou   " + str (al) 
                    if len (st) > 260 : st = st [:260] + "..."
                    s += st 
                    if len (s) > 1000 : break
                return s
        else : 
            return "None"
    
    def combine (self, cl1, cl2) :
        """combine two clauses, two cases :
            1. nothing in common or everything in common --> concatenation of clauses
            2. a position or a property in common --> null clause
            
        @param      cl1     clause 1
        @param      cl2     clause 2
        @return             the new clause
        
        A clause is a @ref cl Rule.
        """
        # incompatibility
        for p1 in cl1 :
            for p2 in cl2 :
                if p1 [1][0] == p2 [1][0] : # same property
                    if p1 [0] != p2 [0] :  # but different positions
                        return None
                if p1 [0] == p2 [0] : # same person
                    if p1 [1][1] == p2 [1][1] and p1 [1][0] != p2 [1][0] :
                        # same category but different properties
                        return None
        # compatibility
        r = copy.deepcopy (cl1)
        for c in cl2 :
            if c not in r : r.append (c)
        return r
        
    def combine_cross_sets (self, set1, set2) :
        """
        combines two sets of clauses
        @param      set1        set of clauses 1
        @param      set2        set of clauses 2
        @return                 combination
        """
        if len (set1) == 0 : return copy.deepcopy (set2)
        if len (set2) == 0 : return copy.deepcopy (set1)
        res = []
        for cl1 in set1 :
            for cl2 in set2 :
                r = self.combine (cl1, cl2)
                if r != None :
                    res.append (r)
        return res
        
        
class RulePosition (Rule) :
    """p1 at position
    """
    def __init__ (self, p1, pos) :
        self.set = [p1]
        self.name = "position"
        self.position = pos
        
    def genere (self) :
        return [ [ ( self.position, self.set [0]) ] ]
        
class RuleEquivalence (Rule) :
    """p1 equivalent to p2
    """
    def __init__ (self, p1, p2) :
        self.set = [p1, p2]
        self.name = "equivalence"
        
    def genere (self) :
        l = []
        for i in range (0,5) :
            l.append ( [ (i, self.set [0]), (i, self.set [1]) ] )
        return l

class RuleVoisin (Rule) :
    """p1 and p2 are neighbors
    """
    def __init__ (self, p1, p2) :
        self.set = [p1, p2]
        self.name = "voisin"
        
    def genere (self) :
        l = []
        for i in range (0,4) :
            l.append ( [ (i, self.set [0]), (i+1, self.set [1]) ] )
            l.append ( [ (i+1, self.set [0]), (i, self.set [1]) ] )
        return l
            
class RuleAvant (Rule) :  
    """ p1 before p2
    """
    def __init__ (self, p1, p2) : 
        self.set = [p1, p2]
        self.name = "avant"
        
    def genere (self) :
        l = []
        for j in range (1,5) :
            for i in range (0,j) :
                l.append ( [ (i, self.set [0]), (j, self.set [1]) ] )
        return l
        
class RuleEnsemble (Rule) :
    """permutation of the elements of a category
    """
    def __init__ (self, set, categorie) : 
        self.set = [ (s,categorie) for s in set ]
        self.name = "ensemble"
        
    def genere (self) :
        l = []
        per = permutation (5)
        for p in per :
            tl = []
            for i in range (0,len (p)) :
                tl.append ( (i, self.set [p [i]]) )
            l.append (tl)
        return l
        

class Enigma :
    """
    this class solves the enigma
    """
    def __init__ (self, display = True) :
        """
        we describe the enigma using the classes we defined above
        @param      display     if True, use print to print some information
        """
        self.regle = []
        
        self.regle.append ( RulePosition (self.find ("lait") , 2) )
        self.regle.append ( RulePosition (self.find ("norvegien"), 0) )
        
        self.regle.append ( RuleEquivalence (self.find ("Pall Mall"),  self.find ("oiseaux")) )
        self.regle.append ( RuleEquivalence (self.find ("anglais"),    self.find ("rouge")) )
        self.regle.append ( RuleEquivalence (self.find ("suedois"),    self.find ("chiens")) )
        self.regle.append ( RuleEquivalence (self.find ("danois"),     self.find ("the")) )
        self.regle.append ( RuleEquivalence (self.find ("vert"),       self.find ("cafe")) )
        self.regle.append ( RuleEquivalence (self.find ("jaune"),      self.find ("Dunhill")) )
        self.regle.append ( RuleEquivalence (self.find ("biere"),      self.find ("Bluemaster")) )
        self.regle.append ( RuleEquivalence (self.find ("allemand"),   self.find ("Prince")) )

        self.regle.append ( RuleVoisin (self.find ("Dunhill"),     self.find ("cheval")) )
        self.regle.append ( RuleVoisin (self.find ("norvegien"),   self.find ("bleu")) )
        self.regle.append ( RuleVoisin (self.find ("Blend"),       self.find ("eau")) )
        self.regle.append ( RuleVoisin (self.find ("Blend"),       self.find ("chats")) )

        self.regle.append ( RuleAvant (self.find ("vert"), self.find ("blanc")) )
        
        self.regle.append ( RuleEnsemble (ttcouleur, 0 ))
        self.regle.append ( RuleEnsemble (ttnationalite, 1) )
        self.regle.append ( RuleEnsemble (ttboisson, 2) )
        self.regle.append ( RuleEnsemble (ttcigare, 3 ))
        self.regle.append ( RuleEnsemble (ttanimal, 4 ))
      
        for r in self.regle :
            r.clauses = r.genere ()
            r.utilise = False
            
        self.count = 0
    
    def find (self, p) :
        for i in range (0, len (ensemble)) :
            if p in ensemble [i] :
                return (p, i)
        return None
            
    def __str__ (self) :
        if "solution" not in self.__dict__ or self.solution == None or len (self.solution) == 0 :
            if self.count > 0 : s = "solution impossible apres " + str (self.count) + " iterations \n"
            else : s = ""
            for r in self.regle :
                s += str (r) + "\n"
            return s
        else :
            sr = ["solution, iteration " + str (self.count)]
            matrix = [ list( " "*5) for _ in range(0,5) ] 
            for row in self.solution :
                i = row[0]
                j = row[1][1]
                s = row[1][0]
                matrix[i][j] = s + " " * (10 - len(s))
            for row in matrix :
                sr.append ( ", ".join (row) )
            classic = "\n".join(sr[1:])
            html = classic.replace(",","</td><tr>").replace("\n","</td></tr>\n<tr><td>")
            return sr[0]+"\n" + "\n".join( [ 
                   classic, 
                   "<table>", 
                   "<tr><td>" + html  + "</td></tr>",
                   "</table>" ] )
            
    def solve (self, solution = [], logf = print) : # solution = [ ]) :
        """solve the enigma by eploring in deepness,
        the method is recursive
        
        @param      solution    [] empty at the beginning, recursively used then
        """

        self.count += 1
        if self.count % 10 == 0 :
            logf ("*",self.count, " - properties in place : ", len (solution)-1)
        
        if len (solution) == 25 :
            # we know the solution must contain 25 clauses,
            # if are here than the problem is solved unless some incompatibility
            for r in self.regle : 
                cl = r.combine_cross_sets ([ solution ], r.clauses)
                if cl == None or len (cl) == 0 :
                    # the solution is incompatible with a solution
                    return None
            self.solution = solution                    
            return solution

        # we are looking for the rule which generates the least possible clauses
        # in order to reduce the number of possibilities as much as possible
        # the research could be represented as a tree, we avoid creating two many paths
        best = None
        rule = None
        
        for r in self.regle :
            
            cl = r.combine_cross_sets ([ solution ], r.clauses)

            if cl == None :
                # the solution is incompatible with a solution
                return None
                
            # we chech rule r is bringing back some results
            for c in cl :
                if len (c) > len (solution) :
                    break
            else :
                cl = None
            
            if cl != None and (best == None or len (best) > len (cl)) :
                best = cl
                rule = r
        
        if best == None :
            # the solution is incompatible with a solution
            return None
            
        rule.utilise = True
            
        # we test all clauses
        for c in best :
            r = self.solve (c, logf = logf)
            if r != None :
                # we found
                return r
                
        rule.utilise = False # impossible
        return None
        
if __name__ == "__main__" :        
    en = Enigma ()
    print (en)
    print ("-----------------------------\n")
    en.solve ()
    print ("-----------------------------\n")
    print (en)

énigme de Harry Potter, tome 1 (avec des fonctions)

def solution_correcte (sol) :
    """cette fonction recoit un tableau de 7 cases,
    chaque case contient un entier compris entre 0 et 3 inclus :
    0 : poison, 1 : vin, 2 : reculer, 3 : avancer
    la fonction determine si l'agencement propose dans sol
    verifie les cinq regles de l'enonce,
    retourne True si toutes les regles sont verifiees
    ou False si l'une des regles n'est pas verifiee,
    
    rappel : les indices vont de 0 a 6 inclus car il y a 7 cases"""
    
    # regle 1
    nb = [0,0,0,0]
    for s in sol : 
        nb [s] += 1
    if nb [0] != 3 : return False # 3 poison
    if nb [1] != 2 : return False # 2 vin
    if nb [2] != 1 : return False # 1 reculer
    if nb [3] != 1 : return False # 1 avancer
        
    # regle 2
    for i in range (1,len (sol)) :
        if sol [i] == 1 and sol [i-1] != 0 : return False
            
    # regle 3
    if sol [0] == sol [6] : return False
    if sol [0] == 3 : return False
    if sol [6] == 3 : return False
        
    # regle 4
    if sol [2] == 0 : return False
    if sol [5] == 0 : return False
        
    # regle 5
    if sol [1] != sol [5] : return False
        
    # si on arrive ici, c'est que toutes les regles sont verifiees
    return True
    
    
def affiche_solution (sol) :
    a = ["poison", "vin", "reculer", "avancer"]
    res = ""
    for s in sol :
        res += "{0}, ".format(a [s])
    return res
        
                                                                  
# seconde idee : 2 boucles seulement pour 
# parcourir toutes les solutions
def solution():
    sol = [ 0,0,0,0,0,0,0] 
    while sol [0] < 4 :
        r = solution_correcte (sol)
        if r :
            return sol
        
        sol [6] += 1
        for i in range (len (sol)-1, 0, -1) :  # on parcourt les indices en 
                                                 # allant de 6 a 1 inclus
            if sol [i] >= 4 :
                sol [i]    = 0
                sol [i-1] += 1

if __name__ == "__main__":
    res = solution()
    print(affiche_solution(res))

énigme de Harry Potter, tome 1 (avec des classes)

contenu_case = ["poison", "vin", "reculer", "avancer"]

class Case :
    def __init__ (self, contenu) :
        self.contenu = contenu_case.index (contenu)
        
    def __str__ (self) :
        return contenu_case [self.contenu]
        
class Regle1 :
    def correcte (self, cases) :
        nb = [0,0,0,0]
        for s in cases : 
            nb [s.contenu] += 1
        if nb [0] != 3 : return False # 3 poison
        if nb [1] != 2 : return False # 2 vin
        if nb [2] != 1 : return False # 1 reculer
        if nb [3] != 1 : return False # 1 avancer
        return True
            
class Regle2 :
    def correcte (self, cases) :
        for i in range (1,len (cases)) :
            if cases [i].contenu == 1 and cases [i-1].contenu != 0 : return False
        return True
        
class Regle3 :
    def correcte (self, cases) :
        if cases [0].contenu == cases [6].contenu : return False
        if cases [0].contenu == 3 : return False
        if cases [6].contenu == 3 : return False
        return True
        
class Regle4 :
    def correcte (self, cases) :
        if cases [2].contenu == 0 : return False
        if cases [5].contenu == 0 : return False
        return True

class Regle5 :
    def correcte (self, cases) :
        if cases [1].contenu != cases [5].contenu : return False
        return True
        
class Enigme :
    def __init__ (self) :
        self.regle = [ Regle1 (), Regle2 (), Regle3 (), Regle4 (), Regle5 ()] 
        self.cases = [ Case ("poison") for i in range (0,7) ]
        
    def __str__ (self) :
        for s in self.cases :
            print (s, ", ",)
        print ("")
        
    def solution_correcte (self) :
        for r in self.regle :
            if not r.correcte (self.cases) :
                return False
        return True
        
    def resoud (self) :
        
        for c in self.cases : 
            c.contenu = 0
            
        while self.cases [0].contenu < 4 :
            r = self.solution_correcte ()
            if r :
                print (self.__str__ ())
            
            self.cases [6].contenu += 1
            for i in range (len (self.cases)-1, 0, -1) :  # on parcourt les indices en 
                                                     # allant de 6 a 1 inclus
                if self.cases [i].contenu >= 4 :
                    self.cases [i].contenu    = 0
                    self.cases [i-1].contenu += 1
    

e = Enigme ()
e.resoud ()


File: vigenere.tex, line 11


ABCDEFGHIJKLMNOPQRSTUVWXZ
BCDEFGHIJKLMNOPQRSTUVWXZA
CDEFGHIJKLMNOPQRSTUVWXZAB
DEFGHIJKLMNOPQRSTUVWXZABC
EFGHIJKLMNOPQRSTUVWXZABCD
FGHIJKLMNOPQRSTUVWXZABCDE
GHIJKLMNOPQRSTUVWXZABCDEF
HIJKLMNOPQRSTUVWXZABCDEFG
IJKLMNOPQRSTUVWXZABCDEFGH
JKLMNOPQRSTUVWXZABCDEFGHI
KLMNOPQRSTUVWXZABCDEFGHIJ
LMNOPQRSTUVWXZABCDEFGHIJK
MNOPQRSTUVWXZABCDEFGHIJKL
NOPQRSTUVWXZABCDEFGHIJKLM
OPQRSTUVWXZABCDEFGHIJKLMN
PQRSTUVWXZABCDEFGHIJKLMNO
QRSTUVWXZABCDEFGHIJKLMNOP
RSTUVWXZABCDEFGHIJKLMNOPQ
STUVWXZABCDEFGHIJKLMNOPQR
TUVWXZABCDEFGHIJKLMNOPQRS
UVWXZABCDEFGHIJKLMNOPQRST
VWXZABCDEFGHIJKLMNOPQRSTU
WXZABCDEFGHIJKLMNOPQRSTUV
XZABCDEFGHIJKLMNOPQRSTUVW
ZABCDEFGHIJKLMNOPQRSTUVWX
ABCDEFGHIJKLMNOPQRSTUVWXZ

File: vigenere.tex, line 42


lescodessecretsontjoueunrolediscretmaisimportantdanslhistoire
CODECODECODECODECODECODECODECODECODECODECODECODECODECODECODEC

File: vigenere.tex, line 49


lescodessecretsontjoueunrolediscretmaisimportantdanslhistoire
CODECODECODECODECODECODECODECODECODECODECODECODECODECODECODEC
NSV...

code de Vigenère

al = "abcdefghijklmnopqrstuvwxyz"
al = al.upper ()

carre = []
for i in range (0,26) :
	carre.append (al)
	al = al [1:26] + al [0]	
	
for c in carre :
	print c

décryptage du code de Vigenère

def CarreVigenere () :
    """creation du carre de Vigenere"""
    al = "abcdefghijklmnopqrstuvwxyz"
    al = al.upper ()
    
    carre = []
    for i in range (0,26) :
        carre.append (al)
        al = al [1:26] + al [0]	
        
    return carre
	
	
def CodeVigenere (message, cle, carre) :
    """code un message selon le code de Vigenere,
    message est le message a coder
    cle est la cle
    carre est le carre de Vigenere"""
    
    alphabet = carre [0]  # contient l'alphabet (premiere ligne du carre)
    resultat = ""         # contiendra le message code
    
    # on parcourt le message
    for i in range (0, len (message)) :
        
        # j est la position de la lettre dans le cle
        # associee a la lettre i dans le message
        # % retourne le reste d'une division entiere
        j = i % len (cle)
        
        a = alphabet.find (message [i])  # numero de la lettre message [i]
        b = alphabet.find (cle [j])      # numero de la lettre cle [j]
        
        c = carre [b][a]
        resultat += c
        
    return resultat
    
def DecodeVigenere (message, cle, carre) :    
    """decode un message selon le code de Vigenere,
    message est le message a decoder
    cle est la cle
    carre est le carre de Vigenere"""
    
    alphabet = carre [0]  # contient l'alphabet (premiere ligne du carre)
    resultat = ""         # contiendra le message code
    
    # on parcourt le message
    for i in range (0, len (message)) :
        
        # j est la position de la lettre dans le cle
        # associee a la lettre i dans le message
        # % retourne le reste d'une division entiere
        j = i % len (cle)
        
        b = alphabet.find (cle [j])       # numero de la lettre cle [j]
        a = carre [b].find (message [i])  # numero de la lettre message [i]
                                          # dans la ligne du carre correspondant
                                          # au decalage introduit par cle [j]
        
        c = carre [0][a]
        resultat += c

    return resultat

message = "ceci est le message non code sans signe de ponctuation"
message = message.replace (" ", "")
message = message.upper ()
cle     = "VIGENERES"
carre   = CarreVigenere ()

code    = CodeVigenere (message, cle, carre)
decode  = DecodeVigenere (code, cle, carre)

print "------------------ cle"
print cle
print "------------------ message"
print message
print "------------------ message code"
print code
print "------------------ message decode"
print decode
print "------------------"
if decode == message : print "message bien retranscrit"
else : print "message mal retranscrit"


#############################################################################
#############################################################################
#############################################################################

print ""
print "####################################################################"
print "seconde partie : decoder sans la cle"
print "cette methode ne marche que sur un message plus long ou de nombreux"
print "message mis bout a bout, on essaye la methode sur le fichier :"
print "hugo_dernier_jour_condamne.txt"
print "####################################################################"

def PGCD (m,n) :
    """determine le PGCD"""
    if m == 1 or n == 1 : return 1
    if m == n : return m
    if m < n : return PGCD (m, n-m)
    return PGCD (n, m-n)
    

def DecodeVigenereLongueurCle (message, mot = 3) :
    """cette fonction determine la longueur de la cle, elle 
    repere les groupes de trois lettres qui se repete dans le message code
    et suppose qu'il y une tres forte probabilite qu'un meme groupe de trois
    soit code avec les memes trois lettres du message et les memes trois 
    lettres de la cle
    
    message  : .....DES...........DES...........DES.........DES....DES
    cle      : ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD
    code     : .....EGV.........................EGV.........EGV..........
    distance :      <----------24--------------><----8----->
    
    la longueur de la cle divise le PGCD de 24 et 8
    """
    al = "abcdefghijklmnopqrstuvwxyz"
    al = al.upper ()
    
    
    # parcours du message pour recenser toutes les positions
    dico = {}
    for i in xrange (0, len (message)-2) :
        t = message [i:i+mot]
        if dico.has_key (t) : dico [t].append (i)
        else : dico [t] = [i]

    # on va garder toutes les distances entre 
    # entre deux occurrences du meme mot de n lettres
    dis = []
    for d in dico :
        p = dico [d]
        if len (p) > 1 :
            for i in range (0, len (p)-1) : 
                #print d, p [i+1] - p [i], " --- ", float (p [i+1] - p [i]) / 8
                dis.append ( p [i+1] - p [i] )

    # on extrait le PGCD
    if len (dis) == 0 : 
        print "impossible de determiner la cle"
        return 0
        
    if len (dis) == 1 : return dis [0]
        
    longueur = PGCD (dis [0], dis [1])
    for d in dis : 
        longueur = PGCD (longueur, d)
        
    if longueur > 5 : 
        # si la longueur est suffisante, le resultat a des chances d'etre bon
        return longueur
    else :
        # sinon, on relance l'algorithme avec des mots plus grand
        return DecodeVigenereLongueurCle (message, mot+1)
        
        
def DecodeVigenereCle (code, l) :
    """determine la cle du message code, connaissant sa longueur,
    on suppose que la lettre E est la lettre la plus frequente
    """
    al  = "abcdefghijklmnopqrstuvwxyz"
    al  = al.upper ()
    cle = ""
    for i in xrange (0, l) :
        nombre = [ 0 for a in al]
        sous   = code [i:len (code):l]  # on extrait toutes les lettres
                                        # i, i+l, i+2l; i+3l, ...

        # on compte les lettres
        for k in sous : nombre [ al.find (k) ] += 1
        
        # on cherche le maximum
        p = 0 
        for k in range (0, len (nombre)) :
            if nombre [k] > nombre [p] : p = k
            
        # on suppose que al [p] est la lettre E code,
        # il ne reste plus qu'a trouver la lettre de la cle
        # qui a permis de coder E en al [p]
        cle += al [ (p + 26 - al.find ("E")) % 26 ]
        
    return cle
    
    
                
    
# on lit Victor Hugo
f = open ("hugo_dernier_jour_condamne.txt")
message = f.read ()  # lit tout d'une seule traite
f.close ()

# on limite la taille du fichier
message = message [5000:7000]

# on enleve les signes de ponctuation et on met en majuscule
message = message.replace ("\n", "")
message = message.replace ("\r", "")
message = message.replace ("\t", "")
message = message.replace (" ", "")
message = message.replace (",", "")
message = message.replace (";", "")
message = message.replace (":", "")
message = message.replace (".", "")
message = message.replace ("'", "")
message = message.replace ("\"", "")
message = message.replace ("-", "")
message = message.replace ("!", "")
message = message.replace ("?", "")
message = message.replace ("(", "")
message = message.replace (")", "")
message = message.upper ()

# on code
print "on code, longueur du message ", len (message)
code    = CodeVigenere (message, cle, carre)
memoire = cle
cle     = None   # on oublie la cle

# on determine la longueur de la cle
l           = DecodeVigenereLongueurCle (code)
# on determine la cle en suppose que la lettre E est la plus frequente
# ne marche pas pour les textes anglais
cle_code    = DecodeVigenereCle (code, l)
# decode le texte
decode      = DecodeVigenere (code, cle_code, carre)



print "------------------ vraie"
print memoire
print "------------------ cle trouve par Babbage"
print "longueur ", l, " cle : ", cle_code
if memoire == cle_code : print "bonne cle"
else : print "mauvaise cle"
print "------------------ message"
print message [:200]
print "------------------ message code"
print code [:200]
print "------------------ message decode"
print decode [:200]
print "------------------"
if decode == message : print "message bien retranscrit"
else : 
    for i in xrange (0, len (decode)) :
        if message[i] != decode [i] :
            print i, message[i], decode[i]
    print "message mal retranscrit"
    

File: position_table_cor.tex, line 24


def trois_pareil (table) :
    """table est une suite booleens, on retourne True
    s'il n'y en a pas trois consecutifs"""
    for i in xrange (len (table)-2) :
        if table [i] == table [i+1] == table [i+2] :
            return False
    return True
    
def compte (n) :
    """on parcours toutes les tables possibles et on compte les 
    bonnes configurations"""
    table = [ False for i in range (0,n) ]
    nb = 0
    bon = 0
    while table [0] != None :
        if n == 5 and trois_pareil (table) : print table
        nb += 1
        if trois_pareil (table) : bon += 1
        for i in xrange (len (table)-1, -1, -1) :
            if not table [i] : 
                table [i] = True
                break
            else :
                table [i] = False
                if i == 0 : table [0] = None
        
    return nb, bon
    
for n in range (3, 15) :
    nb, bon = compte (n)
    print n, " nb = ", nb, "  bon = ", bon, " mauvais = ",
    print " proba = ", 
    print float (bon) / float (nb), "          \t",
    print bon, "/", nb

File: position_table_cor.tex, line 194


HFF
 FFH
  FHH
   HHH
    HHF

File: position_table_cor.tex, line 278


HFF
 FFH
  FHH
   HHF
    HFF

File: position_table_cor.tex, line 287


HFF
 FFH
  FHH
   HHF
    HFF
     FFH      ajouté
      FHF     ajouté

table équilibrée

###############################################################################
#                              questions 1 a 5
###############################################################################

def lit_fichier (nom) :
    """cette fonction lit le contenu d'un fichier
    et retourne une liste contenant ses lignes"""
    f = open (nom, "r")
    li = f.readlines ()
    f.close ()
    r =[]
    for l in li :
        s = l.replace ("\n", "")
        s = s.replace ("\r", "")
        r.append (s)
    return r
    
def genre (prenom, femme, homme) :
    """retourne le genre d'un prenom"""
    if prenom in femme : return True
    if prenom in homme : return False
    return None
    
def contrainte (table, femme, homme) :
    """cette fonction verifie que la table
    obeit aux contrainte d'Harmonie :
    il ne peut y avoir trois personnes voisines du meme sexe
    qui se suivent"""
    ge = [ genre (t,femme, homme) for t in table ]    
    for i in range (0,len (ge)) :
        if ge [i] == ge [ (i+1) % len (ge) ] == ge [(i+2) % len (ge) ] :
            return False
    return True
    
def dominique (table, femme, homme) :
    """cette fonction dit si on peut placer dominique,
    deux schemas de figures possibles : 
      1-  H F dominique H F
      2-  F H dominique F H
    """
    ge = [ genre (t,femme, homme) for t in table ]
    for i in range (0,len (ge)) :
        if  ge [i]                != ge [ (i+1) % len (ge) ] and \
            ge [(i+2) % len (ge)] != ge [ (i+3) % len (ge) ] and \
            ge [i]                == ge [ (i+2) % len (ge) ] :
            return True
    return False
    
femme = lit_fichier ("femme.txt")
homme = lit_fichier ("homme.txt")
table = lit_fichier ("table.txt")
r = contrainte (table, femme, homme)
print "la table suit les desirs d'Harmonie : ", r
r = dominique (table, femme, homme)
print "peut-on ajouter Dominique : ", r


###############################################################################
#                              question 6
###############################################################################

def contrainte_dominique (table, femme, homme) :
    """meme fonction que contrainte mais on tient aussi du fait que 
    le genre peut etre indetermine (None), toute configuration 
    incertaine est eliminee"""
    ge = [ genre (t,femme, homme) for t in table ]    
    for i in range (0,len (ge)) :
        if ge [i] == ge [ (i+1) % len (ge) ] == ge [(i+2) % len (ge) ] :
            return False
        if ge [i] == None and ge [ (i+1) % len (ge) ] == ge [(i+2) % len (ge) ] :
            return False 
        if ge [i] ==  ge [ (i+1) % len (ge) ] and ge [(i+2) % len (ge) ] == None :
            return False 
        if ge [i] ==  ge [ (i+2) % len (ge) ] and ge [(i+1) % len (ge) ] == None :
            return False 
        if ge [i] == None and ge [ (i+1) % len (ge) ] == None :
            return False
        if ge [i] == None and ge [ (i+2) % len (ge) ] == None :
            return False
        if ge [ (i+2) % len (ge) ] == None and ge [ (i+1) % len (ge) ] == None :
            return False
    return True
    
def place_dominique (table, femme, homme) :
    """on cherche a inserer autant de dominique que possible"""
    nb = len (table)
    fin = False
    while not fin :  
        fin = True
        for i in range (0, len (table)) :
            table.insert (i, "DOMINIQUE")
            r = contrainte_dominique (table, femme, homme)
            if r :
                fin = False 
                break
            else :
                del table [i]
    return len (table) - nb
    
print "-----------------------------------------------------------------"
nb = place_dominique (table, femme, homme)
print "nombre de dominique ", nb
for p in table :
    print p
    
    
###############################################################################
#                              question 7
###############################################################################
#
#  nombre minimal : partie entiere de (n+1)/2
#  nombre maximal : 2n 
#
###############################################################################
#                              question 8
###############################################################################

def trois_pareil (table) :
    """table est une suite booleens, on retourne True
    s'il n'y en a pas trois consecutifs"""
    for i in xrange (len (table)-2) :
        if table [i] == table [i+1] == table [i+2] :
            return False
    return True
    
def trois_pareil_rond (table) :
    """table est une suite booleens, on retourne True
    s'il n'y en a pas trois consecutifs"""
    for i in xrange (len (table)) :
        if table [i] == table [ (i+1) % len (table)] == table [(i+2) % len (table)] :
            return False
    return True
    
def compte (n) :
    """on parcours toutes les tables possibles et on compte les 
    bonnes configurations"""
    table = [ False for i in range (0,n) ]
    nb = 0
    bon = 0
    while table [0] != None :
        nb += 1
        if trois_pareil_rond (table) : bon += 1
        for i in xrange (len (table)-1, -1, -1) :
            if not table [i] : 
                table [i] = True
                break
            else :
                table [i] = False
                if i == 0 : table [0] = None
        
    return nb, bon
    
print "-----------------------------------------------------------------"
print "calcul en parcourant toutes les tables possibles"
print "-----------------------------------------------------------------"
for n in range (3, 15) :
    nb, bon = compte (n)
    print n, " nb = ", nb, "  bon = ", bon, 
    print " proba = ", float (bon) / float (nb), "          \t",
    print bon, "/", nb

###############################################################################
#                              question 8
#                                  markov
###############################################################################
# module pour le calcul matriciel
import numpy
import copy


def construit_matrice () :
    """construit la matrice de transition, 
    le vecteur des probabilites d'entrees dans chaque etat"""
    # construction des etats
    etat = []
    for i in range (0,2) :
        for j in range (0,2) :
            for k in range (0,2) :
                etat.append ( (i,j,k) )
    # construction de la matrice
    mat = []
    for i in range (0, len (etat)) :
        l = []
        for j in range (0, len (etat)) :
            if etat [i] [1:3] == etat [j] [0:2] : 
                # (i,j,k) --> (j,k,0) ou (j,k,1)
                l.append (1)
            else : l.append (0)
        # on renormalise sur chaque ligne
        s = sum (l)
        for j in range (0, len (etat)) : l[j] /= float (s)
        mat.append (l)
    
    entree = [ 0.125 for i in range (0,8) ]    
    return etat, numpy.matrix (mat), numpy.matrix (entree)
    
def calcul_probabilite_droite (n, etat, mat_, entree) :
    """calcule les probabilites pour une table droite"""
    pos     = [ etat.index ( (0,0,0) ), etat.index ( (1,1,1) ) ] 
    temp    = copy.deepcopy (entree)
    mat     = copy.deepcopy (mat_)
    for p in pos :
        for i in range (0,8) :
            mat [ (p,i) ] = 0.0
        mat [ (p,p) ] = 1.0
        
    m = mat ** (n-1)
    
    sum = 0.0
    for i in range (0,8) :
        for j in range (0,8) :
            if i not in pos and j not in pos :
                sum += m [ (i,j) ]  * mat [ (j,i) ] 
    return sum
    
    

print "-----------------------------------------------------------------"
print "calcul avec les chaines de Markov"
print "-----------------------------------------------------------------"
etat,mat,entree = construit_matrice ()

for n in range (3,15) :
    proba = calcul_probabilite_droite (n, etat, mat, entree)
    print n, "  bon ", proba

décomposition d'une fraction ractionnelle

#include "stdio.h"
#include "string.h"


//////////////////////////////////////////////////////////////////////

typedef struct {
  double *C ;
  int Ligne ;
  int Colonne ;
} Matrice ;

typedef struct {
  double *C ;
  int Degre ;
} Polynome ;

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

// fonction matricielle

// crée une matrice
Matrice matrice_new (int ligne, int colonne) ;
// crée une matrice carrée identité
Matrice matrice_new_identite (int ligne) ;
// libère une matrice
void matrice_free (Matrice *mat) ;
// change la valeur d'un coefficient
void matrice_change (Matrice *mat, int i, int j, double val) ;
// retourne la valeur d'un coefficient
double matrice_donne (Matrice *mat, int i, int j) ;
// fait une copie de matrice
Matrice matrice_copie (Matrice *mat) ;
// produit de matrice
Matrice matrice_produit (Matrice *mat1, Matrice *mat2) ;
// écrire une matrice
char *matrice_ecrit (Matrice *mat) ;

// réalise le pivot de Gauss
// et retourne la matrice de passage
Matrice matrice_pivot_gauss (Matrice *mat) ;
// réalise le pivot de Gauss de haut en bas
// et retourne la matrice de passage
Matrice matrice_pivot_gauss_inverse (Matrice *mat) ;
// utilise les deux fonctions précédentes pour calculer l'inverse d'une matrice
// la matrice mat rste inchangée
Matrice matrice_inverse (Matrice *mat) ;


//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

// crée un polynôme
Polynome polynome_new (int degre) ;
// libère un polynôme
void polynome_free (Polynome *p) ;
// change la valeur d'un coefficient (celui devant le monôme de degré n)
void polynome_change (Polynome *p, int n, double val) ;
// retourne la valeur d'un coefficient
double polynome_donne (Polynome *p, int n) ;
// retourne une chaîne
char *polynome_ecrit (Polynome *p) ;
// multiplie deux polynôme
Polynome polynome_produit (Polynome *p1, Polynome *p2) ;

// effectue la decomposition d'une fraction rationnelle
// resultat contient les resultats
// première dimension : facteur
// deuxième dimension : puissance [n]
// résultat doit déjà être alloué
void polynome_decomposition (Polynome *numerateur, int facteur, Polynome *element, int *puissance,
                    Polynome partie_entiere,
                    Polynome **resultat) ;

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

Polynome fichier_lecture_polynome (FILE *f)
{
  char buffer [200] ;
  Polynome r ;
  fscanf (f, "%s %s %d", buffer, buffer, &r.Degre) ;
  r = polynome_new (r.Degre) ;
  double d ;
  int n ;
  for (n = 0 ; n <= r.Degre ; n++) {
    fscanf (f, "%s %lf", buffer, &d) ;
    polynome_change (&r, n, d) ;
  }
  return r ;
}

// pour écrire dans un fichier
FILE *Sortie = NULL ;

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

void main (int argc, char *param [])
{
  char *c = "fraction.txt" ;
  char *res = "decompo.txt" ;
  if (argc > 1) c = param [1] ;
  if (argc > 2) res = param [2] ;

  // on lit le fichier
  FILE *f = fopen (c, "r") ;
  if (f == NULL) printf ("impossible de lire le fichier %s\n", c) ;
  else {
    char buffer [200] ;

    // lecture du numérateur
    Polynome Numerateur = fichier_lecture_polynome (f) ;

    // lecture du nombre de polynôme au dénominateur
    int Denominateur ;
    fscanf (f, "%s %s %d", buffer, buffer, &Denominateur) ;

    int *Puissance = new int [Denominateur] ;
    Polynome *Element = new Polynome [Denominateur] ;

    // lecture de ces polynôme
    int n ;
    for (n = 0 ; n < Denominateur ; n++) {
      fscanf (f, "%s %s %d", buffer, buffer, &Puissance [n]) ;
      Element [n] = fichier_lecture_polynome (f) ;
    }

    fclose (f) ;

    // vérification de la lecture
    char *s = polynome_ecrit (&Numerateur) ;
    printf ("numerateur  : %s\n",s) ;
    delete [] s ;
    printf ("\nnombre de terme au denominateur : %d\n",Denominateur) ;
    for (n = 0 ; n < Denominateur ; n++) {
      s = polynome_ecrit (&(Element [n])) ;
      printf ("terme %d puissance %d : %s\n", n+1, Puissance [n], s) ;
      delete [] s ;
    }

    // création de la structure de résultat
    // degré total du dénominateur
    int degre = 0 ;
    for (n = 0 ; n < Denominateur ; n++)
      degre += Puissance [n] * Element [n].Degre ;

    // degré de la partie entière
    int degre_ent = Numerateur.Degre - degre ;
    if (degre_ent < 0) degre_ent = -1 ; // pas de partie entère

    int k ;
    Polynome PartieEntiere = polynome_new (degre_ent) ;
    Polynome **Resultat = new Polynome* [Denominateur] ;
    for (n = 0 ; n < Denominateur ; n++) {
      Resultat [n] = new Polynome [Puissance [n]] ;
      for (k = 0 ; k < Puissance [n] ; k++)
        Resultat [n][k] = polynome_new (Element [n].Degre - 1) ;
          // les coefficients des éléments
          // simple sont des polynômes de degré 0 (constante) pour un élément simple de 1° espèce
          // et de degré 1 pour des éléments simples de 2° espèce
    }


    // traitement de la décomposition
    FILE *g = fopen (res, "w") ;
    Sortie = g ;

    polynome_decomposition (&Numerateur,
                            Denominateur,
                            Element,
                            Puissance,
                            PartieEntiere,
                            Resultat) ;


    // écriture du résultat


    // précision sur la fraction à décomposer

    s = polynome_ecrit (&Numerateur) ;
    fprintf (g, "fraction à décomposer : \n\n") ;
    fprintf (g, "numerateur  : %s\n",s) ;
    delete [] s ;
    fprintf (g, "\nnombre de terme au denominateur : %d\n",Denominateur) ;
    for (n = 0 ; n < Denominateur ; n++) {
      s = polynome_ecrit (&(Element [n])) ;
      if (Puissance [n] > 1) fprintf (g, "terme %d : (%s)^%d\n", n+1, s, Puissance [n]) ;
      else fprintf (g, "terme %d : (%s)\n", n+1, s) ;
      delete [] s ;
    }
    fprintf (g, "\n\ndécomposition en éléments simples \n\n") ;

    // partie entière
    s = polynome_ecrit (&PartieEntiere) ;
    fprintf (g, "partie entière : \t\t%s\n",s) ;
    delete [] s ;

    // les autres termes
    for (n = 0 ; n < Denominateur ; n++) {
      for (k = 0 ; k < Puissance [n] ; k++) {
        s = polynome_ecrit (&(Element [n])) ;
        if (k == 0) fprintf (g, "terme en (%s) : \t", s) ;
        else fprintf (g, "terme en (%s)^%d : \t", s, k+1) ;
        delete [] s ;

        s = polynome_ecrit (&(Resultat [n][k])) ;
        fprintf (g, "%s\n",s) ;
        delete [] s ;
      }
    }



    // fin du programme
    Sortie = NULL ;
    fclose (g) ;

    polynome_free (&Numerateur) ;
    for (n = 0 ; n < Denominateur ; n++) polynome_free (&(Element [n])) ;
    delete [] Element ;

    polynome_free (&PartieEntiere) ;
    for (n = 0 ; n < Denominateur ; n++) {
      for (k = 0 ; k < Puissance [n] ; k++)
        polynome_free (&(Resultat [n][k])) ;
      delete [] Resultat [n] ;
    }
    delete [] Puissance ;
    delete [] Resultat ;

    // fin
//    getchar () ;
  }
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

Matrice matrice_new (int ligne, int colonne)
{
  if (ligne * colonne > 0) {
    Matrice r ;
    r.Ligne = ligne ;
    r.Colonne = colonne ;
    r.C = new double [r.Ligne * r.Colonne] ;
    return r ;
  }
  else {
    Matrice r ;
    r.Ligne = 0 ;
    r.Colonne = 0 ;
    return r ;
  }
}

Matrice matrice_new_identite (int ligne)
{
  Matrice r = matrice_new (ligne, ligne) ;
  int i,j ;
  for (i = 0 ; i < r.Ligne ; i++)
    for (j = 0 ; j < r.Colonne ; j++)
      if (i == j) matrice_change (&r, i,j, 1) ;
      else matrice_change (&r, i,j, 0) ;
  return r ;
}

void matrice_free (Matrice *mat)
{
  if (mat->Ligne * mat->Colonne > 0) {
    delete [] mat->C ;
    mat->Ligne = 0 ;
    mat->Colonne = 0 ;
  }
}

void matrice_change (Matrice *mat, int i, int j, double val)
{
  if ((i >= 0) && (i < mat->Ligne) && (j >= 0) && (j < mat->Colonne))
    mat->C [i * mat->Colonne + j] = val ;
  else printf ("erreur matrice change %d %d\n",i,j) ;
}
double matrice_donne (Matrice *mat, int i, int j)
{
  if ((i >= 0) && (i < mat->Ligne) && (j >= 0) && (j < mat->Colonne))
    return mat->C [i * mat->Colonne + j] ;
  else { printf ("erreur matrice donne %d %d\n",i,j) ; return 0 ; }
}

Matrice matrice_produit (Matrice *mat1, Matrice *mat2)
{
  if (mat1->Colonne == mat2->Ligne) {
    Matrice r = matrice_new (mat1->Ligne, mat2->Colonne) ;
    double d ;
    int i,j,k ;
    for (i = 0 ; i < r.Ligne ; i++)
      for (j = 0 ; j < r.Colonne ; j++) {
        d = 0 ;
        for (k = 0 ; k < mat1->Colonne ; k++)
             d +=  matrice_donne (mat1, i,k)
                 * matrice_donne (mat2, k,j) ;
        matrice_change (&r, i,j, d) ;
      }
    return r ;
  }
  else {
    Matrice r ;
    r.Ligne = 0 ;
    r.Colonne = 0 ;
    return r ;
  }
}

char *matrice_ecrit (Matrice *mat)
{
  char *res = new char [mat->Ligne * mat->Colonne * 20] ;
  *res = 0 ;
  char *c ;
  int i,j ;
  for (i = 0 ; i < mat->Ligne ; i++) {
    for (j = 0 ; j < mat->Colonne ; j++) {
      c = res + strlen (res) ;
      sprintf (c, "%g\t",matrice_donne (mat, i,j)) ;
    }
    c = res + strlen (res) ;
    sprintf (c, "\n") ;
  }
  return res ;
}

Matrice matrice_copie (Matrice *mat)
{
  Matrice r = matrice_new (mat->Ligne, mat->Colonne) ;
  int i,j ;
  for (i = 0 ; i < mat->Ligne ; i++)
    for (j = 0 ; j < mat->Colonne ; j++)
      matrice_change (&r, i,j, matrice_donne (mat, i,j)) ;
  return r ;
}

Matrice matrice_pivot_gauss (Matrice *mat)
{
  // la matrice de passage est carrée et est l'identité au début
  Matrice passage = matrice_new_identite (mat->Ligne) ;

  // pivot
  int n,k,l ;
  double d,div,fact ;
  int pos ;
  bool faire_pivot ;

  // nombre de lignes sur lesquels il faut faire le pivot
  // car le rang d'une matrice M est vérifié r (M) <= MIN (Ligne, Colonne)
  int ligne = mat->Ligne ;
  if (mat->Colonne < ligne) ligne = mat->Colonne ;

  // pivot sur toutes les lignes
  for (n = 0 ; n < ligne ; n++) {
    // on teste le terme diagonale
    faire_pivot = true ;  // par défaut, on effectue le pivot sur la colonne n
    d = matrice_donne (mat, n,n) ;
    if (d == 0) {
      // si ce terme est nul, on regarde si un terme dans la même colonne ne l'est pas
      pos = n ;
      while ((pos < mat->Ligne) && (matrice_donne (mat, pos, n) == 0)) pos++ ;
      if (pos >= mat->Ligne) faire_pivot = false ; // car tous les termes de la colonne sont nuls
      else {
        // sinon, on ajoute la ligne pos à la ligne n
        for (k = n ; k < mat->Colonne ; k++) {
          d = matrice_donne (mat, n, k) ;
          d += matrice_donne (mat, pos, k) ;
          matrice_change (mat, n, k, d) ;
        }

        for (k = 0 ; k < passage.Colonne ; k++) {
          // on répercute également ces changements dans la matrice de passage
          // sur toute la ligne cette fois
          d = matrice_donne (&passage, n, k) ;
          d += matrice_donne (&passage, pos, k) ;
          matrice_change (&passage, n, k, d) ;
        }
      }
    }

    if (faire_pivot) {
      fact = matrice_donne (mat, n,n) ; // on est sûr que fact != 0

      // on fait le pivot sur toutes les lignes après n
      for (l = n+1 ; l < mat->Ligne ; l++) {
        div = matrice_donne (mat, l, n) ;
        // si ce coefficient n'est pas nul
        if (div != 0) {
          for (k = n ; k < mat->Colonne ; k++) {
            d = matrice_donne (mat, l, k) ;
            d -= matrice_donne (mat, n, k)*div/fact ;
            matrice_change (mat, l, k, d) ;
          }

          for (k = 0 ; k < passage.Colonne ; k++) {
            // on répercute également ces changements dans la matrice de passage
            // sur toute la ligne
            d = matrice_donne (&passage, l, k) ;
            d -= matrice_donne (&passage, n, k)*div/fact ;
            matrice_change (&passage, l, k, d) ;
          }
        }
      }
    }

  }
  return passage ;
}

Matrice matrice_pivot_gauss_inverse (Matrice *mat)
{
  // la matrice de passage est carrée et est l'identité au début
  Matrice passage = matrice_new_identite (mat->Ligne) ;

  // pivot
  int n,k,l ;
  double d,div,fact ;
  int ligne = mat->Ligne ;

  // l'inversibilité ne s'applique qu'à des matrices carrées
  bool inversible = mat->Ligne == mat->Colonne ;

  // on s'arrange pour n'avoir que des uns sur les diagonales
  for (n = 0 ; n < ligne ; n++) {
    fact = matrice_donne (mat, n,n) ;
    inversible &= fact != 0 ;
    if (inversible) {
      for (k = n ; k < mat->Colonne ; k++) {
        d = matrice_donne (mat, n, k) ;
        d /= fact ;
        matrice_change (mat, n, k, d) ;
      }
      for (k = 0 ; k < passage.Colonne ; k++) {
        // on répercute également ces changements dans la matrice de passage
        d = matrice_donne (&passage, n, k) ;
        d /= fact ;
        matrice_change (&passage, n, k, d) ;
      }
    }
    else break ;
  }

  // pivot remontant sur toutes les lignes si la matrice est inversible
  if (inversible) {
    for (n = ligne-1 ; n >= 0 ; n--) {
      fact = matrice_donne (mat, n,n) ;
      // on est sûr que fact != 0
      // même, c'est forcément 1 maintenant

      // on fait le pivot sur toutes les lignes après n
      for (l = n-1 ; l >= 0 ; l--) {
        div = matrice_donne (mat, l, n) ;
        // si ce coefficient n'est pas nul
        if (div != 0) {
          for (k = n ; k < mat->Colonne ; k++) {
            d = matrice_donne (mat, l, k) ;
            d -= matrice_donne (mat, n, k)*div/fact ;
            matrice_change (mat, l, k, d) ;
          }

          for (k = 0 ; k < passage.Colonne ; k++) {
            // on répercute également ces changements dans la matrice de passage
            // sur toute la ligne
            d = matrice_donne (&passage, l, k) ;
            d -= matrice_donne (&passage, n, k)*div/fact ;
            matrice_change (&passage, l, k, d) ;
          }
        }
      }
    }
  }
  return passage ;
}

Matrice matrice_inverse (Matrice *mat)
{
  Matrice copie = matrice_copie (mat) ;
  Matrice pas1 = matrice_pivot_gauss (&copie) ;
  Matrice pas2 = matrice_pivot_gauss_inverse (&copie) ;
  Matrice prod = matrice_produit (&pas2, &pas1) ;
  matrice_free (&copie) ;
  matrice_free (&pas2) ;
  matrice_free (&pas1) ;
  return prod ;
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

Polynome polynome_new (int degre)
{
  if (degre >= 0) {
    Polynome r ;
    r.Degre = degre ;
    r.C = new double [degre+1] ;
    return r ;
  }
  else {
    Polynome r ;
    r.Degre = -1 ;
    return r ;
  }
}

void polynome_free (Polynome *p)
{
  if (p->Degre >= 0) {
    delete [] p->C ;
    p->Degre = -1 ;
  }
}


void polynome_change (Polynome *p, int n, double val)
{
  if ((n >= 0) && (n <= p->Degre)) p->C [n] = val ;
  else printf ("erreur polynome_change %d\n",n) ;
}
double polynome_donne (Polynome *p, int n)
{
  if ((n >= 0) && (n <= p->Degre)) return p->C [n] ;
  else { printf ("erreur polynome_donne %d\n",n) ; return 0 ; }
}

char *polynome_ecrit (Polynome *p)
{
  if (p->Degre >= 0)  {
    char *res = new char [p->Degre * 20 + 20] ;
    *res = 0 ;
    char *c = res ;
    int n ;
    for (n = 0 ; n <= p->Degre ; n++) {
      if (polynome_donne (p, n) != 0) {
        if ((c > res) && (polynome_donne (p, n) > 0)) sprintf (c, " + ") ;
        else sprintf (c, " ") ;
        c = res + strlen (res) ;
        if (n == 0) sprintf (c, "%g", polynome_donne (p, n)) ;
        else if (n == 1) {
          if (polynome_donne (p, n) != 1) sprintf (c, "%g*X", polynome_donne (p, n)) ;
          else sprintf (c, "X") ;
        }
        else {
          if (polynome_donne (p, n) != 1) sprintf (c, "%g*X^%d", polynome_donne (p, n), n) ;
          else sprintf (c, "X^%d",n) ;
        }
      }
      c = res + strlen (res) ;
    }
    return res ;
  }
  else {
    char *res = new char [20] ;
    strcpy (res, "nul") ;
    return res ;
  }
}

Polynome polynome_produit (Polynome *p1, Polynome *p2)
{
  Polynome p = polynome_new (p1->Degre + p2->Degre) ;
  int n ;
  int k ;
  double d ;
  // mise à zéro du polynôme produit
  for (n = 0 ; n <= p.Degre ; n++) polynome_change (&p, n, 0) ;
  // calcul du produit
  for (n = 0 ; n <= p1->Degre ; n++) {
    for (k = 0 ; k <= p2->Degre ; k++) {
      d = polynome_donne (&p, n+k) ;
      d += polynome_donne (p1, n) * polynome_donne (p2, k) ;
      polynome_change (&p, n+k, d) ;
    }
  }
  return p ;
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// méthode consacrée à la décomposition

// calcul le produit de tous les polynômes du dénominateur
// en évitant la puissance evite_puissance de l'élément evite_el
// si evite_puissance == -1, calcule tous les produits

Polynome polynome_produit_denominateur (int facteur, Polynome *element, int *puissance,
                           int evite_el, int evite_puissance)
{
  // c'est la constante égale à un
  Polynome prod = polynome_new (0) ;
  polynome_change (&prod, 0, 1) ;

  Polynome temp ;

  int n ;
  int k ;
  int fin ;
  for (n = 0 ; n < facteur ; n++) {

    if (evite_el == n) fin = puissance [n] - evite_puissance ;
    else fin = puissance [n] ;

    for (k = 0 ; k < fin ; k++) {
      temp = polynome_produit (&prod, &(element [n])) ;
      polynome_free (&prod) ;
      prod = temp ;
    }
  }
  return prod ;
}

void polynome_decale_puissance (Polynome *p, int k)
{
  if (k > 0) {
    Polynome res = polynome_new (p->Degre+k) ;
    int n ;
    for (n = 0 ; n <= res.Degre ; n++) {
       if (n < k) polynome_change (&res, n, 0) ;
       else polynome_change (&res, n, polynome_donne (p, n-k)) ;
    }
    polynome_free (p) ;
    *p = res ;
  }
}

void polynome_decomposition (Polynome *numerateur, int facteur, Polynome *element, int *puissance,
                    Polynome partie_entiere,
                    Polynome **resultat)
{
  // calcul du nombre de coefficient et du degré maximal
  int nb_coef = partie_entiere.Degre + 1 ;
  int n ;
  for (n = 0 ; n < facteur ; n++)
    nb_coef += element [n].Degre * puissance [n] ;

  // pour stocker les produits de polynômes
  Polynome *stock = new Polynome [nb_coef] ;

  // on fait les produits
  int k ;
  // on numérote les coefficients en prenant les éléments simpels les uns après les autres
  // par ordre de puissances croissantes
  // et par ordre de monômes de degré croissant

  // la partie entière

  for (k = 0 ; k <= partie_entiere.Degre ; k++) {
    stock [k] = polynome_produit_denominateur (facteur, element, puissance, -1, -1) ;
    // on décale les coefficients vers la droite de k pas
    // pour une multiplicateur de X^k
    polynome_decale_puissance (&(stock [k]), k) ;
  }

  // suite des calculs
  int numcoef = partie_entiere.Degre + 1 ;
  int l ;
  for (n = 0 ; n < facteur ; n++) {
    for (k = 0 ; k < puissance [n] ; k++) { // boucle sur 1 ou 2 coefficients
      for (l = 0 ; l < element [n].Degre ; l++) {
        stock [numcoef] = polynome_produit_denominateur (
                   facteur, element, puissance, n, k+1) ;
        polynome_decale_puissance (&(stock [numcoef]), l) ;
        numcoef++ ;
      }
    }
  }

  // construction de la matrice du système linéaire
  // ressemble à une transposition

  Matrice systeme = matrice_new (nb_coef, nb_coef) ;

  for (n = 0 ; n < nb_coef ; n++) {
    for (k = 0 ; k < nb_coef ; k++) {
      if (n <= stock [k].Degre) matrice_change (&systeme, n,k,
                                    polynome_donne (&(stock [k]), n)) ;
      else matrice_change (&systeme, n,k,0) ;
    }
  }

  // inversion de la matrice

  Matrice inverse = matrice_inverse (&systeme) ;

  // calcul des coefficients

  Matrice constante = matrice_new (nb_coef, 1) ;

  for (n = 0 ; n < nb_coef ; n++)
    if (n <= numerateur->Degre) matrice_change (&constante, n, 0,
                                    polynome_donne (numerateur, n)) ;
    else matrice_change (&constante, n, 0, 0) ;

  // résolution du système

  Matrice solution = matrice_produit (&inverse, &constante) ;

  // on place les solutions dans la structure censée les recevoir

  // partie entière
  for (n = 0 ; n <= partie_entiere.Degre ; n++)
    polynome_change (&partie_entiere, n, matrice_donne (&solution, n, 0)) ;

  // les autres coefficients
  numcoef = partie_entiere.Degre + 1 ;
  for (n = 0 ; n < facteur ; n++)
    for (k = 0 ; k < puissance [n] ; k++)
      for (l = 0 ; l < element [n].Degre ; l++) {
        polynome_change (&(resultat [n][k]), l, matrice_donne (&solution, numcoef, 0)) ;
        numcoef++ ;
      }

  // fin
  matrice_free (&inverse) ;
  matrice_free (&constante) ;
  matrice_free (&systeme) ;
  matrice_free (&solution) ;

  for (n = 0 ; n < nb_coef ; n++) polynome_free (&(stock [n])) ;
  delete [] stock ;
}



//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////


fichier texte contenant la description d'une fraction

numérateur degré 9
d0 0
d1 0
d2 0
d3 0
d4 0
d5 0
d6 0
d7 0
d8 0
d9 1
..................dénominateur produit 2
dénominateur puissance 3
dénominateur degré 1
d0 1
d1 1
dénominateur puissance 2
dénominateur degré 2
d0 2
d1 1
d2 1



suite de Syracuse

def syracuse (u0) :
    suite = [ ]
    ops   = [ ]
    u = u0
    while u != 1 :
        suite.append (u)
        if u % 2 == 0 :
            ops.append (1)
            u = u/2
        else :
            u = (3*u+1) / 2
            ops.append (0)
    suite.append(u)
    suite.append(0)
    ops.reverse()
    return suite, ops
    
def base2 (ops) :
    s = 0.0
    i = 1
    for k,v in enumerate(ops) :
        if v == 1 : s += i
        i *= 2
    return s
    
if __name__ == "__main__" :
    for i in range (1,30) :
        s,o = syracuse(i)
        t = max ( [ _ for _ in s if _%2 == 1] )
        n = base2(o)
        print "% 3d len % 3d %d %d suite" % (i,len(s), t, n), o,s

File: syracuse.tex, line 111


 1 len   1 suite [1]
 2 len   2 suite [2, 1]
 3 len   6 suite [3, 5, 8, 4, 2, 1]
 4 len   3 suite [4, 2, 1]
 5 len   5 suite [5, 8, 4, 2, 1]
 6 len   7 suite [6, 3, 5, 8, 4, 2, 1]
 7 len  12 suite [7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1]
 8 len   4 suite [8, 4, 2, 1]
 9 len  14 suite [9, 14, 7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1]
10 len   6 suite [10, 5, 8, 4, 2, 1]
11 len  11 suite [11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1]
12 len   8 suite [12, 6, 3, 5, 8, 4, 2, 1]
13 len   8 suite [13, 20, 10, 5, 8, 4, 2, 1]
14 len  13 suite [14, 7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1]
15 len  13 suite [15, 23, 35, 53, 80, 40, 20, 10, 5, 8, 4, 2, 1]
16 len   5 suite [16, 8, 4, 2, 1]

File: plus_court_chemin.tex, line 81


# coding: cp1252
import random                 # pour tirer aléatoirement des nombres
import Matrix as mat          # pour les matrices
import UserArray as ua        # pour les matrices
import math                   # fonction sqrt
import PIL.Image as Im        # pour les images
import PIL.ImageDraw as Id    # pour dessiner

def construit_ville(n, x =500, y = 500):
    """tire aléatoirement n villes dans un carrée x * y"""
    l = []
    for i in range(0,n):
        xx = x * random.random ()
        yy = y * random.random ()
        l.append ((xx,yy))
    return l

def distance_ville (l,i,j):
    """calcule la distance entre deux villes i et j de la liste l"""
    x = l [i][0] - l [j][0]
    y = l [i][1] - l [j][1]
    return math.sqrt (float (x*x+y*y))

def construit_arete (l,part = 0.15):
    """tire aléatoirement part * len (l) arêtes et construit la matrice
    d'adjacence"""
    nb  = len (l)
    m   = mat.Matrix ( [ 0 for i in range(0,nb) ]) # crée un vecteur de nb zéros
    m   = ua.transpose (m) * m                     # effectue une multiplication du vecteur
                                                   # précédent avec son vecteur transposé
                                                   # pour obtenir une matrice carrée nulle
    are = int (part * nb * nb)
    while are > 0:
        i = random.randint (0,nb-1)
        j = random.randint (0,nb-1)
        if m [i,j] > 0: continue               # si l'arête existe déjà, on recommence
        m [i,j] = int (distance_ville (l,i,j)) # on affecte comme poids à l'arête 
                                               # la distance entre les deux villes
        are -= 1
    return m

def dessin_ville_arete (l,m,chemin):
    """dessine la ville et les routes dans une image"""
    mx, my = 0,0
    for i in l:
        mx = max (mx, i [0])
        my = max (my, i [1])
    mx += 25
    my += 25
    mx, my = int (mx), int (my)
    im = Im.new ("RGB", (mx, my), (255,255,255)) # création d'une image blanche
    draw = Id.Draw(im)

    # dessin des villes
    for i in l:
        j  = (int (i [0]), int (i[1]))
        j2 = (j [0] + 10, j [1] + 10)
        draw.ellipse ((j,j2), fill = (0,0,0))

    # dessin des arêtes        
    for i in range (0,len(l)):
        for j in range (0,len(l)):
            if m [i,j] > 0:
                a = (int (l [i][0]+5), int (l [i][1]+5))
                b = (int (l [j][0]+5), int (l [j][1]+5))
                draw.line ((a,b),fill=(255,0,0))

    # dessin des villes de départ et d'arrivée
    v1 = chemin [0]
    v2 = chemin [ len (chemin)-1]
    a = (int (l [v1][0]), int (l [v1][1]))
    b = (int (l [v1][0]+10), int (l [v1][1]+10))
    draw.ellipse ((a,b), fill = (0,255,0))
    a = (int (l [v2][0]), int (l [v2][1]))
    b = (int (l [v2][0]+10), int (l [v2][1]+10))
    draw.ellipse ((a,b), fill = (0,255,0))
    
    # dessin du chemin
    for c in range (0,len(chemin)-1):
        i = chemin [c]
        j = chemin [c+1]
        print i,j
        if m [i,j] > 0:
            a = (int (l [i][0]+5), int (l [i][1]+5))
            b = (int (l [j][0]+5), int (l [j][1]+5))
            draw.line ((a,b),fill=(0,0,255))
        else:
            a = (int (l [i][0]+5), int (l [i][1]+5))
            b = (int (l [j][0]+5), int (l [j][1]+5))
            draw.line ((a,b),fill=(0,0,50))

    # on retourne l'image    
    return im

# programme principal
# construction des villes
l = construit_ville (10)
print l

# construction des arêtes
m = construit_arete (l)
print m

# choix de la ville de départ de d'arrivée
a,b = 0,0
while a == b:
    a = random.randint (0,len(l)-1)
    b = random.randint (0,len(l)-1)

print "ville de départ et d'arrivée : ",a,b    

# construction de l'image du résultat
im = dessin_ville_arete(l,m,[a,b])
im.show ()  # on affiche l'image

plus court chemin dans un graphe

# coding: cp1252
import random                 # pour tirer aléatoirement des nombres
import math                   # fonction sqrt
import PIL.Image as Im        # pour les images
import PIL.ImageDraw as Id    # pour dessiner

infini = 10000000 # l'infini est égal à dix millions, c'est une variable globale

def construit_ville(n, x =1000, y = 800):
    """tire aléatoirement n villes dans un carrée x * y, on choisit
    ces villes de sortent qu'elles ne soient pas trop proches"""
    # deux villes ne pourront pas être plus proches que mind
    mind = math.sqrt (x*x+y*y) / (n * 0.75)
    # liste vide
    l = []
    while n > 0:
        # on tire aléatoirement les coordonnées d'une ville
        xx = x * random.random ()
        yy = y * random.random ()
        # on vérifie qu'elle n'est pas trop proche d'aucune autre ville
        ajout = True
        for t in l :
            d1 = t [0] - xx
            d2 = t [1] - yy
            d  = math.sqrt (d1*d1+d2*d2)
            if d < mind :
                ajout = False  # ville trop proche
        # si la ville n'est pas trop proche des autres, on l'ajoute à la liste
        if ajout:
            l.append ((xx,yy))
            n -= 1  # une ville en moins à choisir
    return l

def distance_ville (l,i,j):
    """calcule la distance entre deux villes i et j de la liste l"""
    x = l [i][0] - l [j][0]
    y = l [i][1] - l [j][1]
    return math.sqrt (float (x*x+y*y))

def construit_arete (l,part = 0.15):
    """tire aléatoirement part * len (l) arêtes et construit la matrice
    d'adjacence"""
    global infini
    nb  = len (l)
    m   = [ [ 0 for i in range(0,nb) ] for i in range (0,nb) ] # crée un vecteur de nb zéros

    are = int (part * nb * nb)
    while are > 0:
        i = random.randint (0,nb-1)            # première ville
        j = random.randint (0,nb-1)            # seconde ville
        if i == j : continue                   # pas besoin d'arête entre i et i
        if m [i][j] > 0: continue               # si l'arête existe déjà, on recommence
        m [i][j] = int (distance_ville (l,i,j)) # on affecte comme poids à l'arête
                                                # la distance entre les deux villes
        m [j][i] = m [i][j] # symétrie de la matrice car le graphe est non orienté
        are -= 2            # deux cases de la matrice ne sont plus nulles

    # on associe à toutes les arêtes nulles de poids nul, donc inexistantes,
    # une valeur égale à l'infini pour signifier qu'elles ne sont pas reliées
    global infini
    for i in range (0, nb):
        for j in range (0, nb):
            if m [i][j] == 0:
                m [i][j] = infini

    return m

def dessin_ville_arete (l,m,chemin):
    """dessine la ville et les routes dans une image"""

    # on prend les coordonnées maximales
    mx, my = 0,0
    for i in l:
        mx = max (mx, i [0])
        my = max (my, i [1])
    mx += 25
    my += 25
    mx, my = int (mx), int (my)
    im = Im.new ("RGB", (mx, my), (255,255,255)) # création d'une image blanche
    draw = Id.Draw(im)

    # dessin des villes
    for i in l:
        j  = (int (i [0]), int (i[1]))
        j2 = (j [0] + 10, j [1] + 10)
        draw.ellipse ((j,j2), fill = (0,0,0))

    # dessin des arêtes
    global infini
    for i in range (0,len(l)):
        for j in range (0,len(l)):
            if m [i][j] > 0 and m [i][j] < infini :
                a = (int (l [i][0]+5), int (l [i][1]+5))
                b = (int (l [j][0]+5), int (l [j][1]+5))
                draw.line ((a,b),fill=(255,0,0))

    # dessin des villes de départ et d'arrivée en vert
    v1 = chemin [0]
    v2 = chemin [ len (chemin)-1]
    a = (int (l [v1][0]), int (l [v1][1]))
    b = (int (l [v1][0]+10), int (l [v1][1]+10))
    draw.ellipse ((a,b), fill = (0,255,0))
    a = (int (l [v2][0]), int (l [v2][1]))
    b = (int (l [v2][0]+10), int (l [v2][1]+10))
    draw.ellipse ((a,b), fill = (0,255,0))

    # dessin du chemin, arêtes en bleu
    for c in range (0,len(chemin)-1):
        i = chemin [c]
        j = chemin [c+1]
        if m [i][j] > 0 and m [i][j] < infini :
            a = (int (l [i][0]+5), int (l [i][1]+5))
            b = (int (l [j][0]+5), int (l [j][1]+5))
            draw.line ((a,b),fill=(0,0,255))
        else:
            a = (int (l [i][0]+5), int (l [i][1]+5))
            b = (int (l [j][0]+5), int (l [j][1]+5))
            draw.line ((a,b),fill=(0,0,50))

    # on retourne l'image
    return im

def meilleur_chemin (n,m,a,b):
    """détermine le meilleur chemin,
    n est le nombre de villes,
    m est la matrice d'adjacence,
    a est la ville de départ,
    b la ville d'arrivée"""

    # création d'un tableau, d [i] contient la meilleure distance minimale actuelle
    # séparant la ville i de la ville a
    d = [ 10000000 for i in range(0,n) ]

    # p [i] contient la ville prédécesseur qui permet d'atteindre la ville i
    # avec la distance d [i]
    p = [ -1 for i in range(0,n) ]

    # au départ, seul la distance d[a] est nulle
    d [a] = 0

    # cette boucle s'exécute tant qu'on effectue des mises à jour
    # dans le tableau d[i]
    modif = 1
    while modif > 0:
        modif = 0
        # on parcourt toutes les arêtes
        for i in range(0,n):
            for j in range (0,n):
                # nouvelle distance
                t = d [i] + m [i][j]
                if t < d [j] :  # si on a trouvé une meilleure distance minimale
                    d [j] = t   # on met à jour
                    p [j] = i
                    modif += 1  # une mise à jour de plus

    # on récupère le meilleur chemin
    l = []
    while b != -1:
        l.append (b)
        b = p [b]
    # on le retourne
    l.reverse ()
    return l

def choix_villes_depart_arrive(nb,m):
    """cette fonction choisit deux villes aléatoirement, départ et arrivée,
    elle évite que la ville et départ et d'arrivée soient les mêmes,
    elle évite que ces deux villes soient reliés par un seul arc,
    elle choisit deux villes pour lesquelles il existe un meilleur
    chemin"""
    global infini
    a,b = -1,-1
    tour = 0
    while True:
        a = random.randint (0,nb-1)     # première ville au hasard
        b = random.randint (0,nb-1)     # seconde ville au hasard
        if a == b: continue             # villes identiques, on recommence
        if m [a][b] != infini : continue # villes reliées, on recommence
        l = meilleur_chemin (nb,m,a,b)
        if l != None and len(l) > 3 :
            return a,b  # si le meilleur chemin existe,
                        # et n'est pas trop court (4 villes minimum,
                        # soit deux étapes entre a et b), alors
                        # on retourne le résultat
        else:
            tour += 1
            if tour > 120 : return 0,0       # au bout de 120 essais, on s'arrête

###############################################################################
# programme principal
# construction des villes
l = construit_ville (15)

# construction des arêtes
print "adjacence"
m = construit_arete (l)

# choix de la ville de départ de d'arrivée
print "départ"
a,b = choix_villes_depart_arrive(len(l),m)

print "recherche du meilleur chemin"
chemin  = meilleur_chemin (len(l), m, a,b)

if chemin != None and len(chemin) > 0:
    print "meilleur chemin ", a, " --> ", b, " : ", chemin
    # construction de l'image du résultat
    im = dessin_ville_arete(l,m,chemin)
    im.save ("image.png")
    im.show ()  # on affiche l'image
else :
    print "il n'existe pas de meilleur chemin"


distance d'édition

# coding: latin-1
def get_lines (file) :
    """retourne toutes les lignes d'un fichier, nettoie les fins de lignes et les espaces"""
    f = open (file, "r")
    li = f.readlines ()
    f.close ()
    return [ l.strip ("\r\n") for l in li ]
        
def distance (line1, line2) :
    """construit une distance entre deux tableaux de lignes"""
    d = { (-1,-1):(0,(-1,-1), "") }
    for i in xrange (0, len (line1)) :
        d [ i,-1 ] = (i+1, (i-1,-1), "+ " + line1 [i])
    for j in xrange (0, len (line2)) :
        d [ -1,j ] = (j+1, (-1,j-1), "- " + line2 [j])
    
    for i in xrange (0, len (line1)) :
        l1 = line1 [i]
        for j in xrange (0, len (line2)) :
            l2 = line2 [j]
            c  = abs (cmp (l1, l2))
            i1 = d [i-1,j][0] + 1
            i2 = d [i,j-1][0] + 1
            i3 = d [i-1,j-1][0] + 2*c
            if i1 <= min (i2, i3) :
                d [i,j] = (i1, (i-1,j), "+ " + l1)
            elif i2 <= min (i1, i3) :
                d [i,j] = (i2, (i,j-1), "- " + l2)
            else :
                d [i,j] = (i3, (i-1,j-1), "  " + l1)
            
    last = (len (line1)-1, len (line2)-1)
    pos  = [d [last]]
    pn   = pos [0][1]
    while pn != (-1,-1) :
        p  = pos [len (pos)-1]
        pn = p [1]
        pos.append (d [pn])
    pos.pop ()
    pos.reverse ()
    return [ p [2] for p in pos ]

def distance_file (file1, file2) :
    line1 = get_lines (file1)
    line2 = get_lines (file2)
    return distance (line1, line2)
    
if __name__ == "__main__" :
    file1 = "filedistance.py"
    file2 = "filedistance2.py"
    res   = distance_file (file1, file2)
    for r in res :
        print r

File: plus_court_chemin.tex, line 469


def distance (line1, line2) :
      """construit une distance entre deux tableaux de lignes"""
-     d = { (-1,-1):(0,(-1,-1)) }
+     d = { (-1,-1):(0,(-1,-1), "") }
+     for i in xrange (0, len (line1)) :
+         d [ i,-1 ] = (i+1, (i-1,-1), "+ " + line1 [i])
+     for j in xrange (0, len (line2)) :
+         d [ -1,j ] = (j+1, (-1,j-1), "- " + line2 [j])
      
      for i in xrange (0, len (line1)) :
          l1 = line1 [i]
          for j in xrange (0, len (line2)) :

algorithme de Kohonen

# coding: cp1252
import random                 # pour tirer aléatoirement des nombres
import math                   # fonctions cos, sin
import pygame                 # pour les affichages

def construit_ville(n, x =1000, y = 700):
    """tire aléatoirement n villes dans un carrée x * y, on choisit
    ces villes de sortent qu'elles ne soient pas trop proches"""
    # deux villes ne pourront pas être plus proches que mind
    mind = math.sqrt (x*x+y*y) / (n * 0.75)
    # liste vide
    l = []
    while n > 0:
        # on tire aléatoirement les coordonnées d'une ville
        xx = x * random.random ()
        yy = y * random.random ()
        # on vérifie qu'elle n'est pas trop proche d'aucune autre ville
        ajout = True
        for t in l :
            d1 = t [0] - xx
            d2 = t [1] - yy
            d  = math.sqrt (d1*d1+d2*d2)
            if d < mind :
                ajout = False  # ville trop proche
        # si la ville n'est pas trop proche des autres, on l'ajoute à la liste
        if ajout:
            l.append ((xx,yy))
            n -= 1  # une ville en moins à choisir
    return l

def display_ville(villes,screen,bv):
    """dessine les villes à l'écran"""
    color  = 255,0,0
    color2 = 0,255,0
    for v in villes:
        pygame.draw.circle (screen, color, v, 10)
    pygame.draw.circle (screen, color2, villes [bv], 10)

def construit_liste_neurones (villes, nb = 0):
    """place les neurones sur l'écran,
    il y a autant de neurones que de villes,
    le paramètre villes est la liste des villes"""
    
    if nb == 0 : nb = len (villes)

    # coordonnées maximale
    maxx,maxy = 0,0
    for v in villes:
        if v [0] > maxx : maxx = v [0]
        if v [1] > maxy : maxy = v [1]

    maxx /= 2
    maxy /= 2

    if nb > 1 :
        # dispose les neurones en ellipse
        n = []
        for i in range (0, nb):
            x = maxx + maxx * math.cos (math.pi * 2 * float (i) / nb) / 4
            y = maxy + maxy * math.sin (math.pi * 2 * float (i) / nb) / 4
            n.append ((x,y))
        return n
    else :
        n = [ (maxx, maxy) ]
        return n

def distance_euclidienne_carree (p1,p2):
    """calcule la distance euclidienne entre deux points"""
    x = p1[0] - p2[0]
    y = p1[1] - p2[1]
    return x*x+y*y
    
def ajoute_vecteur (v,n):
    """ajoute deux vecteurs entre eux"""
    return ( v [0] + n [0], v [1] + n [1])

def soustrait_vecteur (v,n):
    """soustrait deux vecteurs"""
    return ( v [0] - n [0], v [1] - n [1])

def multiplie_vecteur (v,f):
    """multiplie un vecteur par un scalaire"""
    return ( v [0] * f, v [1] * f)
    
def poids_attirance(p,dist):
    """calcul le poids d'attraction d'une neurone vers une ville"""
    d  = p [0] * p [0] + p [1] * p [1]
    d  = math.sqrt (d)
    d  = dist / (d + dist)
    return d
    
def vecteur_norme(p):
    """calcul la norme d'un vecteur"""
    return math.sqrt (p [0] * p [0] + p [1] * p [1])

def deplace_neurone (n,villes,neurones, dist_w, forces, compte):
    """déplace le neurone de plus proche de la ville n, déplace ses voisins
        @param    villes        liste des villes
        @param    neurones      liste des neurones
        @param    dist          distance d'attirance
        @param    forces        force de déplacement des voisins du neurones
        @param    compte        incrémente compte [n] où n est l'indice du neurone choisi
        @return                 indice du neurone le plus proche"""

    # recherche du neurone le plus proche
    v       = villes [n]
    proche  = 0
    dist    = distance_euclidienne_carree(v, neurones [0])
    for i in xrange(1,len(neurones)):
        d = distance_euclidienne_carree (v, neurones [i])
        if d < dist :
            dist    = d
            proche  = i
            
    # vecteur de déplacement
    i             = proche
    compte [i]   += 1
    n             = neurones [i]
    vec           = soustrait_vecteur (v,n)
    poids         = poids_attirance (vec, dist_w)
    vec           = multiplie_vecteur (vec, poids)
    n             = ajoute_vecteur (n, vec)
    neurones [i]  = n

    # déplacement des voisins
    for k in xrange(0,len (forces)):
        i1  = (i + k + 1)   % len (neurones)
        i2  = (i - k - 1 + len (neurones)) % len (neurones)
        n1  = neurones [i1]
        n2  = neurones [i2]

        vec   = soustrait_vecteur (n, n1)
        poids = poids_attirance (vec, dist_w)
        vec   = multiplie_vecteur (vec, poids)
        vec   = multiplie_vecteur (vec, forces [k])
        n1    = ajoute_vecteur (n1, vec)

        vec   = soustrait_vecteur (n, n2)
        poids = poids_attirance (vec, dist_w)
        vec   = multiplie_vecteur (vec, poids)
        vec   = multiplie_vecteur (vec, forces [k])
        n2    = ajoute_vecteur (n2, vec)

        neurones [i1] = n1
        neurones [i2] = n2
        
    return proche

def iteration (villes,neurones, dist, forces, compte_v, compte_n):
    """choisit une ville aléatoirement et attire le neurones le plus proche,
    choisit cette ville parmi les villes les moins fréquemment choisies
        @param    villes     liste des villes
        @param    neurones   liste des neurones
        @param    dist       distance d'attirance
        @param    forces     force de déplacement des voisins du neurones
        @param    compte_v   incrémente compte_v [n] où n est l'indice de la ville choisie
        @param    compte_n   incrémente compte_n [n] où n est l'indice du neurone choisi
        @return              indices de la ville et du neurone le plus proche"""

    m             = min (compte_v)
    ind           = [i for i in xrange (0,len (villes)) if compte_v [i] == m]
    n             = random.randint (0,len(ind)-1)
    n             = ind [n]
    compte_v [n] += 1
    return n, deplace_neurone (n,villes,neurones,dist, forces, compte_n)

def display_neurone(neurones,screen,bn):
    """dessine les neurones à l'écran"""
    color  = 0,0,255
    color2 = 0,255,0
    for n in neurones :
        pygame.draw.circle (screen, color, n, 5)
    pygame.draw.circle (screen, color2, neurones [bn], 5)
    if len (neurones) > 1:
        pygame.draw.lines (screen, color, True, neurones, 2)
        
def modifie_structure(neurones,compte, nb_sel):
    """modifie la structure des neurones, supprime les neurones jamais
    déplacés, et ajoute des neurones lorsque certains sont trop sollicités"""

    def cmp_add (i,j):
        return cmp (i [0], j [0])
    
    if nb_sel > 0 :
        # supprime les neurones les moins sollicités
        sup = [i for i in xrange (0, len(neurones)) if compte [i] == 0 ]
        if len(sup) > 0:
            sup.sort ()
            sup.reverse ()
            for i in sup:
                del compte [i]
                del neurones [i]

        # on ajoute un neurone lorsque max (compte) >= 2 * min (compte)
        add = []
        for i in xrange (0,len(compte)):
            if compte [i] > nb_sel:
                d1     = math.sqrt ( distance_euclidienne_carree (neurones [i], \
                                neurones [(i+1) % len (neurones)] ))
                d2     = math.sqrt ( distance_euclidienne_carree (neurones [i], \
                                neurones [(i-1 + len (neurones)) % len (neurones)] ))
                if d1 > d2 : d1 = d2
                p      = neurones [i]
                p      = (p[0] + random.randint (0, int (d1 / 2)) , \
                                p [1] + random.randint (0, int (d1 / 2)) )
                add.append ((i,p,0))
                
        add.sort (cmp_add)
        add.reverse ()
        for a in add:
            neurones.insert (a [0], a [1])
            compte.insert (a [0], a [2])

    # on remet les compteurs à zéros
    for i in xrange (0, len (compte)) : compte [i] = 0

def moyenne_proximite (villes):
    """retourne la distance moyenne entre deux villes les plus proches"""
    c = 0
    m = 0
    for v in villes:
        mn = 100000000
        for vv in villes:
            if v == vv : continue
            d = distance_euclidienne_carree (v,vv)
            if d < mn : mn = d
        c += 1
        m += math.sqrt (mn)
    m /= float (c)
    return m

def attendre_clic (screen,x,y):
    """dessine une croix sur l'écran et attend la pression d'un clic de souris"""
    color   = 0,0,0
    pygame.draw.line (screen, color, (0,0), (x-1,y-1))
    pygame.draw.line (screen, color, (x-1,0), (0,y-1))
    pygame.display.flip ()
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break
                
################################################################################

if __name__ == "__main__" :
    pygame.init ()
    size      = width, height = x,y = 800, 500
    black     = 0, 0, 0
    white     = 255,255,255
    screen    = pygame.display.set_mode(size)
    villes    = construit_ville (30, x,y)
    neurones  = construit_liste_neurones (villes, 3)
    compte_n  = [0 for i in neurones]
    compte_v  = [0 for i in villes]
    tour      = 2
    maj       = tour * len (villes)
    
    dist      = moyenne_proximite (villes) * 4
    fs        = [ 1.5, 1, 0.75, 0.5, 0.25 ]
    
    iter      = 0
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT: sys.exit()
            if event.type == pygame.MOUSEBUTTONUP:
                attendre_clic (screen,x,y)
    
        iter += 1
    
        if iter % maj == 0 :
            modifie_structure (neurones,compte_n, tour)
            dist *= 0.99
            f2    = [ w * 0.90 for w in fs]
            fs    = f2
            
        bv, bn = iteration (villes,neurones, dist, fs, compte_v, compte_n)
    
        screen.fill (white)
        display_ville (villes, screen, bv)
        display_neurone (neurones, screen, bn)
    
        if iter == 1: attendre_clic (screen,x,y)
        
        pygame.display.flip ()
    

voyageur de commerce et algorithme de Kruskal

# coding: cp1252
import random                 # pour tirer aléatoirement des nombres
import math                   # fonctions cos, sin
import pygame                 # pour les affichages
import copy                    # pour copier des résultats intermédiaires
import bresenham_ligne as brl # pour dessiner les arêtes dans l'écran des zones
#import psyco                  # pour accélérer le programme

def attendre_clic (screen,x,y):
    """dessine une croix sur l'écran et attend la pression d'un clic de souris"""
    color   = 0,0,0
    pygame.draw.line (screen, color, (0,0), (x-1,y-1))
    pygame.draw.line (screen, color, (x-1,0), (0,y-1))
    pygame.display.flip ()
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break
                

def construit_ville(n, x =1000, y = 700):
    """tire aléatoirement n villes dans un carrée x * y, on choisit
    ces villes de sortent qu'elles ne soient pas trop proches"""
    # deux villes ne pourront pas être plus proches que mind
    mind = math.sqrt (x*x+y*y) / (n * 0.75)
    # liste vide
    l = []
    while n > 0:
        # on tire aléatoirement les coordonnées d'une ville
        xx = x * random.random ()
        yy = y * random.random ()
        # on vérifie qu'elle n'est pas trop proche d'aucune autre ville
        ajout = True
        for t in l :
            d1 = t [0] - xx
            d2 = t [1] - yy
            d  = math.sqrt (d1*d1+d2*d2)
            if d < mind :
                ajout = False  # ville trop proche
        # si la ville n'est pas trop proche des autres, on l'ajoute à la liste
        if ajout:
            l.append ((xx,yy))
            n -= 1  # une ville en moins à choisir
    return l

def display_ville(villes,screen,bv):
    """dessine les villes à l'écran"""
    color  = 255,0,0
    color2 = 0,255,0
    for v in villes:
        pygame.draw.circle (screen, color, v, 3)
    pygame.draw.circle (screen, color2, villes [bv], 3)

def display_neurone(neurones,screen,bn):
    """dessine les neurones à l'écran"""
    color  = 0,0,255
    color2 = 0,255,0
    for n in neurones :
        pygame.draw.circle (screen, color, n, 3)
    pygame.draw.circle (screen, color2, neurones [bn], 3)
    if len (neurones) > 1:
        pygame.draw.lines (screen, color, True, neurones, 2)
        
def distance (p1,p2):
    """calcule la distance entre deux villes"""
    x = p1 [0] - p2[0]
    y = p1 [1] - p2[1]
    return math.sqrt (x*x + y*y)

def repartition_zone (villes, zone_taille, ask_zone = False) :
    """répartit les villes en zones, retourne les villes rangées par zones,
    chaque éléments zones [z][k] contient : 
        - les coordonnées de la ville
        - ses coordonnées en zone, (zx, zy)
        - son indice dans la liste villes
    la fonction retourne également le nombre de zones 
    selon l'axe des abscisses et l'axe des ordonnées,
    retourne aussi le nombre de zones, si ask_zone est True, 
    retourne un paramètre supplémentaire : zone"""
    print "gestion des zones"
    X,Y = 0,0
    for v in villes:
        X = max (v [0] // zone_taille, X)
        Y = max (v [1] // zone_taille, Y)
    X += 1        
    Y += 1
        
    # attribution des zones
    zone    = []
    nb      = len (villes)
    Zmax    = 0
    for i in xrange (0,len (villes)):
        v       = villes [i]
        x       = int (v [0] // zone_taille)
        y       = int (v [1] // zone_taille)
        z       = int (y * X + x)
        Zmax    = max (z,Zmax)
        zone.append ((z, v, (x,y), i))
        
    # rangement par zone
    Zmax   += 1
    zones = [ [] for i in xrange (0,Zmax) ]
    for z in zone:
        zones [ z [0] ].append ((z [1], z [2], z [3]))
        
    if ask_zone :
        return zones,X,Y,Zmax,zone
    else :
        return zones,X,Y,Zmax
    
def voisinage_zone (z,Zmax,X,Y):
    """retourne la liste des voisins d'une zone z 
    sachant qu'il y a X zones sur l'axe des abscisses et Y zones sur l'axe des ordonnées,
    Zmax est le nombre de zones,
    inclus z dans cette liste"""
    x       = z % X
    y       = z // X
    voisin_ = [z]
    if x > 0: voisin_.append (z-1)
    if x < X: voisin_.append (z+1)
    if y > 0: voisin_.append (z-X)
    if y < Y: voisin_.append (z+X)
    if x > 0 and y > 0 : voisin_.append (z-1-X)
    if x > 0 and y < Y : voisin_.append (z-1+X)
    if x < X and y > 0 : voisin_.append (z+1-X)
    if x < X and y < Y : voisin_.append (z+1+X)
    voisin = [ int (i) for i in voisin_ if i >= 0 and i < Zmax ]
    return voisin

def arbre_poids_minimal(villes, zone_taille):
    """construit l'arbre de poids minimal, retourne une liste de 
    listes, chaque sous-liste associée à une ville contient la liste des ses voisins,
    zone_taille permet de découper l'image en zones, 
    les distances ne seront calculées que si 
    deux éléments sont dans la même zone ou dans une zone voisine"""
    
    def tri_distance (u,v):
        if u [2] < v [2] : return -1
        elif u [2] > v [2] : return 1
        else : return 0
        
    zones,X,Y,Zmax = repartition_zone (villes, zone_taille)

    # calcul des distances
    print "calcul des distances"
    li      = []

    for z in xrange (0,len (zones)):
        if z % 1000 == 0 : print "zone ", z, len(zones)
        voisin  = voisinage_zone (z,Zmax,X,Y)
        for v in zones [z]:
            for zz in voisin:
                for u in zones [zz]:
                    d = distance (v [0], u [0])
                    li.append ((v [2], u [2], d))
    
    print "tri ", len(li)
    li.sort (tri_distance)    
    
    # composantes connexes
    print "construction de l'arbre"
    
    # nombre de composantes connexes
    nb_comp     = len (villes)                            
    
    # indice de la composante d'une ville
    num_comp    = [ i for i in xrange(0,len(villes)) ]   
    
    # liste des voisins pour chaque ville
    arbre       = [ [] for i in xrange(0,len(villes)) ]  
    
    # liste des villes par composante connexe
    list_comp   = [ [i] for i in xrange(0,len(villes)) ] 
 
    iii = 0 
    for c in li:
        if iii % 10000 == 0 : print "arête ", iii, len(li)
        iii += 1
        i,j = c [0], c [1]
        if num_comp [i] != num_comp [j]:
            # on relie les villes i et j car elles appartiennent 
            # à des composantes connexes différentes
            arbre [i].append (j)        # i est voisine de j
            arbre [j].append (i)        # j est voisine de i
            cl = num_comp [i]           # composante connexe restante
            ki = num_comp [j]           # composante connexe à aggréger à la précédente
            for k in list_comp [ki]: 
                num_comp [k] = cl
                list_comp [cl].append (k)
            list_comp [ki] = []
            nb_comp -= 1                # une composante connexe en moins
        
        if nb_comp == 0: 
            break  # il n'y a plus qu'une seule composante connexe, inutile de continuer
    
    return arbre
    
def display_arbre (villes, arbre, mult = 1):
    """dessine le graphe de poids minimal défini par arbre"""
    if mult == 2 : 
        color = 0,255,0
        l = 4
    else :
        l = 1
        color = 0,0,255
    
    for i in xrange (0, len (villes)):
        for j in arbre [i]:
            v  = (villes [i][0] * mult, villes [i][1] * mult)
            vv = (villes [j][0] * mult, villes [j][1] * mult)
            pygame.draw.line (screen, color, v, vv, l)
          
def vecteur_points (p1,p2):
    """retourne le vecteur entre les points p1 et p2"""
    return ( p2 [0] - p1 [0], p2 [1] - p1 [1])
    
def vecteur_norme (vec):
    """retourne la norme d'un vecteur"""
    return math.sqrt (vec [0] * vec [0] + vec [1] * vec [1])
    
def vecteur_cosinus (vec1, vec2):
    """retourne le cosinus entre deux vecteurs, utilise le produit scalaire"""
    norm1 = vecteur_norme (vec1)
    norm2 = vecteur_norme (vec2)
    if norm1 == 0: return 1
    if norm2 == 0: return 1
    scal  = vec1 [0] * vec2 [0] + vec1 [1] * vec2 [1]
    return scal / (norm1 * norm2)

def vecteur_sinus (vec1, vec2):
    """retourne le sinus entre deux vecteurs, utilise le produit vectoriel"""
    norm1 = vecteur_norme (vec1)
    norm2 = vecteur_norme (vec2)
    if norm1 == 0:  return 0
    if norm2 == 0:  return 0
    scal  = vec1 [0] * vec2 [1] - vec1 [1] * vec2 [0]
    return scal / (norm1 * norm2)
    
def oppose_vecteur (vec):
    """retourne le vecteur opposé"""
    return (- vec [0], - vec [1])
    
def circuit_eulerien (villes, arbre):
    """définit un circuit eulérien, villes contient la liste des villes,
    tandis que arbre est une liste de listes, arbre [i] est la liste des villes
    connectées à la ville i, 
    on suppose que arbre est un graphe de poids minimal non orienté,
    l'algorithme ne marche pas s'il existe des villes confondues"""
    
    # on choisit une ville qui est une extrémité et parmi celle-là on la choisit au hasard
    has = []
    for i in xrange (0,len (villes)):
        n = len (arbre [i])
        if n == 1: has.append (i)

    bm = random.randint (0, len (has) -1)
    bm = has [bm]
        
    # vecteur, le circuit eulérien contient 
    # nécessairement 2 * len (villes) noeuds puisque c'est
    # le graphe eulérien d'un arbre de poids minimal non orienté
    vec     = (1,1)
    chemin  = [bm]
    while len (chemin) < 2 * len (villes)-1 :
        
        v = villes [bm]
        
        ma      = - math.pi - 1
        bvec    = vec 
        opvec   = oppose_vecteur (vec)
        for k in xrange (0, len (arbre [bm])) :
            l     = arbre [bm][k]
            vec2  = vecteur_points (v, villes [l])
            if opvec == vec2 :
                angle = -math.pi
            else :
                cos   = vecteur_cosinus (vec, vec2)
                sin   = vecteur_sinus   (vec, vec2)
                angle = math.atan2 (sin, cos)
            if angle > ma :
                ma      = angle
                bl      = k
                bvec    = vec2
                
        b   = arbre [bm][bl]
        chemin.append (b)
        del arbre [bm][bl]  # on supprime l'arc pour ne plus l'utiliser
        bm  = b
        vec = bvec
        
    return chemin

def circuit_hamiltonien (chemin):
    """extrait un circuit hamiltonien depuis un circuit eurlérien"""
    nb      = max (chemin) + 1
    res     = []
    coche   = [ False for i in xrange (0, nb) ]
    for c in chemin :
        if coche [c] : continue 
        res.append (c)
        coche [c] = True
        
    return res

def equation_droite (p1,p2) :
    """retourne l'équation d'une droite passant par p1 et p2,
    ax + by + c = 0, retourne les coefficients a,b,c"""
    vec = vecteur_points (p1,p2)
    a = vec [1]
    b = - vec [0]
    c = - a * p1 [0] - b * p1 [1]
    return a,b,c
    
def evaluation_droite (a,b,c,p):
    """l'équation d'une droite est : ax + by + c, retourne la valeur
    de cette expression au point p"""
    return a * p [0] + b * p [1] + c

def intersection_segment (p1,p2,p3,p4):
    """dit si les segments [p1 p2] et [p3 p4] ont une intersection, 
    ne retourne pas l'intersection"""
    # équation de la droite (p1 p2)
    a1,b1,c1 = equation_droite (p1,p2)
    a2,b2,c2 = equation_droite (p3,p4)
    s1 = evaluation_droite (a2,b2,c2,p1)
    s2 = evaluation_droite (a2,b2,c2,p2)
    s3 = evaluation_droite (a1,b1,c1,p3)
    s4 = evaluation_droite (a1,b1,c1,p4)
    if s1 * s2 <= 0 and s3 * s4 <= 0 : return True
    else : return False 
    
def longueur_chemin (chemin):
    """retourne la longueur d'un chemin"""
    s   = 0
    nb  = len (chemin)
    for i in xrange (0,nb) :
        s += distance ( chemin [i], chemin [ (i+1) % nb ])
    return s
    
def retournement_essai (chemin, i,j, negligeable = 1e-5):
    """dit s'il est judicieux de parcourir le chemin entre les sommets i et j
    en sens inverse, si c'est judicieux, change le chemin et retourne True,
    sinon, retourne False, 
    si j < i, alors la partie à inverser est 
    i, i+1, i+2, ..., len(chemin) -1, 0, 1, ..., j"""
    
    nb = len (chemin)
    if i == j : return False
    if j - i == -1 : return False
    if j - i - nb == -1 : return False
    
    ia = (i - 1 + nb) % nb
    ja = (j + 1 ) % nb
    # arcs enlevés
    d_ia_i = distance (chemin [ia], chemin [i])
    d_j_ja = distance (chemin [j],  chemin [ja])
    # arcs ajoutés
    d_ia_j = distance (chemin [ia], chemin [j])
    d_i_ja = distance (chemin [i],  chemin [ja])
    # amélioration ?
    d = d_ia_j + d_i_ja - d_j_ja - d_ia_i 
    if d >= - negligeable : return False
        
    # si amélioration, il faut retourner le chemin entre les indices i et j
    jp = j
    if jp < i : jp = j + nb
    ip = i
    
    while ip < jp :
        i           = ip % nb 
        j           = jp % nb  
        ech         = chemin [i]
        chemin [i]  = chemin [j]
        chemin [j]  = ech
        ip = ip+1
        jp = jp-1
    
    return True
    
def retournement (chemin, taille) :
    """amélioration du chemin par un algorithme simple, 
    utilise des retournements de taille au plus <taille>,
    retourne le nombre de modifications"""
    
    # traitement des petits retournements
    nb = len (chemin)
    nb_change = 1
    nbtout    = 0
    retour      = { }
    while nb_change > 0 :
        nb_change   = 0
        for t in xrange (1,taille+1):
            retour [t] = 0
            for i in xrange (0, nb) :
                j = (i + t) % nb
                b = retournement_essai (chemin, i, j)
                if b : 
                    retour [t] += 1
                    nb_change  += 1
        nbtout += nb_change
    print "nombre de retournements %d longueur : \t %10.0f détail \t" \
                % (nbtout, longueur_chemin (chemin)), " détail : ", retour
    return nbtout
    
def echange_position_essai (chemin, a,b, x, inversion, negligeable = 1e-5):
    """échange la place des villes ka à kb pour les placer entre les villes i et i+1,
    si inversion est True, on inverse également le chemin inséré, si inversion est False,
    on ne l'inverse pas,
    si cela améliore, déplace les villes et retourne True, sinon, retourne False"""
    
    nb = len(chemin)
    xa = (x + 1) % nb
    ka = (a - 1 + nb) % nb
    kb = (b + 1 ) % nb
    
    if not inversion :
    
        if x == ka : return False
        if x == kb : return False
        if xa == ka : return False
        if b < a :
            if a <= x <= b + nb : return False
        elif a <= x <= b : return False
        if b < a :
            if a <= x + nb <= b + nb : return False
        elif a <= x + nb <= b : return False
            
        # arcs enlevés
        d_x_xa = distance (chemin [x],  chemin [xa])
        d_ka_a = distance (chemin [ka], chemin [a])
        d_b_kb = distance (chemin [b],  chemin [kb])
        # arcs ajoutés
        d_ka_kb = distance (chemin [ka], chemin [kb])
        d_x_a   = distance (chemin [x],  chemin [a])
        d_b_xa  = distance (chemin [b],  chemin [xa])
        
        d = d_ka_kb + d_x_a + d_b_xa - d_x_xa - d_ka_a - d_b_kb 
        if d >= -negligeable : return False
    
        # villes à déplacer
        ech = []
        bp = b
        if bp < a : bp = b + nb
        for i in xrange (a,bp+1):
            ech.append (chemin [i % nb] )
        diff = bp - a + 1
        
        xp = x
        if xp < b : xp += nb
        
        for l in xrange (b+1,xp+1) :
            ll              = l % nb
            bp              = (a + l - b-1) % nb
            chemin [bp]     = chemin [ll]
            
        for l in xrange (0,len(ech)) :
            chemin [ (x+l-diff+1 + nb) % nb ] = ech [l]
            
        return True
        
    else :

        if x == ka : return False
        if x == kb : return False
        if xa == ka : return False
        if b < a :
            if a <= x <= b + nb : return False
        elif a <= x <= b : return False
        if b < a :
            if a <= x + nb <= b + nb : return False
        elif a <= x + nb <= b : return False
        
            
        # arcs enlevés
        d_x_xa = distance (chemin [x],  chemin [xa])
        d_ka_a = distance (chemin [ka], chemin [a])
        d_b_kb = distance (chemin [b],  chemin [kb])
        # arcs ajoutés
        d_ka_kb = distance (chemin [ka], chemin [kb])
        d_x_b   = distance (chemin [x],  chemin [b])
        d_a_xa  = distance (chemin [a],  chemin [xa])
        
        d = d_ka_kb + d_x_b + d_a_xa - d_x_xa - d_ka_a - d_b_kb 
        if d >= -negligeable  : return False
    
        # villes à déplacer
        ech = []
        bp = b
        if bp < a : bp = b + nb
        for i in xrange (a,bp+1):
            ech.append (chemin [i % nb] )
        ech.reverse ()
        diff = bp - a + 1

        cop = copy.copy (chemin)
        
        xp = x
        if xp < b : xp += nb
        
        for l in xrange (b+1,xp+1) :
            ll              = l % nb
            bp              = (a + l - b-1) % nb
            chemin [bp]     = chemin [ll]
            
        for l in xrange (0,len(ech)) :
            chemin [ (x+l-diff+1 + nb) % nb ] = ech [l]
            
        return True
        
def dessin_arete_zone (chemin, taille_zone, X,Y):
    """retourne une liste de listes de listes, 
    res [i][j] est une liste des arêtes passant près de la zone (x,y) = [i][j], 
    si k in res [i][j], alors l'arête k,k+1 est dans la zone (i,j),
    X est le nombre de zones horizontalement, Y est le nombre de zones verticalement,
    taille_zone est la longueur du côté du carré d'une zone"""
    res = [ [ [] for j in xrange (0,Y+1) ]  for i in xrange (0,X+1) ]
    nb = len (chemin)
    for i in xrange (0,nb):
        a       = chemin [i]
        b       = chemin [(i+1) % nb]
        x1,x2   = int (a [0] // taille_zone), int (b [0] // taille_zone)
        y1,y2   = int (a [1] // taille_zone), int (b [1] // taille_zone)
        line = brl.trace_ligne (x1,y1,x2,y2)
        for x,y in line:
            res [x][y].append (i)
    return res
    
def voisinage_zone_xy (x,y,X,Y):
    """retourne la liste des voisins d'une zone (x,y) 
    sachant qu'il y a X zones sur l'axe des abscisses et Y zones sur l'axe des ordonnées,
    inclus z dans cette liste"""
    voisin = [(x,y)]
    if x > 0   : voisin.append ((x-1,y))
    if x < X-1 : voisin.append ((x+1,y))
    if y > 0   : voisin.append ((x,y-1))
    if y < Y-1 : voisin.append ((x,y+1))
    if x > 0   and y > 0   : voisin.append ((x-1,y-1))
    if x > 0   and y < Y-1 : voisin.append ((x-1,y+1))
    if x < X-1 and y > 0   : voisin.append ((x+1,y-1))
    if x < X-1 and y < Y-1 : voisin.append ((x+1,y+1))
    return voisin    
    
def echange_position (chemin, taille, taille_zone, X,Y, grande = 0.5) :
    """regarde si on ne peut pas déplacer un segment de longueur taille 
    pour supprimer les arêtes les plus longues,
    au maximum <grande> longues arêtes,
    retourne le nombre de changement effectués,
    X est le nombre de zones horizontalement,
    Y est le nombre de zones verticalement,
    taille_zone est la longueur d'un côté du carré d'une zone"""
    
    nb = len(chemin)

    def tri_arete (x,y):
        """pour trier la liste l par ordre décroissant"""
        if x [2] < y [2] : return 1
        elif x [2] > y [2] : return -1
        else : return 0
            
    # list des arêtes triés par ordre décroissant
    la = []
    for i in xrange (0,nb) :
        im = (i+1) % nb
        la.append ( (i, im, distance (chemin [i], chemin [im]) ) )
    la.sort (tri_arete)
    
    # zone associé à chaque arête
    zone = dessin_arete_zone (chemin, taille_zone, X, Y)

    dseuil    = la [ int (nb * grande) ] [ 2 ]
    nbtout    = 0
    nb_change = 0
    iarete    = 0
    retour    = { }
    for t in xrange (1, taille+1): retour [t] = 0
        
    while iarete < nb :
        nb_change   = 0
        arete       = la [iarete]
        iarete     += 1
        x           = arete [0]
        xm          = arete [1]
        a           = chemin [x]
        b           = chemin [xm]
        d           = distance ( a,b )
        if d < dseuil : break    # arête trop petite
            
        # zone traversée par la ligne
        x1,x2   = int (a [0] // taille_zone), int (b [0] // taille_zone)
        y1,y2   = int (a [1] // taille_zone), int (b [1] // taille_zone)
        ens     = brl.trace_ligne (x1,y1,x2,y2)
        ville   = []
        for k,l in ens:
            voisin = voisinage_zone_xy (k,l,X,Y)
            for u,v in voisin :
                ville.extend (zone [u][v])
                
        # on supprime les doubles
        ville.sort ()
        if len (ville) == 0 : continue 
        sup = []
        mx = -1
        for v in ville:
            if v == mx : sup.append (v)
            mx = v
        for s in sup:
            ville.remove (s)

        # on étudie les possibilités de casser l'arête (x,xm) aux alentours des villes 
        # comprise dans l'ensemble ville
        for t in xrange (1, taille+1):

            for i in ville:

                # on essaye d'insérer le sous-chemin (x- t + 1 + nb)  --> x
                # au milieu de l'arête i,i+1
                b = echange_position_essai (chemin, (x- t + 1 + nb) % nb,x, i, False)
                if b : 
                    nb_change  += 1
                    retour [t] += 1
                    continue
                    
                # on essaye d'insérer le sous-chemin (xm+ t - 1)  --> xm
                # au milieu de l'arête i,i+1
                b = echange_position_essai (chemin, (xm + t - 1) % nb, xm, i, False)
                if b : 
                    nb_change  += 1
                    retour [t] += 1
                    continue

                # on essaye de casser l'arête x,xm en insérant 
                # le sous-chemin i --> (i+t) % nb
                b = echange_position_essai (chemin, i, (i+t) % nb, x, False)
                if b : 
                    nb_change  += 1
                    retour [t] += 1
                    continue
                # idem
                b = echange_position_essai (chemin, i, (i+t) % nb, x, True)
                if b : 
                    retour [t] += 1
                    nb_change  += 1
                    continue
                # idem
                b = echange_position_essai (chemin, (i-t+nb) % nb, i, x, False)
                if b : 
                    nb_change  += 1
                    retour [t] += 1
                    continue
                # idem
                b = echange_position_essai (chemin, (i-t + nb) % nb, i, x, True)
                if b : 
                    retour [t] += 1
                    nb_change  += 1
                    continue
                    
        nbtout += nb_change
        
    print "nombre de déplacements %d longueur :   \t %10.0f détail \t" \
                    % (nbtout, longueur_chemin (chemin)), " détail : ", retour
    return nbtout

def supprime_croisement (chemin, taille_zone, X,Y) :
    """supprime les croisements d'arêtes,
    retourne le nombre de changement effectués,
    X est le nombre de zones horizontalement,
    Y est le nombre de zones verticalement,
    taille_zone est la longueur d'un côté du carré d'une zone"""
    
    nb = len(chemin)
    
    # zone associé à chaque arête
    zone    = dessin_arete_zone (chemin, taille_zone, X, Y)
    nbtout  = 0 

    for i in xrange (0,nb) :
        im      = (i+1) % nb
        a       = chemin [i]
        b       = chemin [im]
        
        # zone traversée par la ligne
        x1,x2   = int (a [0] // taille_zone), int (b [0] // taille_zone)
        y1,y2   = int (a [1] // taille_zone), int (b [1] // taille_zone)
        ens     = brl.trace_ligne (x1,y1,x2,y2)
        ville   = []
        for k,l in ens:
            voisin = voisinage_zone_xy (k,l,X,Y)
            for u,v in voisin :
                ville.extend (zone [u][v])
                
        # on supprime les doubles
        ville.sort ()
        if len (ville) == 0 : continue 
        sup = []
        mx = -1
        for v in ville:
            if v == mx : sup.append (v)
            mx = v
        for s in sup:
            ville.remove (s)
            
        nb_change = 0
        for v in ville :
            b = retournement_essai (chemin, i,v) 
            if b :
                nb_change += 1
                continue
            b = retournement_essai (chemin, im,v) 
            if b :
                nb_change += 1
                continue

        nbtout += nb_change
        
    print "nombre de croisements %d longueur :      \t %10.0f détail \t" \
                    % (nbtout, longueur_chemin (chemin))
    return nbtout
    
def amelioration_chemin (chemin, taille_zone, X, Y, taille = 10, screen = None):
    """amélioration du chemin par un algorithme simple, 
    utilise des retournements de taille au plus taille,
    traite les arcs qui se croisent,
    traite les grands arcs, utilise un quadrillage de taille window,
    X est le nombre de zones horizontalement,
    Y est le nombre de zones verticalement,
    taille_zone est la longueur d'un côté du carré d'une zone"""

    white = 255,255,255

    #première étape rapide
    nb = 1
    while nb > 0:
        nb  = retournement (chemin, taille)
        if screen != None:
            screen.fill (white)
            display_neurone(chemin, screen, 0)
            pygame.display.flip ()
        
    # amélioration
    nb = 1
    while nb > 0:
        nb  = retournement (chemin, taille)
        if screen != None:
            screen.fill (white)
            display_neurone(chemin, screen, 0)
            pygame.display.flip ()
        nb += echange_position (chemin, taille / 2, taille_zone, X, Y)
        if screen != None:
            screen.fill (white)
            display_neurone(chemin, screen, 0)
            pygame.display.flip ()
        nb += supprime_croisement (chemin, taille_zone,X,Y)
        if screen != None:
            screen.fill (white)
            display_neurone(chemin, screen, 0)
            pygame.display.flip ()
            
        if screen != None :
            for event in pygame.event.get():
                if event.type == pygame.MOUSEBUTTONUP :
                    print "attendre......................................................"
                    attendre_clic (screen,0,0)
                    print "reprise"
                    break
    
################################################################################

if __name__ == "__main__" :
    pygame.init ()
    # pysco.full ()   # pour accélérer le programme, va trois à quatre fois plus vite

    nb_ville  = 500
    partie    = 10
    
    size        = width, height = x,y = 800, 500
    dec         = size [0]
    black       = 0, 0, 0
    white       = 255,255,255
    screen      = pygame.display.set_mode(size)
    villes      = construit_ville (nb_ville, x, y)
    taille_zone = 20
    X           = int (x // taille_zone)
    Y           = int (y // taille_zone)
    
    print "taille de l'image : ", size
    print "nombre de villes : ", len(villes)
    
    screen.fill (white)
    display_ville (villes, screen, 0)
    pygame.display.flip ()
    attendre_clic(screen,0,0)
        
    print "calcul"
    window  = int (math.sqrt (x*y / len(villes)) * 2)
    arbre   = arbre_poids_minimal (villes, window)
    arbre2  = copy.deepcopy (arbre)
    
    print "dessin" ,window
    display_arbre (villes, arbre)
    attendre_clic(screen,0,0)
    
    print "circuit eulérien"
    chemin = circuit_eulerien (villes ,arbre)
    
    print "circuit hamiltonien"
    neurone = circuit_hamiltonien (chemin)
    
    print "dessin"
    neurones = [ villes [i] for i in neurone ]
    display_neurone(neurones, screen, 0)
    attendre_clic(screen,0,0)
    
    print "amelioration_chemin et dessin"
    amelioration_chemin (neurones, taille_zone, X, Y, partie, screen)
    screen.fill (white)
    display_ville (villes, screen, 0)
    display_neurone(neurones, screen, 0)
    attendre_clic(screen,0,0)
    
    # taille double
    print "taille double"
    size      = (size [0], size [1])
    screen    = pygame.display.set_mode(size)
    screen.fill (white)
    #display_arbre (villes, arbre2, 2)
    display_neurone (neurones, screen, 2)
    attendre_clic(screen,0,0)    


edit distance and sequence alignment


class EditDistanceAlignment_Element :
    """
    element used during the computation of an edit distance
    """
    def __init__ (self, pos, cost, el1, el2, op) :
        """
        constructor
        @param      pos         (tuple) position
        @param      cost        cost
        @param      el1         first element
        @param      el2         second element
        @param      op          operation (cmp, ins1, ins2, None)
        """
        self.pos  = pos
        self.el1  = el1
        self.el2  = el2
        self.cost = cost
        self.op   = op    # "cmp", "ins1", "ins2", None
        
    def __str__ (self) :
        """
        usual
        """
        return "pos1=%d pos2=%d cost=%s op=%s el1=%s el2=%s" % \
            (self.pos[0], self.pos[1], "%1.3f" % self.cost if self.cost != None else "None", 
                    self.op, self.el1, self.el2)

def EditDistanceAlignment ( exp1, 
                            exp2,
                            cmpinsFunction      = lambda x,y : 0.0 if x == y else 1.0,
                            constantEpsilon     = 1e-5,
                            constantInfinite    = 1e5,
                            setPosition         = [ (-1,-1), (-1,0), (0,-1), ],
                            returnDistance      = True) :
    """
    computes the edit distance and the alignment between two expressions or strings
    @param      exp1                first sequence
    @param      exp2                second sequence
    @param      cmpinsFunction      function which returns a cost for a comparison or an insertion (None for the other element), example:
                                        @code
                                        lambda x,y : 0.0 if x == y else 1.0
                                        @endcode
    @param      constantEpsilon     unused
    @param      constantInfinite    a weight for impossible configuration
    @param      setPosition         direction to consider while running the edit distance
    @param      returnDistance      if True, the function returns a float, otherwise, a path
    @return                         a float (if returnDistance is True) or a sequence of @see cl EditDistanceAlignment_Element)
    """
    
    if len(exp1) == 0 : 
        return 0 if len(exp2) == 0 else sum ( [ cmpinsFunction (None, e) for e in exp2] ) 
    if len(exp2) == 0 : 
        return sum ( [ cmpinsFunction (e, None) for e in exp1] ) 
            
    l1   = len(exp1) + 1
    l2   = len(exp2) + 1
    l    = l1*l2
    pa   = { }
    pred = { }
    
    for n,el in enumerate (exp1) :
        pa  [n,0] = cmpinsFunction(el,None)
        pred[n,0] = (n-1,0) 
    
    for n,el in enumerate (exp2) :
        pa  [0,n] = cmpinsFunction(None,el)
        pred[0,n] = (0,n-1) 
        
    pa[0,0] = 0.0
    
    for n1,el1 in enumerate (exp1) :
        for n2,el2 in enumerate (exp2) :
            
            cost = [ ]
            for dx,dy in setPosition :
                c = pa.get ( (n1+dx+1, n2+dy+1), constantInfinite)
                if dx == 0 :
                    if dy == -1 :
                        cost.append ( (c+cmpinsFunction (None, el2), (dx,dy)  ) )
                    else :
                        raise NotImplementedError ("unable to deal with with case yet %d,%d" %(dx,dy)) 
                elif dy == 0 :
                    if dx == -1 :
                        cost.append ( (c+cmpinsFunction (el1, None), (dx,dy)  ) )
                    else :
                        raise NotImplementedError ("unable to deal with with case yet %d,%d" %(dx,dy)) 
                else :
                    if dx == -1 and dy == -1:
                        cost.append ( (c+cmpinsFunction (el1, el2), (dx,dy)  ) )
                    else :
                        raise NotImplementedError ("unable to deal with with case yet %d,%d" %(dx,dy)) 
                        
                mn               = min ( cost )
                pa   [n1+1,n2+1] = mn[0]
                pred [n1+1,n2+1] = (n1+mn[1][0]+1,n2+mn[1][1]+1)
                
    if returnDistance :
        return pa [ l1-1,l2-1 ]
    else :
        align = [ ]
        p     = l1-1,l2-1
        while p[0] != -1 and p[1] != -1 :
            e = EditDistanceAlignment_Element (p, pa[p], None,None,None)
            align.append (e)
            p = pred[p]
            
        align.pop()
        align.reverse()
        
        for n,th in enumerate(align) :
            pr      = None if n == 0 else align[n-1]
            th.pos  = (th.pos[0]-1,th.pos[1]-1)
            
            if pr == None :
                if  th.pos == (0,0) : kind = "cmp" 
                elif th.pos[1] == -1 : kind = "ins1" 
                else : kind = "ins2" 
            else :
                if th.pos == (pr.pos[0]+1, pr.pos[1]+1) : kind = "cmp" 
                elif th.pos[0] == pr.pos[0] : kind = "ins2"
                else : kind = "ins1"
    
            th.op = kind
            if kind == "cmp" :
                th.el1 = exp1[th.pos[0]]
                th.el2 = exp2[th.pos[1]]
            elif kind == "ins1" :
                th.el1 = exp1[th.pos[0]]
                th.el2 = None
            elif kind == "ins2" :
                th.el1 = None
                th.el2 = exp2[th.pos[1]]
                
        return align
        
def EditDistanceAlignmentNormalized ( exp1, 
                            exp2,
                            cmpinsFunction      = lambda x,y : 0.0 if x == y else 1.0,
                            constantEpsilon     = 1e-5,
                            constantInfinite    = 1e5,
                            setPosition         = [ (-1,-1), (-1,0), (0,-1), ],
                            returnDistance      = True) :
            
    def function (x,y) :
        if x == y : return 0
        l1 = 0 if x == None else len(x)
        l2 = 0 if y == None else len(y)
        if l1 > l2 :
            return l2*(0.5 / len(exp1) + 0.5 / len(exp2)) + (l1-l2)*1.0 / len(exp1) 
        elif l2 > l1 :
            return l1*(0.5 / len(exp1) + 0.5 / len(exp2)) + (l2-l1)*1.0 / len(exp2) 
        else :
            return l1*(0.5 / len(exp1) + 0.5 / len(exp2)) 
    
    return EditDistanceAlignment(exp1, exp2, function, 
                                 constantEpsilon, constantInfinite, setPosition, returnDistance)
            
def EditDistanceAlignmentWordSequenceInString (exp1, 
                            exp2,
                            cmpinsFunction      = lambda x,y : 0.0 if x == y else 1.0,
                            constantEpsilon     = 1e-5,
                            constantInfinite    = 1e5,
                            setPosition         = [ (-1,-1), (-1,0), (0,-1), ],
                            returnDistance      = True) :
            
    spl1 = exp1.split(' ')
    spl2 = exp2.split(' ')
    def function (x,y) :
        if x == y : return 0
        if x == None : return len(spl2)
        if y == None : return len(spl1)
        return EditDistanceAlignment(x,y, cmpinsFunction, 
                            constantEpsilon, constantInfinite, 
                            setPosition, True)
    
    return EditDistanceAlignment(spl1, spl2, function, 
                                 constantEpsilon, constantInfinite, setPosition, returnDistance)
        
if __name__ == "__main__" :

    def cmpins (x,y) :
        if x == y : return 0
        if x in ("n","m") and y in ("n","m") : return 0.25
        if (x == "s" and y == None) or (x == None and y == "s") : return 0.5
        return 1

    # alignment
    res = EditDistanceAlignment ("cmp", "cmps", cmpins, returnDistance = False)
    for _ in res : print (_)    

    # only distance
    res = EditDistanceAlignment ("cmp", "cmps", cmpins)
    print (res)

    # alignment
    # other writing
    res = EditDistanceAlignment (list("cmp"), list("cmps"), cmpins, returnDistance = False)
    for _ in res : print (_)   

    # numbers
    def cmpins_int (x,y) :
        if x == y : return 0.
        if x in (8,9) and y in (8,9) : return 0.25
        return 1.

    res = EditDistanceAlignment ([1,2,8,7], [1,2,9,7], cmpins_int)
    print (res)
    res = EditDistanceAlignment ([1,2,8,7], [1,2,9,7], cmpins_int, returnDistance = False)
    for _ in res : print (_)   

    

distance entre graphes

#coding:latin-1
"""
@file
@brief This modules gathers classes which describe a graph. The main method is DistanceMatchingGraphsPaths
which does a kind of alignments between acyclic graphs.
"""


import os, sys, copy, re

if sys.version_info.major >= 3 :
    fileprint = print
else :
    def pprint(*x) : print (x)
    fileprint = pprint

try :
    import importme
except ImportError :
    pass


    
class Vertex :
    """
    defines a vertex of a graph
    """
    def __init__ (self, nb, label, weight) :
        """
        constructor
        @param      nb      (int) index of the vertex
        @param      label   (str) label
        @para       weight  (float)
        """
        self.nb     = nb         # kind of id
        self.label  = label      # label
        self.pair   = (None,None)
        self.edges  = { }
        self.predE  = { }
        self.succE  = { }
        self.weight = weight
        
    #~ def __str__ (self) :
        #~ """
        #~ usual
        #~ """
        #~ li = [ "V %s l:%s nbSucc:%d" % (str(self.nb), self.label, len (self.succE)) ]
        #~ if self.pair != (None,None) :   
            #~ li.append (   "    (%s,%s)" % (str(self.pair[0]), str (self.pair[1])) )
        #~ if self.edges != None :         
            #~ li.extend ( [ "    %s->%s" % (k,str(v)) for k,v in self.edges.items() ] )
        #~ if self.predE != None :         
            #~ li.extend ( [ "    prev %s %s" % (k,"") for k,v in self.predE.items() ] )
        #~ return "\n".join(li)
        
    def __str__(self) : 
        """
        usual
        """
        return self.Label()
        
    def isVertex (self) : 
        """
        returns True
        """
        return True
        
    def isEdge (self) : 
        """
        returns False
        """
        return False
        
    def Label(self) : 
        """
        returns the label
        """
        return self.label
        
            
class Edge :
    """
    defines an edge
    """
    
    def __init__ (self,from_, to, label, weight) :
        """
        constructor
        @param  from_       (int)
        @param  to          (int)
        @param  label       (str)
        @param  weight      (float)
        """
        self.from_, self.to = from_,to
        self.nb         = from_, to
        self.label      = label
        self.pair       = (None,None)
        self.weight     = weight
        if self.from_ == "00" and self.to == "00" : raise AssertionError ("should not happen")
        if self.from_ == "11" and self.to == "11" : raise AssertionError ("should not happen")
            
    #~ def __str__ (self) :
        #~ """
        #~ usual
        #~ """
        #~ li = [ "E %s->%s l:%s" % (str(self.from_), str(self.to), self.label) ]
        #~ if self.pair != (None,None) : 
            #~ li.append ("    (%s,%s)" % (str(self.pair[0]), str (self.pair[1])) )
        #~ return "\n".join(li)
        
    def __str__(self) : 
        """
        usual
        """
        return self.Label()

    def isVertex (self) : 
        """
        returns False
        """
        return False
        
    def isEdge (self) : 
        """
        returns True
        """
        return True
        
    def Label(self) : 
        """
        returns the label
        """
        return self.label
        
        


class Graph :
    """
    defines a graph
    """
    
    # graph is a dictionary        
    def GetListOfVertices (graph) :
        edges = [ edge[:2] for edge in graph ]
        unique = { }
        for i,j in edges : unique [i] = unique [j] = 1
        vertices = list(unique.keys())
        vertices.sort()
        return vertices 
    GetListOfVertices = staticmethod(GetListOfVertices)
    
    def __init__ (self, edgeList, vertexLabel = { }, 
                        addLoop = False,
                        weightVertex = 1.,
                        weightEdge = 1.) :
        """
        constructor
        
        @param      edgeList        list of edges
        @param      addLoop         automatically add a loop on each vertex (an edge from a vertex to itself)
        @param      weightVertex    weight for every vertex
        @param      weightEdge      weight for every edge
        """
        if type(edgeList) is str :
            self.load_from_file(edgeList, addLoop)
        else :
            self.vertices = { }
            self.edges    = { }
            self.labelBegin = "00"
            self.labelEnd   = "11"
            vid = Graph.GetListOfVertices (edgeList)
            for u in vid : 
                self.vertices [ u ] = Vertex (u, vertexLabel.get(u, str(u)), weightVertex)
            for e in edgeList :
                i,j = e[:2]
                l   = "" if len(e) < 3 else e[2]
                self.edges [ i,j ] = Edge (i,j, str(l), weightEdge)
            self.private__init__(addLoop, weightVertex, weightEdge)
            
    def __getitem__ (self, index) :
        """
        returns a vertex or an edge if no vertex with the given index was found
        @param      index   id (index) to look for
        @return             Vertex or Edge
        """
        if isinstance (index, str) :
            return self.vertices[index]
        elif isinstance (index, tuple) :
            return self.edges[index]
        else :
            raise KeyError("unable to get element " + str(index))
            
    def load_from_file (self, filename, addLoop) :
        """
        loads a graph from a file
        @param      filename        file name
        @param      addLoop         @see me __init__
        """
        lines = open(filename, "r").readlines ()
        regV = re.compile("\\\"?([a-z0-9_]+)\\\"? *[[]label=\\\"(.*)\\\"[]]")
        regE = re.compile("\\\"?([a-z0-9_]+)\\\"? *-> *\\\"?" + \
                                "([a-z0-9_]+)\\\"? *[[]label=\\\"(.*)\\\"[]]")
        edgeList = []
        vertexLabel = { }
        for line in lines :
            line = line.strip("\r\n ;")
            ed = regE.search(line)
            ve = regV.search(line)
            if ed :
                g = ed.groups()
                edgeList.append ( (g[0], g[1], g[2] ) )
            elif ve :
                g = ve.groups()
                vertexLabel [g[0]] = g[1]
        if len(vertexLabel) == 0 or len(edgeList) == 0 :
            raise OSError("unable to parse file " + filename)
        self.__init__(edgeList, vertexLabel, addLoop)
            
    def private__init__(self, addLoop, weightVertex, weightEdge) :
        if addLoop :
            for k,v in self.vertices.items () :
                if k != self.labelBegin and k != self.labelEnd :
                    self.edges [k,k] = Edge (k,k, "", weightEdge)
        self.ConnectRootAndLeave(weightVertex, weightEdge)
        self.ComputePredecessor()
        self.ComputeSuccessor()

    def ConnectRootAndLeave (self, weightVertex, weightEdge) :
        order = self.GetOrderVertices()
        roots = [ v for v,k in order.items () if k == 0 ]
        vert = { }
        for o in order : vert [o] = 0
        for k,v in self.edges.items () :
            if k[0] != k[1] : 
                vert[k[0]] += 1
        for r in roots :
            if self.labelBegin not in self.vertices :
                self.vertices [ self.labelBegin ] = \
                        Vertex ( self.labelBegin, self.labelBegin, weightVertex)
            if r != self.labelBegin :
                self.edges [ self.labelBegin, r ] = \
                        Edge ( self.labelBegin, r, "", weightEdge )

        leaves = [ k for k,v in vert.items () if v == 0 ]
        for r in leaves:
            if self.labelEnd not in self.vertices :
                self.vertices [ self.labelEnd ] = \
                        Vertex ( self.labelEnd, self.labelEnd, weightVertex)
            if r != self.labelEnd :
                self.edges [ r, self.labelEnd ] = \
                        Edge ( r, self.labelEnd, "", weightEdge )
            
    def GetOrderVertices (self) :
        edges = self.edges
        order = { }
        for k,v in edges.items () :
            order[k[0]] = 0
            order[k[1]] = 0

        modif = 1
        while modif > 0 :
            modif = 0
            for k,v in edges.items () :
                i,j = k
                if i != j and order[j] <= order[i] : 
                    order [j] = order[i]+1
                    modif += 1
        
        return order

    def __str__(self) :
        li = []
        for k,v in self.vertices.items() :
            li.append ( str (v) )
        for k,e in self.edges.items() :
            li.append ( str(e) )
        return "\n".join(li)
        
    def ComputePredecessor (self) :
        """
        usual
        """
        pred = { }
        for i,j in self.edges :
            if j not in pred : pred[j] = { }
            pred [j][i,j] = 0
        for k,v in pred.items () :
            for n in v :
                self.vertices[k].predE [n] = self.edges [n]
                
    def ComputeSuccessor (self) :
        succ = { }
        for i,j in self.edges :
            if i not in succ : succ[i] = { }
            succ [i][i,j] = i,j
        for k,v in succ.items () :
            for n in v :
                self.vertices[k].succE[n] = self.edges[n]
                
    def GetMatchingFunctions(self, functionMatchVertices, fonctionMatchEdges, 
                                cost = False) :
        """
        returns default matching functions between two vertices and two edges
        @param      functionMatchVertices   if not None, this function is returned, othewise, it returns a new fonction. 
                                                Example if cost is False:
                                                @code
                                                lambda v1,v2,g1,g2,w1,w2 : v1.label == v2.label
                                                @endcode
                                                Example if cost is True:
                                                @code
                                                def tempF1 (v1,v2,g1,g2,w1,w2) :
                                                    if v1 != None and not v1.isVertex() : raise TypeError("should be a vertex")
                                                    if v2 != None and not v2.isVertex() : raise TypeError("should be a vertex")
                                                    if v1 == None and v2 == None : return 0
                                                    elif v1 == None or v2 == None : 
                                                        return v2.weight*w2 if v1 == None else v1.weight*w1 
                                                    else : 
                                                        return 0 if v1.label == v2.label else 0.5*(v1.weight*w1 + v2.weight*w2) 
                                                @endcode
        @param      fonctionMatchEdges      if not None, this function is returned, othewise, it returns a new fonction. 
                                                Example if cost is False:
                                                @code
                                                lambda e1,e2,g1,g2,w1,w2 : e1.label == e2.label and 
                                                            (e1.from_ != e1.to or e2.from_ != e2.to) and 
                                                            (e1.from_ != self.labelBegin or e1.to != self.labelBegin) and 
                                                            (e1.from_ != self.labelEnd or e1.to != self.labelEnd) 
                                                @endcode
                                                Example if cost is True:
                                                @code
                                                def tempF2 (e1,e2,g1,g2,w1,w2) :
                                                    if e1 != None and not e1.isEdge() : raise TypeError("should be an edge")
                                                    if e2 != None and not e2.isEdge() : raise TypeError("should be an edge")
                                                    if e1 == None and e2 == None : return 0
                                                    elif e1 == None or e2 == None : 
                                                        return e2.weight*w2 if e1 == None else e1.weight*w1
                                                    elif e1.label != e2.label : return 0.5*(e1.weight*w1 + e2.weight*w2)
                                                    else :
                                                        lab1 = g1.vertices [e1.from_].label == g2.vertices [e2.from_].label 
                                                        lab2 = g1.vertices [e1.to].label == g2.vertices [e2.to].label
                                                        if lab1 and lab2 : return 0
                                                        else :  return e1.weight*w1 + e2.weight*w2
                                                @endcode
        @param      cost                    if True, the returned function should return a float, otherwise a boolean
        @return                             a pair of functions
        """
        if cost :
            
            if functionMatchVertices == None :
                def tempF1 (v1,v2,g1,g2,w1,w2) :
                    if v1 != None and not v1.isVertex() : raise TypeError("should be a vertex")
                    if v2 != None and not v2.isVertex() : raise TypeError("should be a vertex")
                    if v1 == None and v2 == None : return 0
                    elif v1 == None or v2 == None : 
                        return v2.weight*w2 if v1 == None else v1.weight*w1 
                    else : 
                        return 0 if v1.label == v2.label else 0.5*(v1.weight*w1 + v2.weight*w2) 
                functionMatchVertices = tempF1 
                
            if fonctionMatchEdges == None : 
                def tempF2 (e1,e2,g1,g2,w1,w2) :
                    if e1 != None and not e1.isEdge() : raise TypeError("should be an edge")
                    if e2 != None and not e2.isEdge() : raise TypeError("should be an edge")
                    if e1 == None and e2 == None : return 0
                    elif e1 == None or e2 == None : 
                        return e2.weight*w2 if e1 == None else e1.weight*w1
                    elif e1.label != e2.label : return 0.5*(e1.weight*w1 + e2.weight*w2)
                    else :
                        lab1 = g1.vertices [e1.from_].label == g2.vertices [e2.from_].label 
                        lab2 = g1.vertices [e1.to].label == g2.vertices [e2.to].label
                        if lab1 and lab2 : return 0
                        else :  return e1.weight*w1 + e2.weight*w2
            
                fonctionMatchEdges = tempF2
        else :
            if functionMatchVertices == None : 
                functionMatchVertices = lambda v1,v2,g1,g2,w1,w2 : v1.label == v2.label
            if fonctionMatchEdges == None : 
                fonctionMatchEdges = lambda e1,e2,g1,g2,w1,w2 : e1.label == e2.label and \
                            (e1.from_ != e1.to or e2.from_ != e2.to) and \
                            (e1.from_ != self.labelBegin or e1.to != self.labelBegin) and \
                            (e1.from_ != self.labelEnd or e1.to != self.labelEnd) 
        return functionMatchVertices, fonctionMatchEdges
            
    def CommonPaths (self, graph2, 
                     functionMatchVertices = None, 
                     fonctionMatchEdges = None, 
                     noClean = False) :
        functionMatchVertices, fonctionMatchEdges = \
                        self.GetMatchingFunctions(functionMatchVertices, fonctionMatchEdges)
        g = Graph ( [] )
        vfirst = Vertex ( self.labelBegin, "%s-%s" % (self.labelBegin, self.labelBegin),
                        (self.vertices[self.labelBegin].weight + 
                         graph2.vertices[self.labelBegin].weight)/2)
        g.vertices [ self.labelBegin ] = vfirst
        vfirst.pair = self.vertices [ self.labelBegin ], graph2.vertices [ self.labelBegin ]
        
        modif = 1
        while modif > 0 :
            modif = 0
            add = { }
            for k,v in g.vertices.items () :
                
                v1,v2 = v.pair
                if len(v.succE) == 0 :
                    for e1 in v1.succE :
                        for e2 in v2.succE :
                            oe1 = self.edges[e1]
                            oe2 = graph2.edges[e2]
                            if fonctionMatchEdges(oe1,oe2,self,graph2,1.,1.) :
                                tv1 = self.vertices [oe1.to]
                                tv2 = graph2.vertices [oe2.to]
                                if functionMatchVertices (tv1, tv2, self, graph2, 1., 1.) :
                                    # we have a match
                                    ii = "%s-%s" % (tv1.nb, tv2.nb)
                                    if tv1.nb == self.labelEnd and tv2.nb == self.labelEnd :
                                        ii = self.labelEnd
                                    lab = "%s-%s" % (tv1.label, tv2.label) \
                                              if tv1.label != tv2.label else tv1.label
                                    tv = Vertex (ii, lab, (tv1.weight+tv2.weight)/2)
                                    lab = "%s-%s" % (oe1.label, oe2.label) \
                                              if oe1.label != oe2.label else oe1.label
                                    ne = Edge (v.nb, tv.nb,  lab, (oe1.weight + oe2.weight)/2)
                                    add [ tv.nb ] = tv
                                    g.edges [ ne.from_, ne.to ] = ne
                                    ne.pair = oe1,oe2
                                    tv.pair = tv1,tv2
                                    v.succE [ ne.from_, ne.to ] = ne
                                    modif += 1
            for k,v in add.items () :
                g.vertices[k] = v

        if not noClean : 
            #g.ConnectRootAndLeave()
            g.ComputePredecessor()
            g.CleanDeadEnds()
        return g
        
    def CleanDeadEnds (self) :
        edgesToKeep = { }
        verticesToKeep = { }
        if self.labelEnd in self.vertices :
            v = self.vertices  [ self.labelEnd ]
            verticesToKeep [v.nb] = False
            
            modif = 1
            while modif > 0 :
                modif = 0
                add = { }
                for k,v in verticesToKeep.items() :
                    if v : continue
                    modif += 1
                    verticesToKeep [k] = True
                    for pred,vv in self.vertices[k].predE.items() :
                        edgesToKeep [ pred ] = True
                        add [ vv.from_ ] = verticesToKeep.get ( vv.from_, False )
                for k,v in add.items () :
                    verticesToKeep [k] = v

            remove = {}
            for k in self.vertices : 
                if k not in verticesToKeep : remove[k] = True
            for k in remove : del self.vertices[k]

            remove = {}
            for k in self.edges: 
                if k not in edgesToKeep : remove[k] = True
            for k in remove : del self.edges[k]
        else :
            self.vertices = {}
            self.edges = { }
            
    def EnumerateAllPaths (self, edgesAndVertices, begin = []) :
        if len(self.vertices) > 0 and len(self.edges) > 0 :
            if edgesAndVertices :
                last = begin[-1] if len(begin) > 0 \
                                  else self.vertices [self.labelBegin] 
            else :
                last = self.vertices[begin[-1].to] if len(begin) > 0 \
                                        else self.vertices [self.labelBegin] 
                                            
            if edgesAndVertices and len(begin) == 0 :
                begin = [ last ]

            for ef in last.succE :
                e = self.edges[ef]
                path = copy.copy(begin)
                v = self.vertices[e.to]
                if e.to == e.from_ :
                    # cycle
                    continue
                else :
                    path.append (e)
                    if edgesAndVertices : path.append (v)
                    if v.label == self.labelEnd :
                        yield path
                    else :
                        for p in self.EnumerateAllPaths(edgesAndVertices, path) :
                            yield p
                        
    def EditDistancePath (self, p1, p2, g1, g2, 
                          functionMatchVertices = None, 
                          fonctionMatchEdges    = None,
                          useMin                = False,
                          debug                 = False) :
        """
        Tries to align two paths from two graphs
        @param      p1                      path 1 (from g1)
        @param      p2                      path 2 (from g2)
        @param      g1                      graph 1
        @param      g2                      graph 2
        @param      functionMatchVertices   function which gives a distance bewteen two vertices, 
                                            if None, it take the output of @see me GetMatchingFunctions
        @param      fonctionMatchEdges      function which gives a distance bewteen two edges, 
                                            if None, it take the output of @see me GetMatchingFunctions
        @param      useMin                  the returned is based on a edit distance, if this parameter is True, the returned value will be:
                                            @code
                                            if useMin :
                                                n = min (len(p1), len(p2))
                                                d = d*1.0 / n if n > 0 else 0        
                                            @endcode
        @param      debug                   unused
        @return                             2-uple: distance, aligned path
        """
        functionMatchVertices, fonctionMatchEdges = \
                 self.GetMatchingFunctions(functionMatchVertices, fonctionMatchEdges, True)
        dist = { (-1,-1) : (0,None,None) }
        
        w1 = 1.0 / len(p1) if useMin else 1.
        w2 = 1.0 / len(p2) if useMin else 1.
        
        for i1,eorv1 in enumerate (p1) :
            for i2,eorv2 in enumerate (p2) :
                np = i1,i2
                posit = [ ((i1-1,i2),  (eorv1, None)), 
                          ((i1,i2-1),  (None, eorv2)),
                          ((i1-1,i2-1),(eorv1,eorv2)), ]
                
                if eorv1.isEdge() and eorv2.isEdge() :
                    func = fonctionMatchEdges
                elif eorv1.isVertex() and eorv2.isVertex() :
                    func = functionMatchVertices
                else :
                    func = lambda x,y,g1,g2,w1,w2 : \
                                0.5*(x.weight*w1 + y.weight*w2) if x != None and y != None \
                                else (x.weight*w1 if y == None else y.weight*w2)
                    
                for p,co in posit :
                    if p in dist :
                        c0 = dist [p][0]
                        c1 = func (co[0], co[1], g1, g2, w1, w2)
                        c  = c0 + c1
                        if np not in dist : 
                            dist[np] = (c, p, co, (c0, c1))
                        elif c < dist[np][0] :
                            dist[np] = (c, p, co, (c0, c1))
                            
        last = dist [len(p1)-1, len(p2)-1]
        path = [ ]
        while last[1] != None :
            path.append (last)
            last = dist [ last[1] ] 
        
        path.reverse()
        
        d = dist [len(p1)-1, len(p2)-1][0]
        if useMin :
            n = min (len(p1), len(p2))
            d = d*1.0 / n if n > 0 else 0
        return d, path
        
    def privateCountLeftRight (self, valuesInList) :
        countLeft = { }
        countRight = { }
        for k,v in valuesInList :
            i,j = v
            if i not in countRight : countRight [i] = { }
            countRight [i][j] = countRight [i].get (j, 0) + 1
            if j not in countLeft : countLeft [j] = { }
            countLeft [j][i] = countLeft [j].get (i, 0) + 1
        return countLeft, countRight
        
    def privateKruskalMatrix (self, matrix, reverse) :
        countLeft, countRight = self.privateCountLeftRight(matrix)
        cleft, cright = len(countLeft), len(countRight)
        cold = len(matrix)
        matrix.sort (reverse = reverse)
        count = max ( max ( [ sum (_.values()) for _ in countRight.values() ] ),
                      max ( [ sum (_.values()) for _ in countLeft.values() ] ) )
        oldcount = count
        while count > 1 :
            k,v = matrix.pop()
            i,j = v
            countRight[i][j] -= 1
            countLeft [j][i] -= 1
            count = max ( max ( [ max (_.values()) for _ in countRight.values() ] ),
                          max ( [ max (_.values()) for _ in countLeft.values() ] ) )
        
        mini = min(cleft, cright)
        if len(matrix) < mini :
            raise Exception("impossible: the smallest set should get all" + \
                  "its element associated to at least one coming from the other set")
                              
    def privateStringPathMatching (self, path, skipEdge = False) :
        temp = []
        for p in path :
            u,v = p[2]
            if skipEdge and ( (u != None and u.isEdge()) \
                              or (v != None and v.isEdge()))  :
                continue
            su = "-" if u == None else str(u.nb)
            sv = "-" if v == None else str(v.nb)
            s  = "(%s,%s)" % (su,sv)
            temp.append (s)
        return " ".join(temp)

    def DistanceMatchingGraphsPaths (self, graph2, 
                     functionMatchVertices = None, 
                     fonctionMatchEdges = None, 
                     noClean = False, 
                     store = None,
                     useMin = True,
                     weightVertex = 1.,
                     weightEdge = 1.) :
        """
        compute an alignment between two graphs
        @param      graph2                  the other graph
        @param      functionMatchVertices   function which gives a distance bewteen two vertices, 
                                            if None, it take the output of @see me GetMatchingFunctions
        @param      fonctionMatchEdges      function which gives a distance bewteen two edges, 
                                            if None, it take the output of @see me GetMatchingFunctions
        @param      noClean                 if True, clean unmatched vertices and edges
        @param      store                   if None, does nothing, if it is a dictionary, the function will store here various
                                            information about how th matching was operated
        @param      useMin                  @see me EditDistancePath
        @param      weightVertex            a weight for every vertex
        @param      weightEdge              a weight for every edge
        @return                 2 tuple:
                                    - a distance
                                    - a graph containing the aligned paths between the two graphs
        """
                         
        functionMatchVertices, fonctionMatchEdges = \
                        self.GetMatchingFunctions(functionMatchVertices, fonctionMatchEdges, True)
        
        paths1 = list(self.EnumerateAllPaths (True))
        paths2 = list(graph2.EnumerateAllPaths (True))
        
        if store != None :
            store ["nbpath1"] = len (paths1) 
            store ["nbpath2"] = len (paths2) 
        
        matrix_distance = { }
        for i1,p1 in enumerate(paths1) :
            for i2,p2 in enumerate(paths2) :
                matrix_distance [i1,i2] = self.EditDistancePath (p1,p2, self, graph2,
                            functionMatchVertices, fonctionMatchEdges, useMin = useMin)
        
        if store != None : store ["matrix_distance"] = matrix_distance
        reduction = [ (v[0], k) for k,v in matrix_distance.items() ]
        if store != None : store ["path_mat1"] = copy.deepcopy(reduction)
        self.privateKruskalMatrix(reduction, False)
        if store != None : store ["path_mat2"] = copy.deepcopy(reduction)

        pairCountEdge = { }
        pairCountVertex = { }
        for k,v in reduction :
            res,path = matrix_distance [v]
            for el in path :
                n1,n2 = el[2]
                if n1 != None and n2 != None :
                    if n1.isEdge () and n2.isEdge() :
                        add = n1.nb, n2.nb
                        pairCountEdge[add] = pairCountEdge.get(add,0) + 1
                    elif n1.isVertex () and n2.isVertex() :
                        add = n1.nb, n2.nb
                        pairCountVertex[add] = pairCountVertex.get(add,0) + 1
                        
        if store != None :
            store["pairCountVertex"] = pairCountVertex
            store["pairCountEdge"] = pairCountEdge
        
        reductionEdge = [ (v, k) for k,v in pairCountEdge.items() ]
        if store != None : store ["edge_mat1"] = copy.copy (reductionEdge)
        self.privateKruskalMatrix(reductionEdge, True)
        if store != None : store ["edge_mat2"] = copy.copy (reductionEdge)

        reductionVertex = [ (v, k) for k,v in pairCountVertex.items() ]
        if store != None : store ["vertex_mat1"] = copy.copy (reductionVertex)
        self.privateKruskalMatrix(reductionVertex, True)
        if store != None : store ["vertex_mat2"] = copy.copy (reductionVertex)
        
        countEdgeLeft,   countEdgeRight   = self.privateCountLeftRight(reductionEdge)
        countVertexLeft, countVertexRight = self.privateCountLeftRight(reductionVertex)

        resGraph   = Graph ([])
        doneVertex = { }
        doneEdge   = { }
        
        for k,v in self.vertices.items() :
            newv = Vertex (v.nb, v.label, weightVertex)
            resGraph.vertices [k] = newv
            if v.nb in countVertexRight :
                ind = list(countVertexRight[v.nb].keys())[0]
                newv.pair = ( v, graph2.vertices[ ind ] )
                doneVertex[ ind ] = newv
                if newv.pair[0].label != newv.pair[1].label :
                    newv.label = "%s|%s" % (newv.pair[0].label, newv.pair[1].label)
            else :
                newv.pair = ( v, None )
                
        for k,v in graph2.vertices.items() :
            if k in doneVertex : continue
            newv = Vertex ("2a.%s" % v.nb, v.label, weightVertex)
            resGraph.vertices [newv.nb] = newv
            newv.pair = ( None, v )
                
        for k,e in self.edges.items() :
            newe = Edge (e.from_, e.to, e.label, weightEdge)
            resGraph.edges [k] = newe
            if e.nb in countEdgeRight :
                ind = list(countEdgeRight[e.nb].keys())[0]
                newe.pair = ( e, graph2.edges[ ind ] )
                doneEdge[ ind ] = newe
            else :
                newe.pair = ( e, None )
                
        for k,e in graph2.edges.items() :
            if k in doneEdge : continue
            from_ = list(countVertexLeft[e.from_].keys())[0] if e.from_ in countVertexLeft \
                            else "2a.%s" % e.from_ 
            to    = list(countVertexLeft[e.to].keys())[0] if e.to in countVertexLeft \
                            else "2a.%s" % e.to 
            if from_ not in resGraph.vertices : raise RuntimeError("should not happen " + from_)
            if to not in resGraph.vertices : raise RuntimeError("should not happen " + to)
            newe = Edge (from_, to, e.label, weightEdge)
            resGraph.edges [newe.nb] = newe
            newe.pair = ( None, e )
            
        resGraph.ComputePredecessor()
        resGraph.ComputeSuccessor()            
        
        allPaths = list(resGraph.EnumerateAllPaths(True))
        
        temp = [ sum ( [ 0 if None in _.pair else 1 for _ in p ] ) * 1.0 / len(p) \
                          for p in allPaths ]
        distance = 1.0 - 1.0 * sum(temp) / len(allPaths) 
            
        return distance,resGraph
        
    def DrawVerticesEdges(self) :
        vertices = []
        edges    = []
        for k,v in self.vertices.items() :
            if v.pair == (None, None) or (v.pair[0] != None and v.pair[1] != None) :
                vertices.append ( (k, v.label) )
            elif v.pair[1] == None :
                vertices.append ( (k, "-" + v.label, "red") )
            elif v.pair[0] == None :
                vertices.append ( (k, "+" + v.label, "green") )
            else : 
                raise Exception("?")
                
        for k,v in self.edges.items() :
            if v.pair == (None, None) or (v.pair[0] != None and v.pair[1] != None) :
                edges.append ( (v.from_, v.to, v.label) )
            elif v.pair[1] == None :
                edges.append ( (v.from_, v.to, "-" + v.label, "red") )
            elif v.pair[0] == None :
                edges.append ( (v.from_, v.to, "+" + v.label, "green") )
            else : 
                raise Exception("?")
                
        return vertices,edges
        
    
    def unittest_GraphDistance2 (self, debug = False) :
        graph1 = [ ("a","b"), ("b","c"), ("b","X"), ("X","c"), \
                   ("c","d"), ("d","e"), ("0","b") ]
        graph2 = [ ("a","b"), ("b","c"), ("b","X"), ("X","c"), \
                   ("c","t"), ("t","d"), ("d","e"), ("d","g") ]
        graph1 = Graph(graph1)
        graph2 = Graph(graph2)
        store = { }
        distance,graph = graph1.DistanceMatchingGraphsPaths(graph2, 
                            useMin = False, store = store)
        if distance == None : raise TypeError("expecting something different from None")
        allPaths = list(graph.EnumerateAllPaths(True))
        if len(allPaths) == 0 : raise ValueError("the number of paths should not be null")
        if distance == 0 : raise ValueError("expecting a distance > 0")
        vertices,edges = graph.DrawVerticesEdges()
        #GV.drawGraphEdgesVertices (vertices,edges, "unittest_GraphDistance2.png")
        node = graph.vertices["X"]
        if None in node.pair : 
            raise RuntimeError("unexpected, this node should be part of the common set")
        
        if False :
            print ("distance",distance)
            for k,v in store.items() :
                print (k, len(v))
                for _ in v :
                    print ("  ",_)
            
        vertices,edges = graph1.DrawVerticesEdges()
        #GV.drawGraphEdgesVertices (vertices,edges, "unittest_GraphDistance2_sub1.png")
        vertices,edges = graph2.DrawVerticesEdges()
        #GV.drawGraphEdgesVertices (vertices,edges, "unittest_GraphDistance2_sub2.png")
    
if __name__ == "__main__" :
    
    fold = os.path.split(__file__) [0]
    fold = os.path.join(fold, "temp_gaph")
    if not os.path.exists (fold) : os.mkdir (fold)
    
    GV = importme.import_module ("use_graphviz", whereTo = fold)
    
    outfile1 = os.path.join(fold, "unittest_GraphDistance4_sub1.png")
    outfile2 = os.path.join(fold, "unittest_GraphDistance4_sub2.png")
    outfilef = os.path.join(fold, "unittest_GraphDistance4_subf.png")
    for f in [ outfile1, outfile2, outfilef ] : 
        if os.path.exists (f) : os.remove (f)
    
    graph1 = [ ("a","b"), ("b","c"), ("b","d"), ("d","e"), \
               ("e","f"), ("b","f"), ("b","g"), ("f", "g"), 
               ("a","g"), ("a","g"), ("c","d"), ("d", "g"), 
               ("d","h"), ("aa","h"), ("aa","c"), ("f", "h"), ]
    graph2 = copy.deepcopy(graph1) + \
             [ ("h", "m"), ("m", "l"), ("l", "C"), ("C", "r"),
               ("a", "k"), ("k", "l"), ("k", "C"), 
               ]
               
    graph1 = Graph(graph1)
    graph2 = Graph(graph2)
    
    graph2["C"].label = "c"
    store = { }
    if len(list(graph1.EnumerateAllPaths(True))) != 17 : raise Exception("expecting 17 here")
    if len(list(graph2.EnumerateAllPaths(True))) != 19 : raise Exception("expecting 19 here")
    
    distance,graph = graph1.DistanceMatchingGraphsPaths(graph2, 
                    useMin = False, store = store)
    
    if graph["h"].Label() != "h":
        raise Exception("we expect this node to be merged in the process")
    
    if distance == None : raise Exception("expecting something different from None")
    vertices,edges = graph1.DrawVerticesEdges()
    GV.drawGraphEdgesVertices (vertices,edges, outfile1, tempFolder = fold, moduleImport = importme)
    assert os.path.exists (outfile1)

    vertices,edges = graph2.DrawVerticesEdges()
    GV.drawGraphEdgesVertices (vertices,edges, outfile2, tempFolder = fold, moduleImport = importme)
    assert os.path.exists (outfile2)

    vertices,edges = graph.DrawVerticesEdges()
    GV.drawGraphEdgesVertices (vertices,edges, outfilef, tempFolder = fold, moduleImport = importme)
    assert os.path.exists (outfilef)

File: optimisation.tex, line 774


def fonction (x, a,b,c) :
    return x [0]**4 + a * x[0]**3 + b * x[1]**2 + c * x [1]
def derivee (x, a,b,c) :
    return Num.array ( [4 * x[0]**3 + 3 * a * x[0]**2, b * 2 * x [1] + c] )

File: optimisation.tex, line 783


opt = optimisation_bfgs (fonction, derivee, (1,0.01,0.01))
x0  = Num.array ( [ 3, 4] )
x   = opt.optimise (x0)

algorithme BFGS

# coding: cp1252
import numpy as Num           # pour les tableaux
import psyco

class optimisation_bfgs (object) :
    """optimisation à l'aide de l'algorithme BFGS"""
    
    def __init__ (self, f, derivee, args = None, \
                    epsilon = 0.1, erreur = 1e-5, maxiter = 100) :
        """initialisation
        @param      f           fonction à minimiser --> f (x, args)
                                        où x est un vecteur (Numeric.array)
        @param      derivee     dérivée de f  --> derivee (x, args)
        @param      args        autres paramètres de la fonction
        @param      epsilon     coefficient devant le gradient
        @param      erreur      on s'arrête lorsque l'erreur ne décroît plus
        @param      maxiter     nombre d'itérations maximum
        """
        
        self._f          = f
        self._derivee    = derivee
        self._epsilon    = epsilon
        self._erreur     = erreur
        self._maxiter    = maxiter
        self._args       = args
        
    def erreur (self, x) :
        """calcule l'erreur"""
        return self._f (x, *self._args)
        
    def gradient (self, x) :
        """calcule le gradient"""
        return self._derivee (x, *self._args)
        
    def identite (self, dim) :
        """retourne la matrice identité"""
        b   = Num.array ( [ [ 0 for i in xrange (0, dim) ] for j in xrange (0,dim) ] )
        for i in xrange (0, dim) :
            b [(i,i)] = 1
        return b
        
    def optimise (self, xO, classic = False, pr = True) :
        """optimisation selon l'algorithme BFGS,
        x0 est le vecteur initiale, retourne la meilleure solution,
        si pr == True, affiche des résultats intermédiaires,
        classic == True, la matrice bt est mise à jour à chaque itération,
        équivaut à une descente de gradient du premier degré"""
        
        dim     = len (self.gradient (xO))
        stop    = 1e-12
        err     = self.erreur (xO)
        bt      = self.identite (dim)
        id      = True
        t       = 0
        iter    = 0
        old     = err * (1.0 + self._erreur * 2) * 2
        x       = xO
        gt_     = self.gradient (xO)
        xt_     = xO
        nbt     = 0
        
        while   (abs ((old - err) / err) > self._erreur or t == 0) and \
                 iter < self._maxiter :
            
            if pr : 
                print "itération ", iter, " (", \
                            t,nbt, ") \t erreur : ", err, " (", old, ")"
            iter    = iter + 1
            gt      = self.gradient (x)
            ct      = Num.dot (bt, gt)
            
            e   = abs (err) * 2 + 1
            eps = self._epsilon * 2
            while e > err and eps > stop :
                eps = eps / 2
                xt  = x - ct * eps
                e   = self.erreur (xt)
                
            if eps < 1e-12 and t > 0 :
                bt = self.identite (dim)
                if t == 0 : nbt += 1
                else : nbt = 0
                t  = 0
            else :
                old     = err
                x       = xt
                err     = e 
                if not classic :
                    gt      = self.gradient (x)
                    dt      = gt - gt_
                    gbtg    = Num.dot (Num.transpose (gt), Num.dot (bt, gt))
                    gbtd    = Num.dot (Num.transpose (gt), Num.dot (bt, dt))
                    if (gbtg <= 0 or gbtd <= 0) and nbt < 2 :
                        if t == 0 : nbt += 1
                        else : nbt = 0
                        bt = self.identite (dim)
                        t  = 0
                    else :
                        t       = t + 1
                        st      = xt - xt_
                        dtbtdt  = Num.dot (Num.transpose (dt), Num.dot (bt, dt))
                        dtst    = Num.dot (Num.transpose (dt), st)
                        stdt    = Num.dot (Num.transpose (st), dt)
                        stst    = Num.outer (st, st)
                        stdtbt  = Num.dot (Num.outer (st, dt), bt)
                        btdtst  = Num.dot (bt, Num.outer (dt, st))
                        c       = 1.0 + dtbtdt / dtst 
                        b       = stst * (c / stdt) 
                        b      -= (stdtbt + btdtst) / dtst
                        bt      = bt + b
                    
                gt_ = gt
                xt_ = x
        
        return x

if __name__ == "__main__" :
    psyco.full ()
    
    def fonction (x, a,b,c) :
        return x [0]**4 + a * x[0]**3 + b * x[1]**2 + c * x [1]
    def derivee (x, a,b,c) :
        return Num.array ( [4 * x[0]**3 + 3 * a * x[0]**2, b * 2 * x [1] + c] )
        
    opt = optimisation_bfgs (fonction, derivee, (1,0.01,0.01), \
                                    maxiter = 2000, epsilon = 0.2, erreur = 1e-10)
    x0  = Num.array ( [ 3, 4] )
    print "solution initiale : ", x0
    x   = opt.optimise (x0, classic = False)
    print "solution finale : ", x

File: optimisation.tex, line 797


x   = opt.optimise (x0, classic = False)

File: optimisation.tex, line 803


x   = opt.optimise (x0, classic = True)

simulation de tailles de poissons

# coding: cp1252
import random
import math

class poisson_loi (object) :
    """loi de distribution de la taille des poissons"""
    
    def __init__(self, alpha = 0.5, mm = 1, sm = 1, mf = 1, sf = 1) :
        """initialisation des paramètres de la loi"""
        self.alpha  = alpha 
        self.mm     = mm
        self.sm     = sm
        self.mf     = mf
        self.sf     = sf
        
    def init (self, l) :
        """initialisation de la classe avec une liste de variables"""
        m = 0 
        s = 0
        for x in l :
            m += x 
            s += x*x 
        m /= len (l)
        s /= len (l)
        s -= m*m
        self.alpha  = 0.5
        self.sm     = s / 2
        self.sf     = s / 2
        self.sm     = math.sqrt (self.sm)
        self.sf     = math.sqrt (self.sf)
        self.mm     = m + self.sm * 2
        self.mf     = m - self.sf * 2
        
    def __str__(self) :
        """affichage"""
        s = "classe poisson_loi\n"
        s += "alpha = " + str (self.alpha) + "\n"
        s += "moyenne male = " + str (self.mm) + "\n"
        s += "sigma male = " + str (self.sm) + "\n"
        s += "moyenne femelle = " + str (self.mf) + "\n"
        s += "sigma femelle = " + str (self.sf) + "\n"
        return s
        
    def simulation (self) :
        """simule une taille de poisson"""
        u = random.uniform (0,1)
        v = random.gauss (0,1)
        if u <= self.alpha :
            return v * self.sm + self.mm
        else :
            return v * self.sf + self.mf
            
    def generate (self,N) :
        """simule N tailles de poisson"""
        return [ self.simulation () for i in xrange (0,N) ]
        
    def trace_densite (self, autre = None) :
        """trace la courbe de la densité, 
        si autre != None, en trace une autre"""
        xa = min (self.mm, self.mf) - 3.0 * max (self.sm, self.sf)
        xb = max (self.mm, self.mf) + 3.0 * max (self.sm, self.sf)
        n  = 100
        x  = [ xa + (xb - xa) * i / n for i in xrange (0,n+1) ]
        y  = [ self.densite (xa + (xb - xa) * i / n) for i in xrange (0,n+1) ]
        import pylab as pl
        pl.plot ( x, y, "b" )
        if autre != None :
            xa = min (autre.mm, autre.mf) - 3.0 * max (autre.sm, autre.sf)
            xb = max (autre.mm, autre.mf) + 3.0 * max (autre.sm, autre.sf)
            n  = 100
            x  = [ xa + (xb - xa) * i / n for i in xrange (0,n+1) ]
            y  = [ autre.densite (xa + (xb - xa) * i / n) for i in xrange (0,n+1) ]
            pl.plot (x, y, "r")
            
        pl.title ("Distribution des tailles de poisson")
        pl.xlabel ("x")
        pl.ylabel ("y")
        
        pl.show()
        
    def densite (self, x) :
        """calcule de la densité au point x"""
        dpi = 1.0 / math.sqrt (math.pi * 2)
        xm = (x - self.mm) ** 2 / (2 * self.sm * self.sm)
        xm = math.exp (- xm)
        xf = (x - self.mf) ** 2 / (2 * self.sf * self.sf)
        xf = math.exp (- xf)
        return self.alpha * xm / self.sm + (1.0 - self.alpha) * xf / self.sf
        
    def log_densite (self, x) :
        """calcule de la log-densité au point x"""
        try :
            return math.log (self.densite (x))
        except :
            print "---------- erreur -------------------------------------------"
            print x
            return 0
        
    def log_densite_list (self, l) :
        """calcule la somme des log-densités au point x de l"""
        s = 0 
        for x in l :
            s += self.log_densite (x)
        s /= len (l)
        return s
        
    def gradient (self, x) :
        """calcul le gradient au point x, retourne un t-uple"""
        unpim   = 1.0 / (math.sqrt (2 * math.pi) * self.sm)
        unpif   = 1.0 / (math.sqrt (2 * math.pi) * self.sf)
        expm    = math.exp ( - ( x - self.mm)**2 / (2 * (self.sm**2)))
        expf    = math.exp ( - ( x - self.mf)**2 / (2 * (self.sf**2)))
        grada   = unpim * expm - unpif * expf
        gradmm  = (x - self.mm) / (self.sm** 2) * self.alpha * unpim * expm
        gradmf  = (x - self.mf) / (self.sf** 2) * (1.0 - self.alpha) * unpif * expf
        gradsm  = self.alpha * unpim * (x - self.mm) ** 2 / (self.sm ** 3) - \
                    self.alpha * unpim / self.sm
        gradsm *= expm
        gradsf  = (1.0 - self.alpha) * unpif * (x - self.mf) ** 2 / (self.sf ** 3) - \
                    self.alpha * unpif / self.sf
        gradsf *= expf
        f       = self.densite (x)
        return (grada / f, gradmm / f, gradsm / f, gradmf / f, gradsf / f)
        
    def gradient_total (self, l) :
        """calcul la somme des gradients pour tous les x de l"""
        g = [ 0.0 for i in range (0,5) ]
        for x in l :
            (a,b,c,d,e) = self.gradient (x)
            g [0] += a
            g [1] += b
            g [2] += c
            g [3] += d
            g [4] += e
        for i in range (0,len (g)) :
            g [i] /= len (l)
        return ( g [0], g [1], g [2], g [3], g [4] ) 
        
    def optimisation (self, l, epsilon = 0.001, erreur = 1e-5) :
        """recherche du maximum de la fonction f"""
        self.init (l)
        de   = self.log_densite_list (l)
        print "première densité : ", de
        dold = de / 2
        nb   = 0
        while abs (dold - de) / de > erreur :
            (a,b,c,d,e) = self.gradient_total (l)
            self.alpha      += epsilon * a
            self.mm         += epsilon * b
            self.sm         += epsilon * c
            self.mf         += epsilon * d
            self.sf         += epsilon * e
            dold = de
            de   = self.log_densite_list (l)
            nb  += 1
            print "itération ", nb, " densité ", de, " (", dold, ")  ", \
                    abs (dold - de) / de, " epsilon = ", epsilon
        

if __name__ == "__main__" :
    # création d'une instance de la classe        
    cl = poisson_loi (0.55, 0.40, 0.020, 0.35, 0.015)
    print cl                # affichage
    #cl.trace_densite ()     # courbe densité
    
    l = cl.generate (10000)
    cl2 = poisson_loi ()
    print "-----------------------------------------------------------"
    print "log densité maximale ", cl.log_densite_list (l)
    (a,b,c,d,e) = cl.gradient_total (l)
    print "gradient idéal ", (a,b,c,d,e)
    print "-----------------------------------------------------------"
    
    (a,b,c,d,e) = cl2.gradient_total (l)
    print "gradient avant", (a,b,c,d,e)
    cl2.optimisation (l)
    (a,b,c,d,e) = cl2.gradient_total (l)
    print "gradient après ", (a,b,c,d,e)
    print "-----------------------------------------------------------"
    print cl2
    cl2.trace_densite (cl)
    print "log vraisemblance  : ", cl2.log_densite_list (l)
    
    

File: optimisation.tex, line 924


import psyco
psyco.full ()

déterminer la taille des poissons

# coding: cp1252
import poisson
#import scipy.optimize.lbfgsb as Opt    # optimisation
import bfgs                      # optimisation
import numpy as Num           # pour les tableaux
import psyco

def fonction_bfgs (x, cl, l) :
    """fonction retournant l'opposé de la log-vraisemblance 
    de l'instance cl, fonction à minimiser"""
    cl.set (x)
    f = - cl.log_densite_list (l)
    #print f, "\t", x
    return f
    
def fonction_derivee_bfgs (x, cl, l) :
    """fonction retournant l'opposé de la log-vraisemblance 
    de l'instance cl, fonction à minimiser"""
    cl.set (x)
    f           = cl.gradient_total (l)
    return - Num.array (f)

class poisson_loi_bfgs (poisson.poisson_loi) :
    """loi de distribution de la taille des poissons,
    optimisation à l'aide de l'algorithme BFGS"""
    
    def __init__(self, alpha = 0.5, mm = 1, sm = 1, mf = 1, sf = 1) :
        """initialisation des paramètres de la loi"""
        poisson.poisson_loi.__init__(self, alpha, mm, sm, mf, sf)
        
    def set (self, x) :
        """initialisation avec un tableau"""
        self.alpha    = x [0]
        self.mm       = x [1]
        self.sm       = abs (x [2])
        self.mf       = x [3]
        self.sf       = abs (x [4])
        
    def get (self) :
        """retourne un tableau contenant les paramètres"""
        return Num.array ( (self.alpha, self.mm, self.sm, self.mf, self.sf) ) 
        
    def __str__(self) :
        """affichage"""
        s = "classe poisson_loi BFGS\n"
        s += "alpha = " + str (self.alpha) + "\n"
        s += "moyenne male = " + str (self.mm) + "\n"
        s += "sigma male = " + str (self.sm) + "\n"
        s += "moyenne femelle = " + str (self.mf) + "\n"
        s += "sigma femelle = " + str (self.sf) + "\n"
        return s
        
    def optimisation (self, l, epsilon = 0.001) :
        """recherche du maximum de la fonction f"""
        self.init (l)
        x0     = self.get ()
        print x0
        opt    = bfgs.optimisation_bfgs (fonction_bfgs, \
                                        fonction_derivee_bfgs, \
                                        args = (self, l))
        x = opt.optimise (x0)
        #x      = bfgs.Opt.fmin_l_bfgs_b ( fonction_bfgs, \
        #                             x0, \
        #                             fonction_derivee_bfgs, \
        #                             args = (self, l))
        self.set (x)
        print "optimisation terminée"
        print "valeur maximale : ", self.log_densite_list (l)
        print "message ", d


if __name__ == "__main__" :
    psyco.full ()
    # création d'une instance de la classe        
    cl = poisson.poisson_loi (0.55, 0.40, 0.020, 0.35, 0.015)
    print cl                # affichage
    #cl.trace_densite ()     # courbe densité
    
    l = cl.generate (10000)
    cl2 = poisson_loi_bfgs ()
    print "-----------------------------------------------------------"
    print "log densité maximale ", cl.log_densite_list (l)
    (a,b,c,d,e) = cl.gradient_total (l)
    print "gradient idéal ", (a,b,c,d,e)
    print "-----------------------------------------------------------"
    
    (a,b,c,d,e) = cl2.gradient_total (l)
    print "gradient avant", (a,b,c,d,e)
    cl2.optimisation (l)
    (a,b,c,d,e) = cl2.gradient_total (l)
    print "gradient après ", (a,b,c,d,e)
    print "-----------------------------------------------------------"
    print cl2
    cl2.trace_densite (cl)
    print "log vraisemblance  : ", cl2.log_densite_list (l)

optimisation en fonction d'une donnée aléatoire

import math

def factorielle(x):
     if x == 0: return 1
     else: return x * factorielle(x-1)
         
def profit (N,X,p,q,s) :
    if X <= N : return X * (q-p)
    else : return X * (s-p) + N * (q-s)

def proba_poisson (l, i) :
    return math.exp (-l) * (l ** i) / factorielle (i)
    
def esperance (X,p,q,s,l) :
    res = 0.0
    for i in range (0,l*2) :
        res += profit (float (i),X,p,q,s) * proba_poisson (l,i)
    return res
    
def maximum (p,q,s,l) :
    res = []
    for X in range (0, 2 * l) :
        r = esperance (X,p,q,s,l) 
        res.append ((X,r))
    return res
    
def find_maximum (res) :
    m = (0,0)
    for r in res :
        if r [1] > m [1] :
            m = r
    return m
    
if __name__ == "__main__" :
    res = maximum (2,5,1,80)
    m = find_maximum (res)
    print m    
    # dessin d'une courbe
    from pylab import *
    plot ( [ r [1] for r in res] )
    show ()

File: strategie_avec_alea.tex, line 149


def exponentielle (l) :
    u = random.random ()
    return - 1.0 / l * math.log (1.0 - u)
    
def poisson (l) :
    s = 0
    i = 0
    while s <= 1 :
        s += exponentielle (l)
        i += 1
    return i-1

File: strategie_avec_alea.tex, line 166


def histogramme_poisson (l, n = 1000) :
    h = [ 0.0 for i in range (0,4*l+1) ]
    for i in range (0, n) :
        x = poisson (l)
        if x < len (h) :
            h [x] += 1
    s = sum (h)
    for i in range (0, len (h)) :
        h [i] = float (h [i]) / s
    return h

h = histogramme_poisson (10)
from pylab import *
plot (h, "r")
plot ([ proba_poisson (10, i) for i in range (0, len (h))])
legend ( ["histogramme", u"densité" ] )
show ()

File: strategie_avec_alea.tex, line 198


def poisson_melange (params, coef) :
    s = 0
    for i in range (0, len (params)) :
        p = poisson (params [i])
        s += p * coef [i]
    return s

File: strategie_avec_alea.tex, line 210


def histogramme_poisson_melange (params, coef, n = 1000) :
    h = [ 0.0 for i in range (0, 4*sum(params)+1) ]
    for i in range (0, n) :
        x = poisson_melange (params, coef)
        if x < len (h) :
            h [x] += 1
    s = sum (h)
    for i in range (0, len (h)) :
        h [i] = float (h [i]) / s
    return h
    
h = histogramme_poisson_melange ([48,10,4], [1,2,3])
from pylab import *
plot (h, "r")
plot ([ proba_poisson (80, i) for i in range (0, len (h))])
legend ( [u"N1 + 2 N2 + 3 N3", u"Poisson (80)" ], "right") 
show ()

optimisation en fonction d'une donnée aléatoire selon un mélange de lois

# coding: cp1252
import math
import random
import psyco
psyco.full ()

proba_poisson_melange_tableau = []

def exponentielle (l) :
    u = random.random ()
    return - 1.0 / l * math.log (1.0 - u)
    
def poisson (l) :
    s = 0
    i = 0
    while s <= 1 :
        s += exponentielle (l)
        i += 1
    return i-1
    
def poisson_melange (params, coef) :
    s = 0
    for i in range (0, len (params)) :
        p = poisson (params [i])
        s += p * coef [i]
    return s
    
def histogramme_poisson_melange (params, coef, n = 100000) :
    h = [ 0.0 for i in range (0, 4*max(params)) ]
    for i in range (0, n) :
        x = poisson_melange (params, coef)
        if x < len (h) :
            h [x] += 1
    s = sum (h)
    for i in range (0, len (h)) :
        h [i] = float (h [i]) / s
    return h        

def profit (N,X,p,q,s) :
    if X <= N : return X * (q-p)
    else : return X * (s-p) + N * (q-s)
        
def proba_poisson_melange (params, coef, i) :
    global proba_poisson_melange_tableau
    if len (proba_poisson_melange_tableau) == 0 :
        proba_poisson_melange_tableau = histogramme_poisson_melange (params, coef)
    if i >= len (proba_poisson_melange_tableau) : return 0.0
    else : return proba_poisson_melange_tableau [i]
    
def esperance (X,p,q,s,params, coef) :
    res = 0.0
    for i in range (0,4*sum(params)) :
        res += profit (float (i),X,p,q,s) * proba_poisson_melange (params, coef,i)
    return res
    
def maximum (p,q,s,params, coef) :
    res = []
    for X in range (0, 4*sum (params)) :
        r = esperance (X,p,q,s,params, coef) 
        res.append ((X,r))
    return res
    
def find_maximum (res) :
    m = (0,0)
    for r in res :
        if r [1] > m [1] :
            m = r
    return m
    
if __name__ == "__main__" :
    res = maximum (2,5,1,[48,10,4], [1,2,3])
    m = find_maximum (res)
    print m    
    # dessin d'une courbe
    from pylab import *
    plot ( [ r [1] for r in res] )
    show ()

File: finance_autostrat.tex, line 490


date time         Open    High    Low     Close   Volume
07/11/2007 19:42  7822    7823    7818    7819.5  1130
07/11/2007 19:48  7819.5  7830    7819.5  7822.5  1543
07/11/2007 19:54  7823    7827.5  7819.5  7824    1244
07/11/2007 20:00  7824    7825.5  7822.5  7824.5   216      # 20.00
07/11/2007 20:24  7828    7833    7825.5  7830     640      # 20.24, il manque 3 périodes
07/11/2007 20:30  7829.5  7831.5  7827    7829.5   478
07/11/2007 20:36  7830    7830.5  7821    7829     716
07/11/2007 20:42  7829.5  7834.5  7826    7828     681

File: finance_autostrat.tex, line 860


Date      Open   High   Low    Close  Volume
20/03/08  56.01  56.75  55.26  55.84  2434000
19/03/08  57.53  57.95  56.40  56.77  2714400
18/03/08  58.85  58.99  57.13  57.61  3265900
14/03/08  60.27  60.78  59.00  59.53  2105500
13/03/08  59.01  60.47  59.00  60.15  2702700
12/03/08  60.84  60.85  59.35  60.02  2982400
11/03/08  61.12  61.56  60.00  60.47  2480900

graphe d'une série financière

#coding:latin-1
def GraphOHLC (title, dates, ohlc, file, size = (800,400), t1 = 0, t2 = -1) :
    """dessine une série financière avec matplotlib
    - title est une titre
    - dates est une liste de date
    - ohlc est une liste de dictionnaire avec les clés 
                      ("Open", "High", "Low", "Close", "Volume")
    - file est un nom de fichier, le graphe y sera sauvegardé
    - size est la taille désirée pour le graphique
    - t1 est l'indice de la première date du graphique
    - t2 est l'indice de la dernière date du graphique
    """
    
    # on coupe la série si besoin
    if t2 == -1 : t2 = len (dates)
    dates = dates [t1:t2]
    ohlc = ohlc [t1:t2]
    
    import pylab
    
    # on crée les labels pour les abscisses
    # sans afficher toutes les dates car elles deviennent illisibles sinon
    # on en affiche que 10
    ind  = pylab.arange (len (dates))
    lab  = ["" for i in ind]
    for i in range (0,len (dates),len(dates)/10) : lab [i] = dates [i]

    # on crée la figure
    fig  = pylab.figure (figsize=(size [0]/100, size [1]/100))
    ax   = fig.add_subplot(111)
    
    # la première série à tracer est celle des volumes sous forme d'histogramme
    for i in range (0, len (ohlc)) :
        oh = ohlc [i]
        
        # l'histogramme est vert si c'est un jour de hausse
        # rouge si c'est un jour de baisse
        if i == 0 : co = (0.5,0.5,0.5)
        elif ohlc [i]["Close"] > ohlc [i-1]["Close"] : co = (0.0,1.0,0.0)
        else : co = (1.0,0.0,0.0)
        if len (dates) > 300 : 
            pylab.plot ( [i, i], [0, oh ["Volume"]], "k", color = co)
        elif len (dates) > 100 : 
            pylab.plot ( [i, i], [0, oh ["Volume"]], "k", \
                                         linewidth = 2.0, color = co)
        else : 
            pylab.plot ( [i, i], [0, oh ["Volume"]], "k", \
                                          linewidth = 4.0, color = co)
        
    # on écrit la légende du volume
    v = [0.0 for i in ind]
    pylab.plot (ind, v, "c.")
    pylab.ylabel ("volume")
        
    # on construit un second axe au graphique pour la série des prix
    ymin, ymax = pylab.ylim()
    pylab.ylim (ymin, ymax*3)
    pylab.xticks (ind, lab, fontsize = "small", rotation = 13  )
    ax2 = pylab.twinx()
    
    # puis un dessine les prix sur le graphique selon le même schéma, 
    # la même série de points
    # (i-0.5, Open) (i,Open) (i,Low) (i,High) (i,Close) (i+0.5,Close)
    for i in range (0, len (dates)) :
        oh = ohlc [i]
        co = (0.0,0.0,1.0)
        pylab.plot ([i-0.5, i], [oh["Open"],  oh["Open"]],  "k", \
                                      linewidth = 1.0, color = co)
        pylab.plot ([i, i],     [oh["Low"],   oh["High"]],  "k", \
                                      linewidth = 1.0, color = co)
        pylab.plot ([i, i+0.5], [oh["Close"], oh["Close"]], "k", \
                                      linewidth = 1.0, color = co)

    # on termine par le titres, la légende du second axe et celles des abscisses
    pylab.title   (title)
    pylab.ylabel  ("euros")
    pylab.xticks  (ind, lab, fontsize = "small", rotation = 13)
    pylab.xlabel  ("dates")
    # il ne reste plus qu'à sauver la figure
    pylab.savefig (file, orientation='paysage')

simulation d'un pendule

#!/usr/bin/env pythonw2.3

# lignes utilisees pour matplotlib
import matplotlib
matplotlib.use("WXAgg")
import matplotlib.pylab as pylab
import numpy as N
import math


#############################################################################
# debut du programme
#############################################################################

def pendule_lineaire (tt, vt, at, gR, dt) :
	"""calcule t (t+1), v(t+1), a(t+1)
	t'' + gR t = 0"""
	at = - gR * tt
	vt += at * dt
	tt += vt * dt 
	return tt,vt,at

def pendule_non_lineaire (tt, vt, at, gR, dt) :
	"""calcule t (t+1), v(t+1), a(t+1)
	t'' + gR t = 0"""
	at = - gR * math.sin (tt)
	vt += at * dt
	tt += vt * dt 
	return tt,vt,at

def periode (courbe,dt) :
	"""estime la période d'une courbe dont on sait qu'elle est cyclique"""
	lp = []
	p = 0
	for i in range (1, len (courbe)-1) :
		if courbe [i-1] <= courbe [i] and courbe [i] >= courbe [i+1] :
			# maximum
			lp.append (i)
	# moyenne entre les durees entre deux maximas
	s = 0
	for l in range (1,len (lp)) :
		s += lp [l] - lp [l-1]
	return float (s) / (len (lp)-1) * dt
	
        
# initialisation : un angle t0 != 0, pas de vitesse, pas d'accélération
t0			= 1
tt,vt,at 	= t0,0,0
stt,svt,sat = t0,0,0
dt 			= 0.01
gR 			= 0.5
t 			= 0

T 			= []
th 			= []
sth 		= []
cth 		= []

# boucle
print "simultation"
for i in range (0,4000) :
        T.append (t)
        th.append (tt)
        sth.append (stt)
        ctt 		= t0 * math.cos (math.sqrt (gR) * t)
        cth.append (ctt)
        t 			= t + dt
        tt,vt,at 	= pendule_lineaire (tt, vt, at, gR, dt)
        stt,svt,sat = pendule_non_lineaire (stt, svt, sat, gR, dt)
        
print "periode theorique : ", math.pi * 2 / math.sqrt (gR)
print "periode courbe theorique ", periode (cth, dt)
print "periode courbe lineaire ", periode (th, dt)
print "periode courbe non lineaire ", periode (sth, dt)

# pour calculer l'angle a partir duquel la solution lineaire
# n'est plus viable, il faut calculer la difference entre les periodes
# et choisir un seuil au dela duquel la difference est trop grande
        
# affichage des premieres valeurs
print "premieres valeurs "
print "angle initial : ", t0 * 180 / math.pi
for i in range (0,10) :
        print T[i], " : ", th[i], "\t", cth [i], "\t", sth [i]


# matplotlib n'accepte que des donnees stockees dans un type de tableau
# definies dans le package Numeric
aT = N.array (T)
ath = N.array (th)
acth = N.array (cth)
asth = N.array (sth)

# dessin de la courbe
print "dessin de la courbe"
pylab.title("Oscillation d'un pendule")
pylab.xlabel("t")
pylab.ylabel("theta")
pylab.grid (True)
pylab.plot (aT, ath, linewidth=1.0, color = "blue")
pylab.plot (aT, acth, linewidth=1.0, color = "red")
pylab.plot (aT, asth, linewidth=1.0, color = "green")
pylab.show ()

simulation d'une corde en chute libre

# coding: cp1252
import pygame                 # pour les affichages
import math                   # pour les racines carrées


class point (object) :
    """définition d'un point : deux coordonnées et une masse"""
    __slots__ = "x","y","m"
    
    def __init__ (self, x,y,m) :
        """définit un point de la corde, de coordonnées (x,y)
        et de masse m"""
        self.x, self.y, self.m = float (x), float (y), float (m)
        
    def deplace (self, dep, dt) :
        """déplace un point"""
        self.x += dep [0] * dt
        self.y += dep [1] * dt
        
    def deplace_point (self, dep, dt) :
        """déplace un point"""
        self.x += dep.x * dt
        self.y += dep.y * dt
        
    def difference (self, p) :
        """retourne le vecteur qui relie deux points,
        retourne le couple de ses coordonnées"""
        return p.x - self.x, p.y - self.y
        
    def __str__ (self) :
        """afficher le point"""
        return "(x,y) = (%4.1f,%4.1f) masse %f" % (self.x,self.y,self.m)
        
class corde (object) :
    """définition d'une corde, une liste de points"""
    
    def __init__(self, nb, p1, p2, m, k, g, f, l) :
        """initialisation d'une corde
        @param          nb          nombre de points
        @param          p1 = x1,y1  coordoonnées du premier point (fixe)
        @param          p2 = x2,y2  coordoonnées du dernier point (fixe)
        @param          m           masse de la corde, 
                                    répartie entre tous les pointstous les points
        @param          k           raideur de l'élastique
        @param          g           intensité de l'apesanteur, 
                                    valeur positive
        @param          f           vitesse de freinage
        @param          l           longueur de la corde"""
        x1,y1           = p1[0], p1[1]
        x2,y2           = p2[0], p2[1]
        self.list       = []
        self.vitesse    = []
        for i in range (0,nb) :
            x = x1 + float (i) * (x2 - x1) / float (nb - 1)
            y = y1 + float (i) * (y2 - y1) / float (nb - 1)
            self.list.append ( point (x,y, float (m) / nb))
            self.vitesse.append (point (0,0,0))
        self.k = k * nb
        self.g = g
        self.l = float (l) / (nb-1)
        self.f = f
            
    def display (self, screen) :
        """affichage de la corde à l'aide du module pyagame"""
        self.display_courbe_theorique (screen)
        x,y     = screen.get_size ()
        color   = (0,0,0)
        for p in self.list :
            pygame.draw.circle (screen, color, (int (p.x), int (y - p.y)), int (p.m+1))
        for i in xrange (0,len (self.list)-1) :
            pygame.draw.line (screen, color, \
                            (int (self.list [i].x),      int (y - self.list [i].y)), \
                            (int (self.list [i+1].x),    int (y - self.list [i+1].y))) 
                            
    def display_courbe_theorique (self, screen) :
        
        def cosh (x) :
            """retourne le cosinus hyperbolique de x"""
            return math.cosh (x)
        
        def sinh (x) :
            """retourne le sinus hyperbolique de x"""
            return math.sinh (x)
            
        def asinh (x) :
            """retourne la réciproque du sinus hyperbolique de x"""
            t = x + math.sqrt (x*x + 1)
            return math.log (t)
        
        def acosh (x) :
            """retourne la réciproque du cosinus hyperbolique de x"""
            t = abs (x) + math.sqrt (x*x - 1)
            return math.log (t)
            
        def trouve_alpha (x2, L) :
            """détermine la valeur de alpha une seule fois"""
            if self.__dict__.has_key ("alpha") : return self.alpha
                
            def fonction (a,x2,L) :
                if a == 0.0 : return 0.0
                else : return 1.0 / a * sinh (a * x2) - L / 2

            a1      = 1.0 / x2
            a2      = 1.0 / x2
            m       = 1.0 / x2
            diff    = fonction (m, x2, L)
            while abs (diff) > 1e-3 :
                if diff > 0 : # faire décroître alpha
                    if fonction (a1, x2, L) > 0 : a1 /= 2.0
                    else : a2 = m
                else :
                    if fonction (a2, x2, L) < 0 : a2 *= 2.0
                    else : a1 = m
                m       = (a1 + a2) / 2
                diff    = fonction (m, x2, L)
            self.alpha = m
            return m
        
        p1 = self.list [0]
        p2 = self.list [ len (self.list) - 1 ]
        if p1.y != p2.y : return None # cas non prévu
        # on trace la courbe y = cosh (alpha x)
        L       = self.l * (len (self.list) - 1)
        mx      = (p1.x + p2.x) / 2
        x1      = p1.x - mx
        x2      = p2.x - mx
        alpha   = trouve_alpha (x2, L) # est solution de 1/alpha sinh (alpha x1) = L/2
        C       = - 1.0 / alpha * cosh (alpha * x2) 

        sx,sy   = screen.get_size ()
        color   = (0,0,255)
        
        ix1     = int (x1)
        ix2     = int (x2)
        x0,y0   = p1.x,p1.y
        for i in xrange (ix1, ix2+1) :
            x   = int (mx + i)
            y   = 1.0 / alpha * cosh (alpha * float (i)) + C + p1.y
            if 0 < y < sy and 0 < y0 < sy :
                pygame.draw.line (screen, color, (x0,sy-y0), (x, sy-y), 2)
            x0,y0 = x,y
        

    def force_point (self, i) :
        """calcule les forces qui s'exerce en un point, 
        retourne un couple x,y"""
        x,y = 0,0
        # poids
        y -= self.g * self.list [i].m
        # voisin de gauche
        dx, dy = self.list [i].difference (self.list [i-1])
        d = math.sqrt (dx *dx + dy *dy)
        if d > self.l :
            dx = (d - self.l) / d * dx
            dy = (d - self.l) / d * dy
            x += self.k * dx
            y += self.k * dy
        # voisin de droite
        dx, dy = self.list [i].difference (self.list [i+1])
        d = math.sqrt (dx *dx + dy *dy)
        if d > self.l :
            dx = (d - self.l) / d * dx
            dy = (d - self.l) / d * dy
            x += self.k * dx
            y += self.k * dy
        # freinage
        x += - self.f * self.vitesse [i].x
        y += - self.f * self.vitesse [i].y
            
        return x,y    
        
    def iteration (self, dt) :
        """calcule les déplacements de chaque point et les met à jour,
        on ne déplace pas les points situés aux extrémités,
        retourne la somme des vitesses et des accélérations au carré"""
        force = [ (0,0) ]
        for i in xrange (1, len (self.list)-1) :
            x,y = self.force_point (i)
            force.append ((x,y))
        force.append ((0,0))
        
        # déplacement
        for i in xrange (1, len (self.list)-1) :
            self.vitesse [i].deplace ( force [i], dt )
            self.list [i].deplace_point ( self.vitesse [i], dt ) 
            
        d = 0
        for f in force :
            d += self.vitesse [i].x ** 2 + force [i][0] **2
            d += self.vitesse [i].y ** 2 + force [i][1] **2
            
        return d
        
    def __str__ (self):
        """affiche chaque point de la corde"""
        s = ""
        l = 0
        for i in xrange (0, len (self.list)) :
            s +=  "point " + str (i) + " : " + str (self.list [i]) 
            if i < len (self.list) -1 :
                x,y     = self.list [i].difference (self.list [i+1])
                d       = math.sqrt (x*x + y*y)
                s += "\t segment : %4.0f" % d 
                s += " ( %4.0f )" % self.l
            if i != 0 and i != len (self.list)-1 : 
                x,y = self.force_point (i)
                s += "\t force en ce point (%f,%f) " % (x,y) 
            s += "\n"
            if i > 0 : 
                x,y = self.list [i].difference (self.list [i-1])
                l += math.sqrt (x*x + y*y)
        s += "longueur de la corde " + str (l) + "\n"
        s += "longueur attendue " + str ((len (self.list)-1) * self.l) + "\n"
        return s

def attendre_clic (screen,x,y):
    """dessine un rectangle rouge sur l'écran et 
    attend la pression d'un clic de souris"""
    color   = 255,0,0
    pygame.draw.line (screen, color, (10,10), (x-10,10), 2)
    pygame.draw.line (screen, color, (x-10,10), (x-10,y-10), 2)
    pygame.draw.line (screen, color, (x-10,y-10), (10,y-10), 2)
    pygame.draw.line (screen, color, (10,y-10), (10,10), 2)
    pygame.display.flip ()
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break

if __name__ == "__main__" :
    
    pygame.init ()
    size      = width, height = x,y = 800, 500
    black     = 0, 0, 0
    white     = 255,255,255
    screen    = pygame.display.set_mode(size)
    nb        = 10
    c         = corde (nb, (100,450), (700,450), 100, 1, 0.1, 0.05, 800)
    dt        = 0.1
    print "corde initial"
    print c
    
    iter      = 0
    dep       = len (c.list) * (x*x + y*y)
    while True and dep > 1e-6 :

        for event in pygame.event.get():
            if event.type == pygame.QUIT: sys.exit()
            if event.type == pygame.MOUSEBUTTONUP:
                print c
                attendre_clic (screen,x,y)
    
        if iter % 10 == 0 :
            screen.fill (white)
            c.display (screen)
            pygame.display.flip ()

        iter += 1
    
        if iter == 1: attendre_clic (screen,x,y)
            
        dep = c.iteration (dt)
        #print "dep =", dep
        
        pygame.display.flip ()
    
    print c
    attendre_clic (screen,x,y)

filtrage d'un signal sonore

import pygame
import pygame.mixer
import pygame.sndarray
import FFT
import math
import numpy as Numeric
import string
import copy
import pylab
import numpy

pygame.mixer.init ()
pygame.init ()


fourier = None
indice = None

def get_sound ():
    """charge le son sound010.wav"""
    s = pygame.mixer.Sound ("sound010.wav")
    t = pygame.sndarray.array (s)
    return s
    
def play_sound(s):
    """joue un son"""
    s.play ()

def convert_array(t, s):
    """joue un son decrit dans un tableau a une dimension"""
    
    s = pygame.sndarray.array (s)
    for i in range (0, len (s)) :
        s [i]= t [i]
    #tt = Numeric.array ([ [x, x] for x in t] )
    #print tt [0:10]
    s = pygame.sndarray.make_sound (s)
    return s
    
def array_sound(s):
    """convertit un son en un tableau d'entiers"""
    a = pygame.sndarray.array(s)
    t = Numeric.array([i for i in xrange(0,len(a))])
    for i in xrange(0,len(a)): t [i] = a [i][0]
    return t

def dessine_son(mem,t,fourier,ind,a,b):
    """dessine une partie du son, limite la taille a 512"""
    m = len (mem)
    if m > 256 : m = 256
    x  = [ i for i in xrange (ind,ind+m) ] 
    y1 = [ mem[i] for i in xrange (ind,ind+m) ] 
    y2 = [ t[i] for i in xrange (ind,ind+m) ] 
    pylab.figure (1)
    p1 = pylab.plot (x,y1)
    p2 = pylab.plot (x,y2)
    pylab.title ("Fourier")
    pylab.xlabel ("frequence")
    pylab.ylabel ("amplitude")
    pylab.legend ( ("son", "son + filtre"))

    m = len (fourier)
    if m > 256 : m = 256
    #x  = [ i for i in xrange (0,m) ] 
    pylab.figure (2)
    x  = [ i for i in xrange (0,m) ] 
    y1 = [ abs(fourier[i]) for i in xrange (0,m) ] 
    y2 = []
    for i in x :
        if a <= i <= b : y2.append (450000.0)
        else : y2.append (0.0)
    p3 = pylab.plot (x,y1)
    p4 = pylab.plot (x,y2)
    pylab.legend ( ("fourrier", "filtre"))
    pylab.show()

def filtre_son_extrait(t,a,b):
    """calcul de la transformee de Fourier, application du filtre [a,b],
    recomposition du signal"""
    fft = FFT.fft (t)
    global fourier             
    if fourier == None and indice != None : fourier = copy.copy(fft)
    for i in xrange(0,len(t)):
        if a <= i <= b:
            pass
        else:
            fft [i] = complex(0,0)
    tt = FFT.inverse_fft(fft)
    for i in xrange(0,len(t)):
        t [i] = int(tt [i].real)
       

def filtre_son(t,a,b,div = 256):
    """filtre un son par tranche de div frequences, ne garde que les
    frequences comprises entre a et b"""
    global indice
    nb = len (t) / div
    for i in xrange (0,nb):
        if i == nb / 2 : indice = i * div
        ext = t [i * div : (i+1) * div]
        filtre_son_extrait (ext,a,b)

def essai():
    print "chargement du son"        
    s = get_sound ()
    print "duree : ", s.get_length (), " secondes"
    print "musique"
    play_sound (s)
    pygame.time.delay (6000)
    t = array_sound (s)
    mem = copy.copy(t)
    print "nombre de donnees ", len (t)
    print "duree d'une donnee ", s.get_length () * 1000 / len (t), "millisecondes"


    rep = ""
    if rep != "n" :
        #rep = string.split (rep, ",")
        #a = int (rep [0])
        #b = int (rep [1])
        a,b = 10,100

        print "filtrage [%d,%d]" % (a,b)
        filtre_son (t,a,b)

        print "dessin des premiers instants, son filtre"
        dessine_son (mem,t,fourier,indice, a,b)

        print "son filtre"
        s = convert_array (t, s)
        play_sound (s)
        
        pygame.time.delay (6000)

essai ()

image de synthèse, base

# coding: cp1252
"""définition des objets permettant de construire une image de synthèse"""
import math
import copy

class vecteur (object) :
    """définit ce qu'est un point"""
    __slots__ = "x","y","z"
    
    def __str__ (self):
        """pour l'affichage"""
        return "(%3.2f,%3.2f,%3.2f)" % (self.x, self.y, self.z)
    
    def __init__(self,x,y,z):
        """initialisation"""
        self.x, self.y, self.z = float (x), float (y), float (z)
    
    def __add__ (self,p):
        """addition de deux points"""
        return vecteur (self.x + p.x, self.y + p.y, self.z + p.z)
        
    def __neg__ (self):
        """retourne l'opposé d'un vecteur"""
        return vecteur (-self.x,-self.y,-self.z)

    def __iadd__ (self,p):
        """addition de deux points"""
        self.x += p.x
        self.y += p.y
        self.z += p.z
        return self

    def __sub__ (self,p):
        """soustraction de deux points"""
        return vecteur (self.x - p.x, self.y - p.y, self.z - p.z)

    def __isub__ (self,p):
        """soustraction de deux points"""
        self.x -= p.x
        self.y -= p.y
        self.z -= p.z
        return self
        
    def __mul__ (self,x):
        """multiplication par un scalaire"""
        return vecteur (self.x * x, self.y * x, self.z * x)

    def __imul__ (self,x):
        """multiplication par un scalaire"""
        self.x *= x
        self.y *= x
        self.z *= x
        return self
        
    def __div__ (self,x):
        """division par un scalaire"""
        return vecteur (self.x / x, self.y / x, self.z / x)

    def __idiv__ (self,x):
        """division par un scalaire"""
        self.x /= x
        self.y /= x
        self.z /= x
        return self
        
    def norme2 (self) :
        """retourne la norme du vecteur au carrée"""
        return self.x * self.x + self.y * self.y + self.z * self.z
        
    def scalaire (self, v) :
        """calcule le produit scalaire entre self et v"""
        return self.x * v.x + self.y * v.y + self.z * v.z
        
    def vectoriel (self, v) :
        """calcule le produit vectoriel entre self et v"""
        res   = vecteur (0,0,0)
        res.x = self.y * v.z - self.z * v.y
        res.y = self.z * v.x - self.x * v.z
        res.z = self.x * v.y - self.y * v.x
        return res
        
    def norme (self) :
        """retourne la norme du vecteur"""
        return math.sqrt (self.norme2 ())
        
    def renorme (self) :
        """renorme ce vecteur"""
        n = self.norme ()
        if n > 0 : return self / n
        else : return copy.copy (self)
            
    def cosinus (self, v) :
        """retourne le cosinus de entre le vecteur self et le vecteur r"""
        sc = self.scalaire (v)
        n1 = self.norme ()
        n2 = v.norme ()
        n  = n1 * n2
        if n == 0 : return 0
        return float (sc) / float (n)
        
    def sinus (self, v, norm) :
        """retourne le sinus de entre le vecteur self et le vecteur r, 
        norm est un vecteur normal et de norme 1 permettant d'orienter
        le plan dans lequel se trouve les deux vecteurs dont il faut mesurer le sinus"""
        sc = self.vectoriel (v)
        n1 = self.norme ()
        n2 = v.norme ()
        n  = n1 * n2
        if n == 0 : return 0
        return sc.scalaire (norm) / float (n)
        
    def angle (self, v, norm) :
        """retourne l'angle entre les vecteur self et v,
        retourne un angle compris entre -pi et pi,
        norm est la direction du vecteur normal au plan des deux vecteurs"""
        cos     = self.cosinus (v)
        sin     = self.sinus (v, norm)
        angle   = math.atan2 (sin, cos)
        if angle > math.pi : angle -= math.pi * 2
        return angle
        
    def diff_abs (self, v):
        """retourne la somme des valeurs absolues des différentes entre coordonnées"""
        r  = abs (self.x - v.x)
        r += abs (self.y - v.y)
        r += abs (self.z - v.z)
        return r
        
    def __eq__ (self, v) :
        """définit l'égalité entre deux vecteurs"""
        if v == None : return False
        return self.diff_abs (v) < 1e-10
           
    def __ne__ (self, v) :
        """définit l'égalité entre deux vecteurs"""
        if v == None : return True
        return self.diff_abs (v) > 1e-10


class couleur (vecteur) :
    """une couleur est un vecteur dont les coordonnées sont comprises entre 0 et 1, 
    x <--> rouge, y <--> vert, z <--> bleu"""
    
    def __init__ (self, x,y,z) :
        vecteur.__init__(self, x,y,z)
        self.borne ()
            
    def borne (self) :
        """si une couleur est hors bornes, réajuste la couleur, prend le maximum devient 1,
        les autres intensités sont ajustées selon ce facteur d'échelle"""
        if self.x < 0 : self.x = 0
        if self.y < 0 : self.y = 0
        if self.z < 0 : self.z = 0
        m = max (self.x, self.y)
        m = max (m, self.z)
        if m > 1 :
            self.x /= m
            self.y /= m
            self.z /= m
        
    def __add__ (self,p):
        """addition de deux couleurs"""
        return couleur (self.x + p.x, self.y + p.y, self.z + p.z)

    def produit_terme (self, v) :
        """effectue un produit terme à terme"""
        return couleur (self.x * v.x, self.y * v.y, self.z * v.z)

    def __mul__ (self,x):
        """multiplication par un scalaire"""
        return couleur (self.x * x, self.y * x, self.z * x)
        


class repere (object) :
    """définition d'un repère orthonormé"""
    
    def __init__ (self,   origine = vecteur (0,0,0), \
                            axex    = vecteur (1,0,0), \
                            axey    = vecteur (0,1,0), \
                            axez    = vecteur (0,0,1)) :
        """initialisation, origine et les trois axes"""
        self.origine    = origine
        self.x          = axex
        self.y          = axey
        self.z          = axez
        
    def coordonnees (self, v) :
        """on suppose que les coordonnées de v sont exprimées dans ce repère,
        calcule les coordonnées de v dans le repère d'origine"""
        res      = copy.copy (self.origine)
        res.x  += v.x * self.x.x +  v.y * self.y.x + v.z * self.z.x
        res.y  += v.x * self.x.y +  v.y * self.y.y + v.z * self.z.y
        res.z  += v.x * self.x.z +  v.y * self.y.z + v.z * self.z.z
        return res
        
    def __str__ (self):
        """affichage"""
        s  = "origine : " + str (self.origine) + "\n"
        s += "axe des x : " + str (self.x) + "\n"
        s += "axe des y : " + str (self.y) + "\n"
        s += "axe des z : " + str (self.z) + "\n"
        return s
        
class pixel (object) :
    """définit ce qu'est un pixel"""
    __slots__ = "x","y"
        
    def __init__(self,x,y):
        """initialisation"""
        self.x, self.y = int (x), int (y)
    
    def __str__ (self):
        """pour l'affichage"""
        return "(%d, %d)" % (self.x, self.y)
        
        
        
        
class rayon (object) :
    """définit ce qu'est un rayon"""
    __slots__ = "origine", "direction", "pixel", "couleur"
    
    def __init__ (self, origine, direction, pixel, couleur):
        """initialisation"""
        self.origine, self.direction, self.pixel, self.couleur = \
                origine, direction, pixel, couleur
        
    def __str__ (self):
        """pour l'affichage"""
        s  = "origine   : "     + str (self.origine)
        s += " direction : "    + str (self.direction)
        s += " pixel : "        + str (self.pixel)
        s += " couleur : "      + str (self.couleur)
        return s
    

class objet (object):
    """définit l'interface pour un objet à dessiner dans une image de synthese"""

    def intersection (self, r) :
        """retourne le point d'intersection avec le rayon r, 
        retourne None s'il n'y pas d'intersection"""
        return None
        
    def normale (self, p, rayon) :
        """retourne la normale au point de coordonnée p, et connaissant le rayon"""
        return None
        
    def couleur_point (self, p) :
        """retourne la couleur au point de coordonnée p"""
        return None
    
    def rayon_refracte (self, rayon, p) :
        """retourne le rayon réfracté au point p de la surface,
        si aucune, retourne None"""
        return None
        
    def rayon_reflechi (self, rayon, p) :
        """retourne le rayon réfléchi au point p de la surface,
        si aucune, retourne None"""
        return None
        
    def phong_coefficient (self):
        """retourne un coefficient propre à l'objet pour
        le modèle d'illumination de Phong"""
        return float (0)
        
        
        
class source (object) :
    """définition d'une source ponctuelle"""
    __slots__ = "origine", "couleur"

    def __init__ (self, origine, couleur):
        """initialisation"""
        self.origine, self.couleur = origine, couleur
        
    def __str__ (self) :
        """affichage"""
        return "source : " + str (self.origine) + " couleur : " + str (self.couleur)
        
if __name__ == "__main__" :
    v = vecteur (0,1,2)
    u = vecteur (0,1,2)
    w = u + v
    print (u,v,w)
    print (w * 6)
    p = pixel (5,5)
    print (p)
    c = couleur (1,1,1) 
    print (c)
    r = rayon (u,w,p,c)
    print (r)
    s = source (v, c)
    print (s)


image de synthèse, sphère

# coding: cp1252
"""définition d'une sphère"""
import image_synthese_base as base
import math

class sphere (base.objet):
    """définit une sphère"""
    __slots__ = "centre", "rayon", "couleur"
    
    def __init__ (self, centre, rayon, couleur):
        """initialisation"""
        self.centre, self.rayon, self.couleur = centre, float (rayon), couleur

    def intersection (self, r) :
        """retourne le point d'intersection avec le rayon r, 
        retourne None s'il n'y pas d'intersection"""
        oc      = self.centre - r.origine
        vn      = r.direction.norme2 ()
        s       = r.direction.scalaire (oc)
        delta   = s*s - vn * (oc.norme2 () - self.rayon * self.rayon)
        if delta < 0 : return None
        delta   = math.sqrt (delta)
        l1      = (s - delta) / vn
        l2      = (s + delta) / vn
        
        if      0 < l1 < l2 :   l = l1
        elif    l1 < 0 < l2 :   l = l2
        elif    0 < l2 < l1 :   l = l2
        elif    l2 < 0 < l1 :   l = l1
        else :                  l = None

        if l == None : return None

        v = r.origine + r.direction * l
        return v
        
    def normale (self, p, rayon) :
        """retourne la normale au point de coordonnée p"""
        v = (p - self.centre) / self.rayon
        return v     
        
    def couleur_point (self, p) :
        """retourne la couleur au point de coordonnée p"""
        return self.couleur
        
    def __str__ (self):
        """affichage"""
        s  = "sphère --- centre : " + str (self.centre)
        s += " rayon : " + str (self.rayon)
        s += " couleur : " + str (self.couleur)
        return s
        
        
        
if __name__ == "__main__" :
    s = sphere (base.vecteur (0,0,0), 5, base.couleur (0,1,0))
    r = base.rayon (    base.vecteur (10,0,0), base.vecteur (1,0,0), \
                        base.pixel (0,0), base.couleur (0,0,0))
    print (s)
    print (r)
    p = s.intersection (r)
    print (p)
    


image de synthèse, scène

# coding: cp1252
"""définition d'une scène"""
import image_synthese_base as base
import image_synthese_sphere as obj
import math
import pygame

class scene (object):
    """définit une scène, les axes x,y sont ceux de l'écran, 
    z-1 est la distance à l'écran du point (x,y,z)"""
    
    def __init__ (self, repere, alpha, x,y) :
        """définit la position de l'oeil, l'angle d'ouverture,
        et la taille de l'écran"""
        self.repere = repere
        self.alpha  = float (alpha)
        self.dim    = (int (x), int (y))
        
    def ajoute_source (self, source):
        """ajoute une source ponctuelle de lumière"""
        if "sources" not in self.__dict__: 
            self.sources = []
        self.sources.append (source)
        
    def ajoute_objet (self, objet):
        """ajoute un objet à la scène"""
        if "objets" not in self.__dict__: 
            self.objets = []
        self.objets.append (objet)
        
    def __str__ (self) :
        """affichage"""
        s  = "scène ----------------------------\n"
        s += "repère : " + str (self.repere) + "\n"
        s += "angle d'ouverture : " + str (self.alpha) + "\n"
        s += "dimension de l'écran : " + str (self.dim) + "\n"
        if "sources" in self.__dict__:
            for a in self.sources : s += "   " +str (a) + "\n"
        if "objets" in self.__dict__:
            for a in self.objets :  s += "   " + str (a) + "\n"
        return s
        
    def intersection (self, rayon) : 
        """calcule le point d'intersection entre un rayon et le plus proche des objets,
        retourne l'objet et le point d'intersection"""
        if "objets" not in self.__dict__: return None, None
        p       = rayon.origine
        sp,so   = None, None
        for o in self.objets :
            i = o.intersection (rayon)
            if i == None : continue
            if rayon.direction.scalaire (i - p) <= 0 : continue 
            if i == rayon.origine : continue 
            if sp == None : 
                sp  = i
                so  = o
            else :
                v = i - p
                d = sp - p
                if v.norme2 () < d.norme2 () :
                    sp = i
                    so = o
        return so, sp                
                
    def sources_atteintes (self, p) : 
        """retourne la liste des sources atteintes depuis une position p de l'espace,
        vérifie qu'aucun objet ne fait obstacle"""
        res = []
        for s in self.sources:
            r   = base.rayon (s.origine, p - s.origine, base.pixel (0,0), s.couleur)
            o,i = self.intersection (r)
            if i == None : continue
            if (i - p).norme2 () < 1e-10 :   # possible problème d'arrondi
                res.append (s)
                continue
        return res
                        
    def construit_rayon (self, pixel) :
        """construit le rayon correspondant au pixel pixel"""
        x = (pixel.x - self.dim [0] / 2) * math.tan (self.alpha / 2) / min (self.dim)
        y = (pixel.y - self.dim [1] / 2) * math.tan (self.alpha / 2) / min (self.dim)
        v = base.vecteur (x,y,1)
        r = base.rayon (self.repere.origine, self.repere.coordonnees (v), \
                            pixel, base.couleur (1,1,1))
        return r
        
    def modele_illumination (self, rayon, p, obj, source) :
        """calcule la couleur pour un rayon donné, un point p, un objet obj, 
        et une source de lumière source"""
        n   = obj.normale (p, rayon)
        cos = n.cosinus (source.origine - p)
        cl  = obj.couleur_point (p) * cos
        cl  = cl.produit_terme (rayon.couleur)
        return cl
        
    def couleur_fond (self) :
        """retourne la couleur du fond"""
        return base.couleur (0,0,0)
        
    def rayon_couleur (self, rayon, ref = True) :
        """retourne la couleur d'un rayon connaissant les objets,
        cette fonction doit être surchargée pour chaque modèle d'illumination, 
        si ref == True, on tient compte des rayons réfracté et réfléchi"""
        
        list_rayon = [ rayon ]
        c = base.couleur (0,0,0)
        b = False
        while len (list_rayon) > 0 :
            r   = list_rayon.pop ()
            o,p = self.intersection (r)

            if p == None : continue
                
            if ref :
                t   = o.rayon_refracte (r, p)
                if t != None : list_rayon.append (t)
                t   = o.rayon_reflechi (r, p)
                if t != None : list_rayon.append (t)
                
            sources = self.sources_atteintes (p)
            if len (sources) == 0 : return base.couleur (0,0,0)
            for s in sources :
                cl  = self.modele_illumination (r, p, o, s)
                c  += cl
                b   = True

        if not b : c = self.couleur_fond ()
        else : c.borne ()
        return c        
        
    def construit_image (self, screen):
        """construit l'image de synthèse où screen est un objet du module pygame"""
        count   = 0
        nbpixel = int (self.dim [0] * self.dim [1] / 100)
        for y in range (0, self.dim [1]) :
            for x in range (0, self.dim [0]) :
                p = base.pixel (x,y)
                r = self.construit_rayon (p)
                c = self.rayon_couleur (r, True)
                q = (p.x,self.dim [1] - p.y - 1) 
                d = (int (c.x * 255), int (c.y * 255), int (c.z * 255))
                pygame.draw.line (screen, d, q,q)
                count += 1
                if count % 150 == 0 : pygame.display.flip ()
                if count % nbpixel == 0 : print ("avancement " , count // nbpixel , "%")
        pygame.display.flip ()


def attendre_clic ():
    """dessine une croix sur l'écran et attend la pression d'un clic de souris"""
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break


if __name__ == "__main__" :
    s = scene (base.repere (), math.pi / 1.5, 400, 300)
    s.ajoute_source ( base.source (base.vecteur (0,10,10), \
                        base.couleur (1,1,1) ) )
    s.ajoute_source ( base.source (base.vecteur (10,10,5), \
                        base.couleur (0.5,0.5,0.5) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,0,12), \
                        3, base.couleur (1,0,0) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,-400,12), \
                        396, base.couleur (0.5,0.5,0.5) ) )
    print (s)
    
    screen  = pygame.display.set_mode (s.dim)
    screen.fill ((255,255,255))
    s.construit_image (screen)

    print ("image terminée")
    attendre_clic ()


image de synthèse, complet

# coding: cp1252
"""implémentation du modèle d'illumination de Phong"""
import image_synthese_scene as scene
import image_synthese_base as base
import image_synthese_sphere as obj
import math
import pygame


class scene_phong (scene.scene):
    """définit une scène et utilise le modèle d'illumination de Phong
    pour construire l'image de synthèse"""
    
    def __init__ (self, repere, alpha, x,y,
                    ka          = 0.1,
                    kb          = 0.8,
                    kc          = 0.3,
                    reflet      = 6,
                    fond        = base.couleur (200,200,200)) :
        """définit la position de l'oeil, l'angle d'ouverture,
        et la taille de l'écran"""
        scene.scene.__init__ (self, repere, alpha, x, y)
        self.ka, self.kb, self.kc   = ka,kb,kc
        self.reflet                 = reflet
        self.fond                   = fond
        self.constante              = float (1)
        
    def __str__ (self) :
        """affichage"""
        s  = scene.scene.__str__ (self)
        s += "ka = %1.3f   kb = %1.3f   kc = %1.3f\n" % (self.ka,self.kb,self.kc)
        s += "reflet " + str (self.reflet) + "\n"
        s += "couleur du fond " + str (self.fond) + "\n"
        return s
        
    def couleur_fond (self) :
        """retourne la couleur du fond"""
        return self.fond * self.ka
        
    def modele_illumination (self, rayon, p, obj, source) :
        """calcule la couleur pour un rayon donné, un point p, un objet obj, 
        et une source de lumière source"""
        n   = obj.normale (p, rayon).renorme ()
        vr  = rayon.direction.renorme ()
        vr *= float (-1)
        vs  = source.origine - p
        vs  = vs.renorme ()
        bi  = vs + vr
        bi  = bi.renorme ()
        
        # premier terme
        cos      = n.scalaire (vs)
        couleur  = source.couleur.produit_terme (obj.couleur_point (p)) * (cos * self.kb)
        
        # second terme : reflet
        cos      = n.scalaire (bi) ** self.reflet
        couleur += source.couleur.produit_terme (source.couleur) * (cos * self.kc)
        couleur  = couleur.produit_terme (rayon.couleur)
        
        return couleur


if __name__ == "__main__" :
    s = scene_phong (base.repere (), math.pi / 1.5, 400, 300)

    s.ajoute_source ( base.source (base.vecteur (0,10,10), \
                        base.couleur (1,1,1) ) )
    s.ajoute_source ( base.source (base.vecteur (10,10,5), \
                        base.couleur (0.5,0.5,0.5) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,0,12), \
                        3, base.couleur (1,0,0) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,-400,12), \
                        396, base.couleur (0.5,0.5,0.5) ) )
    print s
    
    screen  = pygame.display.set_mode (s.dim)
    screen.fill ((255,255,255))
    s.construit_image (screen)

    print "image terminée"
    scene.attendre_clic ()


image de synthèse, facette

# coding: cp1252
"""définition d'une sphère"""
import image_synthese_base as base
import image_synthese_sphere as obj
import image_synthese_phong as scene
import image_synthese_scene as scene_p
import pygame
import math

class facette (base.objet):
    """définit un triangle dans l'espace"""
    
    def __init__ (self, a,b,c, couleur):
        """initialisation"""
        self.a, self.b, self.c = a,b,c
        ab = b - a
        ac = c - a
        self.vnorm = ab.vectoriel (ac)
        self.vnorm = self.vnorm.renorme ()
        self.couleur = couleur
        
    def intersection_plan (self, r) :
        """retourne le point d'intersection entre le plan et le rayon r"""
        if r.direction.scalaire (self.vnorm) == 0 :
            return None
        oa      = self.a - r.origine 
        l       = self.vnorm.scalaire (oa) / self.vnorm.scalaire (r.direction)
        p       = r.origine + r.direction * l
        return p
        
    def point_interieur (self, p) :
        """dit si un point appartient à l'intérieur du triangle"""
        pa      = self.a - p        
        pb      = self.b - p        
        pc      = self.c - p   
        theta   = pa.angle (pb, self.vnorm)
        theta  += pb.angle (pc, self.vnorm)
        theta  += pc.angle (pa, self.vnorm)
        theta   = abs (theta)
        if theta >= math.pi * 0.9 : return True
        else : return False

    def intersection (self, r) :
        """retourne le point d'intersection avec le rayon r, 
        retourne None s'il n'y pas d'intersection"""
        p = self.intersection_plan (r)
        if p == None : return None
        if self.point_interieur (p) : return p
        else : return None
        
    def normale (self, p, rayon) :
        """retourne la normale au point de coordonnée p et connaissant le rayon"""
        if rayon.direction.scalaire (self.vnorm) < 0 :
            return self.vnorm
        else :
            return - self.vnorm 
        
    def couleur_point (self, p) :
        """retourne la couleur au point de coordonnée p"""
        return self.couleur
        
    def __str__ (self):
        """affichage"""
        s  = "facette --- a : " + str (self.a)
        s += " b : " + str (self.b)
        s += " c : " + str (self.c)
        s += " couleur : " + str (self.couleur)
        return s
        
        
class rectangle (facette):
    """définit un rectangle dans l'espace"""
    
    def __init__ (self, a,b,c,d, couleur):
        """initialisation, si d == None, d est calculé comme étant 
        le symétrique de b par rapport au milieu du segment [ac]"""
        facette.__init__(self, a,b,c, couleur)
        if d != None : self.d = d
        else :
            i       = (a + c) / 2
            self.d  = b + (i-b) * 2
        
    def point_interieur (self, p) :
        """dit si un point appartient à l'intérieur du triangle"""
        pa      = self.a - p        
        pb      = self.b - p        
        pc      = self.c - p   
        pd      = self.d - p   
        theta   = pa.angle (pb, self.vnorm)
        theta  += pb.angle (pc, self.vnorm)
        theta  += pc.angle (pd, self.vnorm)
        theta  += pd.angle (pa, self.vnorm)
        theta   = abs (theta)
        if theta >= math.pi * 0.9 : return True
        else : return False
        
    def __str__ (self):
        """affichage"""
        s  = "rectangle --- a : " + str (self.a)
        s += " b : " + str (self.b)
        s += " c : " + str (self.c)
        s += " d : " + str (self.d)
        s += " couleur : " + str (self.couleur)
        return s
        
       


        
if __name__ == "__main__" :
    
    s = scene.scene_phong (base.repere (), math.pi / 1.5, 400, 300)

    s.ajoute_source ( base.source (base.vecteur (0,8,8), \
                        base.couleur (0.6,0.6,0.6) ) )
    s.ajoute_source ( base.source (base.vecteur (10,0,0), \
                        base.couleur (0.6,0.6,0.6) ) )
    s.ajoute_source ( base.source (base.vecteur (8,8,4.5), \
                        base.couleur (0.6,0.6,0.6) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (1,0,5), \
                        1, base.couleur (1,0,0) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,-400,12), \
                        396, base.couleur (0.5,0.5,0.5) ) )
    s.ajoute_objet (facette ( base.vecteur (0,-2.5,6),   \
                               base.vecteur (-2,-2.5,3), \
                               base.vecteur (1,-3.5,4.5), \
                               base.couleur (0.2,0.8,0)))
    s.ajoute_objet (rectangle ( base.vecteur (0,-2.5,6),   \
                               base.vecteur (-2,-2.5,3), \
                               base.vecteur (-2,2.8,3.5), \
                               None, \
                               base.couleur (0,0,1)))
    print s
    
    screen  = pygame.display.set_mode (s.dim)
    screen.fill ((255,255,255))
    s.construit_image (screen)

    print "image terminée"
    scene_p.attendre_clic ()
    
    


File: file_dattente.tex, line 276


import math
import random
def generate_expo (mu):
    x = 0
    while x == 0: x = random.random()
    y = - math.log(1-x) / mu
    return y

File: file_dattente.tex, line 288


import random
def generate_expo (mu):
    return random.expovariate(mu)

simulation de longévité des ampoules

# coding: cp1252

import math
import random

def generate_expo (mu):
    return random.expovariate(mu)

S           = 10000
iteration   = 500
mu          = 1.0 / 100

# création d'un tableau de S ampoule qui contient la durée de
# vide restante d'une ampoule
ampoule         = [0 for a in range(0,S)]
moyenne_grille  = 0
for i in range(0,iteration):
    grille = 0
    mean   = 0
    for n in range(0,S):
        mean += ampoule [n]
        if ampoule[n] == 0:
            # remplacement d'une ampoule grillée
            grille += 1
            # on détermine la durée de vie de cette ampoule
            # on arrondit à l'entier le plus proche
            ampoule [n] = int (generate_expo(mu))
        else :
            # on enlève une heure à la durée de vie de l'ampoule
            ampoule [n] -= 1
    mean /= S
    if i > 0: moyenne_grille += grille
    print "itération : ", i, " moyenne durée : ", mean, " grillées :", grille

moyenne_grille = float (moyenne_grille) / float (iteration - 1)
print "nombre moyen d'ampoules grillées :", moyenne_grille

simulation génétique

import random

class Couleur :
    
    def __init__ (self, g1,g2) :
        self.g1 = g1        
        self.g2 = g2
        
    def couleur (self) :
        """ deux genes differents : marron,
        deux genes egaux a marron : marron
        deux genes egaux a bleu : bleu"""
        if self.g1 != self.g2 : return "marron"
        elif self.g1 == "marron" : return "marron"
        else : return "bleu"
            
    def __str__ (self) :
        return self.couleur ()
            
    def __add__ (self, autre) :
        """creation d'un fils, on tire au hasard le premier gene
        parmi ceux de self, on recommence pour le second gene parmi ceux de autre"""
    
        n = random.randint (0,1)
        if n == 0 : g1 = self.g1
        else : g1 = self.g2

        n = random.randint (0,1)
        if n == 0 : g2 = autre.g1
        else : g2 = autre.g2

        return Couleur (g1,g2)
        
def creation_hasard_couleur (proportion_gene_bleu) :
    """cree un individu au hasard, 
    proportion_gene_bleu est la proportion du gene bleu"""
    x = random.random ()
    if x <= proportion_gene_bleu : g1 = "bleu"
    else : g1 = "marron"

    x = random.random ()
    if x <= proportion_gene_bleu : g2 = "bleu"
    else : g2 = "marron"
    
    return Couleur (g1,g2)
    
    
def simulation (proportion_gene_bleu, nb_couleur, nb_iteration) :
    """effectue une simulation en tenant du nombre d'invidu (nb_couleur),
    du nombre d'iteration (nb_iteration), 
    de la proportion de gene bleu initiale (proportion_gene_bleu),
    cette proportion est differente de la proportion de gens aux yeux bleus,
    proportion_gene_bleu est la probabilite du gene bleu face au gene marron"""
    
    l = [ creation_hasard_couleur (proportion_gene_bleu) for i in range (0,nb_couleur) ]
    
    # on compte les proportions des couleurs des gens au debut
    # on utilise un dictionnaire
    prop_couleur = { "bleu":0 , "marron":0 }
    for c in l : prop_couleur [ c.couleur () ] += 1
    
    print ("distribution des couleurs d'yeux a la premiere generation ")
    print (prop_couleur)

    for it in range (0, nb_iteration) :

        e = []
        for i in range (0, len (l)) :
            n1 = random.randint (0, len (l)-1)
            n2 = random.randint (0, len (l)-1)
            e.append ( l [n1] + l [n2] )
            
        l = e
        
    # on compte les proportions des couleurs des gens a la fin
    # on utilise un dictionnaire
    prop_couleur_fin = { "bleu":0 , "marron":0 }
    for c in l : prop_couleur_fin [ c.couleur () ] += 1
        
    print ("\ndistribution des couleurs d'yeux a la derniere generation ")
    print (prop_couleur_fin)
    

l = [ 0.1 * (i+1) for i in range (0,9) ]
for x in l :
    print ("\nproportion_gene_bleu = ", x)
    simulation (x,1000,1000)
    
# ce programme effectue une simulation de 1000 iterations pour 1000 individus
# pour toutes les proportions de gene bleu [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
# l'objectif est de determiner a partir de quel seuil les gens aux yeux bleus ont une chance 
# de ne pas disparaitre
#
# pour chaque seuil, une seule simulation de permet de conclure, il faudrait 
# faire plusieurs centaines de simulation pour chaque seuil et ne conserver que la moyenne
# pour avoir un resultat fiable

calcul de table de mortalité

# colonne 1 : age
# colonne 2 : nombre d'hommes en vie a cet age depuis la naissance
# colonne 3 : nombre de femmes en vie a cet age depuis la naissance
# colonne 4 : nombre de gens en vie a cet age depuis la naissance
mortalite = [\
                [	0 	,	100000	,	100000	,	100000	], \
                [	1 	,	99571	,	99658	,	99613	], \
                [	2 	,	99537	,	99631	,	99583	], \
                [	3 	,	99514	,	99613	,	99562	], \
                [	4 	,	99495	,	99599	,	99546	], \
                [	5 	,	99479	,	99587	,	99532	], \
                [	6 	,	99465	,	99577	,	99520	], \
                [	7 	,	99453	,	99567	,	99509	], \
                [	8 	,	99442	,	99558	,	99499	], \
                [	9 	,	99433	,	99550	,	99490	], \
                [	10 	,	99422	,	99543	,	99481	], \
                [	11 	,	99411	,	99535	,	99472	], \
                [	12 	,	99400	,	99527	,	99462	], \
                [	13 	,	99387	,	99518	,	99451	], \
                [	14 	,	99371	,	99507	,	99437	], \
                [	15 	,	99350	,	99495	,	99421	], \
                [	16 	,	99320	,	99480	,	99398	], \
                [	17 	,	99280	,	99461	,	99368	], \
                [	18 	,	99227	,	99438	,	99330	], \
                [	19 	,	99157	,	99410	,	99281	], \
                [	20 	,	99076	,	99382	,	99225	], \
                [	21 	,	98989	,	99353	,	99167	], \
                [	22 	,	98899	,	99324	,	99106	], \
                [	23 	,	98808	,	99295	,	99046	], \
                [	24 	,	98718	,	99267	,	98986	], \
                [	25 	,	98632	,	99239	,	98928	], \
                [	26 	,	98545	,	99212	,	98871	], \
                [	27 	,	98455	,	99180	,	98809	], \
                [	28 	,	98367	,	99148	,	98748	], \
                [	29 	,	98279	,	99116	,	98687	], \
                [	30 	,	98187	,	99080	,	98623	], \
                [	31 	,	98085	,	99039	,	98551	], \
                [	32 	,	97979	,	98998	,	98476	], \
                [	33 	,	97871	,	98951	,	98398	], \
                [	34 	,	97756	,	98899	,	98314	], \
                [	35 	,	97633	,	98846	,	98225	], \
                [	36 	,	97500	,	98783	,	98126	], \
                [	37 	,	97355	,	98716	,	98020	], \
                [	38 	,	97201	,	98642	,	97905	], \
                [	39 	,	97033	,	98558	,	97777	], \
                [	40 	,	96849	,	98464	,	97637	], \
                [	41 	,	96645	,	98363	,	97483	], \
                [	42 	,	96427	,	98249	,	97316	], \
                [	43 	,	96186	,	98128	,	97134	], \
                [	44 	,	95912	,	97987	,	96924	], \
                [	45 	,	95606	,	97837	,	96695	], \
                [	46 	,	95272	,	97675	,	96445	], \
                [	47 	,	94901	,	97493	,	96166	], \
                [	48 	,	94483	,	97295	,	95855	], \
                [	49 	,	94024	,	97087	,	95518	], \
                [	50 	,	93532	,	96858	,	95155	], \
                [	51 	,	92993	,	96615	,	94760	], \
                [	52 	,	92428	,	96358	,	94346	], \
                [	53 	,	91835	,	96084	,	93909	], \
                [	54 	,	91201	,	95794	,	93442	], \
                [	55 	,	90533	,	95487	,	92950	], \
                [	56 	,	89824	,	95168	,	92432	], \
                [	57 	,	89070	,	94828	,	91880	], \
                [	58 	,	88266	,	94472	,	91295	], \
                [	59 	,	87407	,	94086	,	90666	], \
                [	60 	,	86496	,	93667	,	89995	], \
                [	61 	,	85546	,	93226	,	89294	], \
                [	62 	,	84556	,	92766	,	88562	], \
                [	63 	,	83504	,	92272	,	87783	], \
                [	64 	,	82388	,	91749	,	86956	], \
                [	65 	,	81202	,	91188	,	86075	], \
                [	66 	,	79938	,	90587	,	85135	], \
                [	67 	,	78599	,	89936	,	84131	], \
                [	68 	,	77184	,	89236	,	83065	], \
                [	69 	,	75653	,	88467	,	81906	], \
                [	70 	,	74012	,	87633	,	80659	], \
                [	71 	,	72245	,	86710	,	79304	], \
                [	72 	,	70350	,	85692	,	77837	], \
                [	73 	,	68317	,	84567	,	76247	], \
                [	74 	,	66155	,	83344	,	74543	], \
                [	75 	,	63859	,	81995	,	72709	], \
                [	76 	,	61404	,	80490	,	70718	], \
                [	77 	,	58802	,	78823	,	68572	], \
                [	78 	,	56060	,	76968	,	66263	], \
                [	79 	,	53165	,	74899	,	63771	], \
                [	80 	,	50171	,	72622	,	61127	], \
                [	81 	,	47013	,	70078	,	58269	], \
                [	82 	,	43733	,	67275	,	55222	], \
                [	83 	,	40329	,	64168	,	51963	], \
                [	84 	,	36830	,	60763	,	48509	], \
                [	85 	,	33321	,	57061	,	44906	], \
                [	86 	,	29785	,	53099	,	41162	], \
                [	87 	,	26244	,	48845	,	37273	], \
                [	88 	,	22775	,	44371	,	33314	], \
                [	89 	,	19407	,	39804	,	29360	], \
                [	90 	,	16252	,	35111	,	25455	], \
                [	91 	,	13351	,	30448	,	21694	], \
                [	92 	,	10752	,	25917	,	18153	], \
                [	93 	,	8489	,	21596	,	14885	], \
                [	94 	,	6563	,	17564	,	11931	], \
                [	95 	,	4919	,	13959	,	9331	], \
                [	96 	,	3588	,	10756	,	7086	], \
                [	97 	,	2562	,	8079	,	5254	], \
                [	98 	,	1791	,	5918	,	3805	], \
                [	99 	,	1254	,	4245	,	2714	], \
                [	100 	,	879	,	3014	,	1921	], \
                [	101 	,	628	,	2110	,	1351	], \
                [	102 	,	467	,	1482	,	962	], \
                [	103 	,	375	,	1056	,	707	], \
                [	104 	,	279	,	752	,	510	], \
                ]

def proba_vie_sup (mortalite, age_vie, age_mort) :
    nb1 = mortalite [age_vie][3]
    if age_mort < len (mortalite) : nb2 = mortalite [age_mort][3]
    else : nb2 = 0
    return float (nb2) / float (nb1)
    
def proba_mort_egale (mortalite, age_vie, age_mort) :
    p1 = proba_vie_sup  (mortalite, age_vie, age_mort)
    p2 = proba_vie_sup  (mortalite, age_vie, age_mort+1)
    return p1 - p2
    
def esperance_vie (mortalite, age_vie) :
    s = 0.0
    w = 0.0
    for i in range (age_vie, len (mortalite)) :
        s += i * proba_mort_egale (mortalite, age_vie, i)
        w += proba_mort_egale (mortalite, age_vie, i)
    return s / w - age_vie
    
print proba_vie_sup (mortalite, 20, 40)
print esperance_vie (mortalite, 20), esperance_vie (mortalite, 0)


calcul de taux de fécondité

# colonne 1 : age
# colonne 2 : nombre d'hommes en vie a cet age depuis la naissance
# colonne 3 : nombre de femmes en vie a cet age depuis la naissance
# colonne 4 : nombre de gens en vie a cet age depuis la naissance
mortalite = [\
                [	0 	,	100000	,	100000	,	100000	], \
                [	1 	,	99571	,	99658	,	99613	], \
                [	2 	,	99537	,	99631	,	99583	], \
                [	3 	,	99514	,	99613	,	99562	], \
                [	4 	,	99495	,	99599	,	99546	], \
                [	5 	,	99479	,	99587	,	99532	], \
                [	6 	,	99465	,	99577	,	99520	], \
                [	7 	,	99453	,	99567	,	99509	], \
                [	8 	,	99442	,	99558	,	99499	], \
                [	9 	,	99433	,	99550	,	99490	], \
                [	10 	,	99422	,	99543	,	99481	], \
                [	11 	,	99411	,	99535	,	99472	], \
                [	12 	,	99400	,	99527	,	99462	], \
                [	13 	,	99387	,	99518	,	99451	], \
                [	14 	,	99371	,	99507	,	99437	], \
                [	15 	,	99350	,	99495	,	99421	], \
                [	16 	,	99320	,	99480	,	99398	], \
                [	17 	,	99280	,	99461	,	99368	], \
                [	18 	,	99227	,	99438	,	99330	], \
                [	19 	,	99157	,	99410	,	99281	], \
                [	20 	,	99076	,	99382	,	99225	], \
                [	21 	,	98989	,	99353	,	99167	], \
                [	22 	,	98899	,	99324	,	99106	], \
                [	23 	,	98808	,	99295	,	99046	], \
                [	24 	,	98718	,	99267	,	98986	], \
                [	25 	,	98632	,	99239	,	98928	], \
                [	26 	,	98545	,	99212	,	98871	], \
                [	27 	,	98455	,	99180	,	98809	], \
                [	28 	,	98367	,	99148	,	98748	], \
                [	29 	,	98279	,	99116	,	98687	], \
                [	30 	,	98187	,	99080	,	98623	], \
                [	31 	,	98085	,	99039	,	98551	], \
                [	32 	,	97979	,	98998	,	98476	], \
                [	33 	,	97871	,	98951	,	98398	], \
                [	34 	,	97756	,	98899	,	98314	], \
                [	35 	,	97633	,	98846	,	98225	], \
                [	36 	,	97500	,	98783	,	98126	], \
                [	37 	,	97355	,	98716	,	98020	], \
                [	38 	,	97201	,	98642	,	97905	], \
                [	39 	,	97033	,	98558	,	97777	], \
                [	40 	,	96849	,	98464	,	97637	], \
                [	41 	,	96645	,	98363	,	97483	], \
                [	42 	,	96427	,	98249	,	97316	], \
                [	43 	,	96186	,	98128	,	97134	], \
                [	44 	,	95912	,	97987	,	96924	], \
                [	45 	,	95606	,	97837	,	96695	], \
                [	46 	,	95272	,	97675	,	96445	], \
                [	47 	,	94901	,	97493	,	96166	], \
                [	48 	,	94483	,	97295	,	95855	], \
                [	49 	,	94024	,	97087	,	95518	], \
                [	50 	,	93532	,	96858	,	95155	], \
                [	51 	,	92993	,	96615	,	94760	], \
                [	52 	,	92428	,	96358	,	94346	], \
                [	53 	,	91835	,	96084	,	93909	], \
                [	54 	,	91201	,	95794	,	93442	], \
                [	55 	,	90533	,	95487	,	92950	], \
                [	56 	,	89824	,	95168	,	92432	], \
                [	57 	,	89070	,	94828	,	91880	], \
                [	58 	,	88266	,	94472	,	91295	], \
                [	59 	,	87407	,	94086	,	90666	], \
                [	60 	,	86496	,	93667	,	89995	], \
                [	61 	,	85546	,	93226	,	89294	], \
                [	62 	,	84556	,	92766	,	88562	], \
                [	63 	,	83504	,	92272	,	87783	], \
                [	64 	,	82388	,	91749	,	86956	], \
                [	65 	,	81202	,	91188	,	86075	], \
                [	66 	,	79938	,	90587	,	85135	], \
                [	67 	,	78599	,	89936	,	84131	], \
                [	68 	,	77184	,	89236	,	83065	], \
                [	69 	,	75653	,	88467	,	81906	], \
                [	70 	,	74012	,	87633	,	80659	], \
                [	71 	,	72245	,	86710	,	79304	], \
                [	72 	,	70350	,	85692	,	77837	], \
                [	73 	,	68317	,	84567	,	76247	], \
                [	74 	,	66155	,	83344	,	74543	], \
                [	75 	,	63859	,	81995	,	72709	], \
                [	76 	,	61404	,	80490	,	70718	], \
                [	77 	,	58802	,	78823	,	68572	], \
                [	78 	,	56060	,	76968	,	66263	], \
                [	79 	,	53165	,	74899	,	63771	], \
                [	80 	,	50171	,	72622	,	61127	], \
                [	81 	,	47013	,	70078	,	58269	], \
                [	82 	,	43733	,	67275	,	55222	], \
                [	83 	,	40329	,	64168	,	51963	], \
                [	84 	,	36830	,	60763	,	48509	], \
                [	85 	,	33321	,	57061	,	44906	], \
                [	86 	,	29785	,	53099	,	41162	], \
                [	87 	,	26244	,	48845	,	37273	], \
                [	88 	,	22775	,	44371	,	33314	], \
                [	89 	,	19407	,	39804	,	29360	], \
                [	90 	,	16252	,	35111	,	25455	], \
                [	91 	,	13351	,	30448	,	21694	], \
                [	92 	,	10752	,	25917	,	18153	], \
                [	93 	,	8489	,	21596	,	14885	], \
                [	94 	,	6563	,	17564	,	11931	], \
                [	95 	,	4919	,	13959	,	9331	], \
                [	96 	,	3588	,	10756	,	7086	], \
                [	97 	,	2562	,	8079	,	5254	], \
                [	98 	,	1791	,	5918	,	3805	], \
                [	99 	,	1254	,	4245	,	2714	], \
                [	100 	,	879	,	3014	,	1921	], \
                [	101 	,	628	,	2110	,	1351	], \
                [	102 	,	467	,	1482	,	962	], \
                [	103 	,	375	,	1056	,	707	], \
                [	104 	,	279	,	752	,	510	], \
                ]

class Population :
    
    def __init__ (self, mortalite) :
        self.mortalite = mortalite
        

    def proba_vie_sup (self, age_vie, age_mort) :
        nb1 = self.mortalite [age_vie][3]
        if age_mort < len (mortalite) : nb2 = self.mortalite [age_mort][3]
        else : nb2 = 0
        return float (nb2) / float (nb1)
        
    def proba_mortalite_sexuee (self, age_vie, age_mort, indice) :
        nb1 = self.mortalite [age_vie][indice]
        if age_mort < len (mortalite) : nb2 = self.mortalite [age_mort][indice]
        else : nb2 = 0
        return 1.0 - float (nb2) / float (nb1)
        
    def proba_mort_egale (self, age_vie, age_mort) :
        p1 = self.proba_vie_sup  (age_vie, age_mort)
        p2 = self.proba_vie_sup  (age_vie, age_mort+1)
        return p1 - p2
        
    def esperance_vie (self, age_vie) :
        s = 0.0
        w = 0.0
        for i in range (age_vie, len (mortalite)) :
            s += i * self.proba_mort_egale (age_vie, i)
            w += self.proba_mort_egale (age_vie, i)
        if w == 0 : return 0.0
        else : return s / w - age_vie
        
    def proportion_femme (self, age_vie) :
        d1 = self.mortalite [age_vie][3] - self.mortalite [age_vie][1]
        d2 = self.mortalite [age_vie][2] - self.mortalite [age_vie][1]
        if d1 == 0 and d2 == 0 : return 0.5
        else : return float (d1) / float (d2)
        
    def annee_viager (self, i, j) :
        return self.esperance_vie (i) - self.esperance_vie (j)
        
    def proportion_femme_tout (self) :
        p1f = self.proportion_femme (1)
        p1h = 1.0 - p1f
        m1f = self.proba_mortalite_sexuee (0, 1, 1)
        m1h = self.proba_mortalite_sexuee (0, 1, 2)
        cf  = 1.0 / (1.0 - m1f)
        ch  = 1.0 / (1.0 - m1h)
        return p1f * cf / ( p1f * cf + p1h * ch )
        
        
class PopulationPlus (Population) :
    
    def proba_mort_egale (self, age_vie, age_mort) :
        if age_mort > 0 : 
            return Population.proba_mort_egale (self, age_vie, age_mort)
        else :
            p1 = self.proba_vie_sup  (age_vie, age_mort)
            p2 = 1.0 - (1.0 - self.proba_vie_sup  (age_vie, age_mort+1)) / 2
            return p1 - p2    
  
  
class Simulation (Population)  :
    
    def __init__ (self, popu, fecondite = 0.2, age1 = 25, age2 = 34) :
        Population.__init__ (self, popu)
        self.fecondite = fecondite
        self.age1 = age1
        self.age2 = age2
    
    def prepare (self) :
        p = self.proportion_femme_tout ()
        self.sim = [ [ t [1] * p, t [2] * (1.0 - p) ] for t in self.mortalite ]
        
    def proportion_bebe_fille (self) :
        p1 = self.proportion_femme_tout ()
        #p2 = self.proportion_femme (1)
        return p1 # approximation
        
    def bebe (self) :
        b = 0
        for a in range (self.age1, self.age2 + 1) :
            b += self.sim [a][0] * self.fecondite
        p = self.proportion_bebe_fille ()
        return int (b * p), int (b * (1.0 - p)) 
    
    def iteration (self) :
        for i in range (len (self.sim)-1, 0, -1) : # boucle a l'envers
            self.sim [i][0] = self.sim [i-1][0] * (1.0 - self.proba_mortalite_sexuee (i-1, i, 1))
            self.sim [i][1] = self.sim [i-1][1] * (1.0 - self.proba_mortalite_sexuee (i-1, i, 2))
        f,g = self.bebe ()
        self.sim [0][0] = f
        self.sim [0][1] = g
        
    def simulation (self, nb) :
        self.prepare ()
        for i in range (0, nb) :
            self.iteration ()
        return self.sim
        
    def nb (self, sim) :
        f,g = 0,0
        for i in sim :
            f += i [0]
            g += i [1]
        return int (f), int (g)
            
  
        
p = Population (mortalite)
print p.proba_vie_sup (20, 40)
print p.esperance_vie (20), p.esperance_vie (0)
for i in range (0, 5) :
    print p.proportion_femme (i)
    
print "--------------------"    
pp = PopulationPlus (mortalite)
print pp.esperance_vie (20), pp.esperance_vie (0)
print pp.proportion_femme_tout ()

for x in range (0, 200) :
    fecondite = 0.2 + x * 0.0001
    s = Simulation (mortalite, fecondite = fecondite)
    r = s.simulation (0)
    z = s.nb (r)
    r = s.simulation (100)
    print "fecondite = ", fecondite, " population H,F ", s.nb (r), " initiale ", z

    

goûts en commun

import random

def genere_fichier_exemple (nom) :
    """cette fonction cree un fichier d'exemple contenant des prenoms
    et des reponses, le format est le suivant :
    
    prenom, espace, liste des reponses mise bout a bout, passage a la ligne"""
    prenom = [  "jean", "cecile", "juliette", "daniel", "julie", \
                "gerard", "amelie", "charles", "alix", "frederic", \
                "claire", "richard" ]
    f = open (nom, "w")
    for p in prenom :
        f.write (p)
        f.write (" ")
        for i in range (0,20) :
            a = random.randint (0,5) + 1
            f.write (str (a))
        f.write ("\n")
    f.close ()
    
class Personne :
    """on definit une personne"""
    def __init__ (self, prenom, reponse) :
        self.prenom  = prenom
        self.reponse = reponse
        self.commun  = 0    # compte le nombre de points communs
        
    def __cmp__ (self, autre) :
        """operateur de comparaison, reponse a la question 5"""
        if self.commun == autre.commun : return 0
        if self.commun < autre.commun : return -1
        return 1
        
    def __str__ (self) :
        """pour l'affichage"""
        s = self.prenom + "\t" + str (self.commun)
        return s
        
    def point_commun (self, autre) :
        """calcul le nombre de points commun entre deux personnes"""
        s = 0
        for i in range (0, len (self.reponse)) :
            if self.reponse [i] == autre.reponse [i] : s += 1
        return s
        
    
def lit_reponse (nom) :
    """on relie le fichier ecrit avec la fonction precedente"""
    f = open (nom, "r")
    line = f.readlines ()
    f.close ()
    
    rep = []
    for l in line :
        s = l.replace ("\n", "")  # on enleve les fins de ligne
        spl = s.split ()    # on coupe la ligne en deux, les deux morceaux
                            # separes par des espaces
        rep.append ( Personne ( spl [0], spl [1] )) 
    return rep
    
def point_commun (n, rep) :
    """calcule le nombre de points communs entre rep [n] et rep [i],
    stocke le resultat dans rep [i].commun"""
    for r in rep :
        d = r.point_commun (rep [n])
        r.commun = d
    
###########################################################    
# debut du programme
###########################################################
# creation du fichier
genere_fichier_exemple ("reponses.txt")

# relecture du fichier
rep = lit_reponse ("reponses.txt")

# calcule les points communs
point_commun (0, rep)

# on les trie par ordre croissant
rep.sort ()

print "le ou la plus proche ", rep [len (rep)-1]
print "le ou la plus loin ", rep [0]

# liste complete
for r in rep :
    print r
        

File: histogramme_cor.tex, line 7


# coding: cp1252
import random
import math
 
n  = 10000
hn = dict ()
for i in xrange (1,n):
    x  = random.gauss (0,1)
    xx = round (x, 1)
    if xx not in hn:					# si h [xx] n'existe pas encore
        hn [xx] = 0
    hn [xx] += 1

# affichage de l'histogramme
for w in hn:
    print w, "    \t", float (hn [w]) / float (n)

File: histogramme_cor.tex, line 45


# coding: cp1252
import random
import math

n  = 10000
hb = dict ()
k  = 400
for i in xrange (1,n):
    if (i % 500 == 0) :	       # comme le programme est assez lent, 
        print i                # cela permet de suivre l'avancement
    s = 0
    for j in xrange (1,k): 
        a  = random.randint (0,1)
        s += a
    x  = float (s - k/2) / math.sqrt (float (k * 0.25))
    xx = round (x, 1)
 
    if xx not in hb:
        hb [xx] = 0
    hb [xx] += 1
    
# affichage de l'histogramme
for w in hb:
    print w, "    \t", float (hb [w]) / float (n)

File: histogramme_cor.tex, line 111


x = hn.keys ()
x.sort ()
y = [ hn [a] for a in x ] 
import IaGraph.plot
IaGraph.plot(x, y)
import Tkinter
Tkinter.mainloop ()

File: histogramme_cor.tex, line 135


from scipy import gplt
x1 = hn.keys ()
x1.sort ()
y = [ hn [a] for a in x1 ]
x2 = hb.keys ()
x2.sort ()
z = [ hb [a] for a in x2 ]
gplt.plot (x1,y,x2,z)

File: histogramme_cor.tex, line 159


x1 = hn.keys ()
x1.sort ()
y = [ hn [a] for a in x1 ]
x2 = hb.keys ()
x2.sort ()
z = [ hb [a] for a in x2 ]

import biggles      
p = biggles.FramedPlot()
p.title = "Histogramme"
p.xlabel = "x"
p.ylabel = "y"
p.add( biggles.Curve(x1, y, color="red") )
p.add( biggles.Curve(x2, z, color="blue") )
p.show()

histogramme

# coding: cp1252
import random
import math

n  = 10000
hn = dict ()

for i in xrange (1,n):
    x  = random.gauss (0,1)
    xx = round (x, 1)
    if xx not in hn:					# si h [xx] n'existe pas encore
        hn [xx] = 0
    hn [xx] += 1

# affichage de l'histogramme
for w in hn:
    print w, "    \t", float (hn [w]) / float (n)


n  = 10000
hb = dict ()
k  = 400
for i in xrange (1,n):
    if (i % 500 == 0) :	     # comme le programme est assez lent,
        print i              # cela permet de suivre l'avancement
    s = 0
    for j in xrange (1,k):
        a  = random.randint (0,1)
        s += a
    x  = float (s - k/2) / math.sqrt (float (k * 0.25))
    xx = round (x, 1)

    if xx not in hb:
        hb [xx] = 0
    hb [xx] += 1

# affichage de l'histogramme
for w in hb:
    print w, "    \t", float (hb [w]) / float (n)


x1 = hn.keys ()
x1.sort ()
y = [ hn [a] for a in x1 ]
x2 = hb.keys ()
x2.sort ()
z = [ hb [a] for a in x2 ]

import biggles
p = biggles.FramedPlot()
p.title = "Histogramme"
p.xlabel = "x"
p.ylabel = "y"
p.add( biggles.Curve(x1, y, color="red") )
p.add( biggles.Curve(x2, z, color="blue") )
p.show()


écrire un rapport au format HTML

# coding: cp1252
import os
import os.path
import PIL.Image
        
class html_file (object) :
    """cette classe propose quelques méthodes pour écrire un fichier HTML simplement"""
    
    header = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
</HEAD>
<BODY >"""

    foot = """</BODY>
</HTML>        
    """
    
    def __init__ (self, file) :
        """construction d'un fichier HTML"""
        self.file = file
        
    def open (self) :
        """ouverture du fichier"""
        self.f = open (self.file, "w")
        self.f.write (self.header)
        
    def close (self) :
        """fermeture du fichier"""
        self.f.close ()
        
    def text (self, s) :
        """écrit du texte dans un fichier HTML"""
        s = s.replace ("\n", "<BR>")
        self.f.write (s)
        
    def text_line (self) :
        """passe une ligne dans un fichier HTML"""
        self.f.write ("<BR>")
        
    def table_begin (self, nc) :
        """commence une table, nc est le nombre de colonnes"""
        self.f.write ("""<TABLE cellSpaceing="1" """)
        self.f.write ("""cellPadding="1" border="1">\n  <TR>\n    <TD>""")
        
    def table_end (self) :
        """termine une table"""
        self.f.write ("""    </TD>\n  </TR>\n</TABLE>\n""")
        
    def table_next (self) :
        """passe à la colonne suivante"""
        self.f.write ("""    </TD>\n    <TD>""")
        
    def table_next_line (self) :
        """passe à la ligne suivante"""
        self.f.write ("""    </TD>\n  </TR>\n  <TR>\n    <TD>""")
        
    def relative_path (self, url) :
        """trouve le chemin relatif par rapport au fichier"""
        pr = os.path.commonprefix ( [ self.file, url ] )
        if pr != None :
            d = os.path.dirname (self.file)
            if pr.count (d) == 1 :
                pr = d + "\\"
            url = url [ len (pr) : len (url) ]
        return url

    def clean_url (self, url) :
        """enlève les espaces et redresse les barres"""
        url = url.replace (" ", "\%20")
        url = url.replace ("\\", "/")
        return url
        
    def add_link (self, url, caption, isfile) :
        """ajoute un lien dans le fichier html, 
        url est l'adresse, caption est l'intitulé du lien, 
        si isfile vaut True, cherche un chemin relatif par rapport à self.file"""
        if isfile : url = self.relative_path (url)
        url = self.clean_url (url) 
        s   = """<A HREF="%s">%s</A>""" % (url, caption)
        self.f.write (s)
        
    def add_image (self, image, size = None, zoom = None) :
        """ajoute une image dans le fichier html,
        celle-ci est enregistrée avec un numéro, offre la possibilité de zoomer 
        ou de modifier la taille"""
        if not self.__dict__.has_key ("num_image") : self.num_image = 0
        name, ext = os.path.splitext (self.file)
        name      = name + str (self.num_image) + ".png"
        image.save (name)
        self.add_image_link (name, size, zoom)
        self.num_image += 1
        
    def add_image_link (self, url, size = None, zoom = None) :
        """ajoute une image dans le fichier html,
        cette image n'est pas recopiée, il est possible de spécifier une taille, 
        ou de multiplier cette taille"""
        
        if size == None :
            im      = PIL.Image.open (url)
            size    = im.size
        if zoom != None :
            size = (int (size [0] * zoom), int (size [1] * zoom))

        url = self.relative_path (url)
        url = self.clean_url (url) 
            
        s = """<IMG width=%d height=%d border=0 SRC="%s" alt="%s">""" \
                        % (size [0], size [1], url, url)
        self.f.write (s)

        
if __name__ == "__main__" :
    
    print "écriture du fichier ",file
    file = "c:\\temp\\essai.html"
    
    html = html_file (file)
    html.open ()
    html.text ("""première ligne d'un fichier HTML,
    seconde ligne""")
    html.table_begin (2)
    html.text ("1")
    html.table_next ()
    html.text ("2")
    html.table_next_line ()
    html.text("3")
    html.table_next ()
    html.text ("4")
    html.table_end ()
    html.add_link ("c:\\temp\\cours.py", "cours.py", True)
    html.text_line ()
    im = PIL.Image.new ("RGB", (100,100), color = (100,100,100))
    html.add_image (im)
    html.add_image (im, zoom = 2)
    html.close ()
    
    print "fin"


récupération de chiffre de la base MNIST

# coding: cp1252
"""décomposition de la base d'image MNIST"""

import os
import struct
import PIL  # ligne à supprimer si on n'a pas besoin des images
import PIL.Image as PIM  # ligne à supprimer si on n'a pas besoin des images

def transcription_entier (str) :
    """convertit un entier lu en format binaire en entier"""
    t = struct.unpack ("BBBB", str)
    i = t [3] + t [2] * 256 + t [1] * 256 * 256 + t [0] * 256 * 256 * 256
    return i
    
def lire_image (fim, nl, nc) :
    """lit une image dans le fichier fim, cette image a nl lignes et nc colonnes,
    retourne l'image sous la forme d'un t-uple"""
    nb  = nl * nc
    str = fim.read (nb)
    t   = struct.unpack ("B" * nb, str)
    return t
    
def lire_image (fim, nl, nc) :
    """lit une image dans le fichier fim, cette image a nl lignes et nc colonnes,
    retourne l'image sous la forme d'un t-uple"""
    nb  = nl * nc
    str = fim.read (nb)
    t   = struct.unpack ("B" * nb, str)
    return t

def lire_label (fla) :
    """lit un label (un chiffre) dans le fichier fla, retourne un entier"""
    str = fla.read (1)
    t   = struct.unpack ("B", str)
    return t [0]

def binarisation (image, binar) :
    """binarisation d'une image"""
    
    res = []
    for i in image :
        if i < 255 - binar : res.append (255)
        else : res.append (0)
    return res


def write_image_matlab (fmat, image) :
    """écrit une image au format matlab, chaque nombre indique 
    la position du prochain pixel noir,
    la suite est aussi longue qu'il y a de pixels dans l'image
    et se termine par une suite de 0 qui indique qu'il n'y a plus de pixels noirs"""
    nb = 0
    for i in xrange (0, len(image)) :
        if image [i] == 0 :
            fmat.write ("," + str (i+1))
            nb += 1
    for i in xrange (0, len (image) - nb) :
        fmat.write (",0")

def decompose_mnist (file_image, file_label, file_matlab, binar, \
                        nbcl = -1, dir_image1 = None, dir_image2 = None) :
    """décompose la base MNIST en un format utilisable sous MATLAB,
    commence par [, termine par ], chaque ligne est composée comme suit :
    premier nombre = classe, voir fonction write_image_matlab ;,
    nbcl est le nombre d'images à extraire par classe, 
    si nbcl == -1, traite toute la base,
    binar est le seuil de binarisation, voir fonction binarisation,
    si dir_image1 != None, les images des nombres sont écrites,
    si dir_image2 != None, on continue d'explorer le fichier des images 
    mais les images des nombres sont écrites dans le répertoire dir_image2"""
    
    fim = open (file_image, "rb")
    fla = open (file_label, "rb")
    
    s           = fla.read (4) # , (Hal_byte*) &umagic_an) ;
    magic_an    = transcription_entier (s)
    s           = fla.read (4) # , (Hal_byte*) &unb_an) ;
    nb_an       = transcription_entier (s)
    
    s           = fim.read (4) # , (Hal_byte*) &umagic_im) ;
    magic_im    = transcription_entier (s)
    s           = fim.read (4) # , (Hal_byte*) &unb_im) ;
    nb_im       = transcription_entier (s)
    s           = fim.read (4) #, (Hal_byte*) &unl_im) ;
    nl_im       = transcription_entier (s)
    s           = fim.read (4) #, (Hal_byte*) &unc_im) ;
    nc_im       = transcription_entier (s)
    
    if nbcl == -1 : nbcl = nb_im
    
    print "nombre de labels ", nb_an
    print "nombre magique label , vérification (2049) ", magic_an
    print "nombre d'images ", nb_im
    print "nombre magique image, vérification (2051) ", magic_im
    print "nombre de lignes ", nl_im
    print "nombre de colonnes ", nc_im

    if file_matlab != None :
        fmat = open (file_matlab, "wt")
        fmat.write ("[")
        
    label_count = { }
    
    nb      = 0
    cent    = int (nb_im / 100)
    while nb < nb_im :
        
        if nb % cent == 0 : print "avancement ", nb / cent, " %"
        nb += 1
        
        image = lire_image (fim, nl_im, nc_im)
        label = lire_label (fla)
        
        image = binarisation (image, binar)
        
        if not label_count.has_key (label) : label_count [label] = 0
        if 0 <= label_count [label] < nbcl : 
            dir_image = dir_image1
        elif nbcl <= label_count [label] < nbcl * 2 : 
            dir_image = dir_image2
        else : 
            dir_image = None
            continue 
            

        if file_matlab != None :
            fmat.write (str (label))
            write_image_matlab (fmat, image)
            fmat.write (";\n")
        
        if dir_image != None :
            nom     = "image_%d_%5d" % (label, label_count [label] % nbcl)
            nom     = dir_image + "\\" + nom + ".tif"
            surf    = PIM.new ("RGB", (nc_im, nl_im) )
            for i in xrange (0, len (image)) :
                x,y = i % nc_im, i // nc_im
                c   = image [i]
                surf.putpixel ((x,y), (c,c,c))
                
            surf.save (nom)
            
        label_count [label] += 1
    
    if file_matlab != None :
        fmat.write ("]")
        fmat.close ()
        
    fim.close ()
    fla.close ()
    
    key = label_count.keys ()
    key.sort ()
    for i in key :
        print "label ", i , " \t : ", label_count [i]
    
    return label_count


if __name__ == "__main__" : 
        file_image  = "C:\\Downloads\\data_image\\mnist\\t10k-images.idx3-ubyte"
        file_label  = "C:\\Downloads\\data_image\\mnist\\t10k-labels.idx1-ubyte"
        file_matlab = "c:\\temp\\mnist2\\matlab.txt"
        dir_image   = None # "c:\\temp\\mnist2"
        nb          = 20
        binar       = 190
        
        decompose_mnist (file_image, file_label, file_matlab, \
                        binar, nb, dir_image1, dir_image2)

plus proches voisins

# coding: cp1252
import math
import random


class nuage_points (object) :
    """définit une classe de nuage de points"""
    
    def __init__ (self) :
        """constructeur"""
        self.nb = 0         # aucun élément
        self.nuage = []     # aucun élément
        
    def __iter__(self) :
        """retourne un itérateur sur l'ensemble de points"""
        return self.nuage.__iter__ ()
        
    def __len__ (self) :
        """retourne le nombre d'élément"""
        return len (self.nuage)
        
    def distance (self, obj1, obj2) :
        """retourne une distance entre deux éléments obj1 et obj2"""
        return 0
        
    def label (self, obj) :
        """retourne le label d'un objet"""
        return None
        
    def ppv (self, obj) :
        """retourne l'élément le plus proche de obj et sa distance avec obj"""
        mn = None
        dm = None
        for l in self.nuage :
            d = self.distance (l, obj)
            if dm == None or d < dm :
                dm = d
                mn = l
        return mn,dm
        
    def ppv_nuage (self, nuage, bienclasse = None, erreur = None) :
        """calcule un taux de classification pour un nuage,
        utilise la fonction ppv pour chaque élément de nuage,
        retourne le nombre d'élément bien classés, et mal classés,
        si bienclasse est une liste vide (!= None), cette liste contiendra
        la liste des couples d'éléments (x,y) in (nuage, self) pour lesquels
        la classification est bonne,
        si erreur est une liste vide (!= None), cette liste contiendra 
        la liste des couples d'éléments (x,y) in (nuage,self) 
        pour lesquels la classification est mauvaise"""
        disp    = len (nuage) / 10 ;
        good    = 0
        bad     = 0
        n       = 0
        for x in nuage :
            obj,d = self.ppv (x)
            if self.label (obj) == self.label (x) : 
                good += 1
                if bienclasse != None : bienclasse.append ((obj,x))
            else : 
                bad += 1
                if erreur != None : erreur.append ((obj, x))
            if n % disp == 0 : print "ppv_nuage ", n * 100 / len (nuage), "%"
            n += 1
        return good, bad
        

plus proches voisins sur des images

# coding: cp1252
import os
import os.path
import mnist
import string
import PIL
import PIL.Image
import html_file as html
import psyco
import random
import kppv
import time

# définit une classe héritant de kppv.nuage_points qui surcharge les 
# fonctions distance et label
class nuage_point_distance_label (kppv.nuage_points) :
    """hérite de kppv.nuage_point et surcharge les méthodes :
            - distance
            - label
    """

    def distance (self, obj1, obj2) :
        """surcharge de la fonction distance, comme les images sont toutes
        de dimensions identiques, on peut compter les pixels de couleurs différentes,
        le résultat est la distance entre deux images"""
        if len (obj1) != len (obj2) :
            print "erreur, len (obj1) != len (obj2)"
        d = 0
        for i in xrange (2, len (obj1)) :
            if obj1 [i] != obj2 [i] : d += 1
        return d
                
    def label (self, obj) :
        """retourne le label d'un objet"""
        return obj [0]
    
        
class nuage_image (object) :
    """nuage de points, chaque élément est une image, 
    les images sont en noir et blanc, liste de 0 ou 1"""
    
    def __init__ (self, nuage_ppv, rep, nb, extension = "tif") :
        """initialise le nuage d'images avec un répertoire
        qui est l'emplacement des images pour ce nuage, 
        le nom des images contient une chaîne de caractères suivi 
        d'un label séparés par un blanc soulignés, 
        extension est le type de images à charger,
        on ne considère que les nb premières images,
        nuage est une instance de la classe nuage_point ou nuage_point_laesa"""
        
        def binarise (p) :
            if p [0] == 0 : return 1
            else : return 0
        
        self.nb     = 0
        self.nuage  = []
        
        file = os.listdir (rep)
        nb   = min (nb, len (file))
        step = nb / 10
        n    = 0 
        for f in file :
            if n >= nb : break
            if n % step == 0 : print "nuage_image, avancement ", n * 100 / nb, "%"
            n += 1
            ext = os.path.splitext (f)
            ext = ext [len (ext) - 1].lower ()
            ext = ext [1 : len (ext)]
            if ext != "tif" : continue 
            s       = f.split ("_")
            label   = s [1]
            im      = PIL.Image.open (rep + "\\" + f)
            size    = im.size
            data    = [ binarise (im.getpixel ((x,y))) for y in xrange (0, size [1]) \
                                                        for x in xrange (0, size [0]) ]
            data.insert (0, size)
            data.insert (0, label)
            self.nuage.append ( tuple (data))
            
        self.ppv          = nuage_ppv 
        self.ppv.nb       = self.nb
        self.ppv.nuage    = self.nuage

        
    def image (self, obj) :
        """reconstruit une image à partir d'un élément"""
        size    = obj [1]
        im      = PIL.Image.new ("RGB", size)
        nb      = len (obj) - 2
        for i in xrange (0, nb) :
            if obj [i] == 0 : im.putpixel ( (i % size [0], i // size [1]), (255,255,255))
            else : im.putpixel ((i % size [0], i // size [1]), (0,0,0))
        return im
    
    def html_couple (self, fichier, l, zoom = None) :
        """écrit un fichier html contenant toutes les images mal classées, 
        à partir de la liste erreur construite par la méthode nuage_points.ppv_nuage"""
        
        # nombre de colonnes maximales
        maxc = 0
        for x in l : maxc = max (maxc, len (x))
     
        f = html.html_file (fichier)
        f.open ()
        f.table_begin (maxc*2+1)
        
        f.text ("indice")
        f.table_next ()
        f.text ("label")
        f.table_next ()
        f.text ("à classer")
        f.table_next ()
        for n in xrange (1, maxc) :
            f.text ("label")
            f.table_next ()
            f.text ("voisin " + str (n))
            f.table_next ()
        f.table_next_line ()

        n = 0
        for x in l :
            f.text (str (n))
            f.table_next ()
            n += 1
            for el in x :
                im = self.image (el)
                f.text (self.ppv.label (el))
                f.table_next ()
                f.add_image (im, zoom = zoom)
                f.table_next ()
            f.table_next_line ()
            
        f.table_end ()
        f.close ()
        
    def ppv_nuage (self, nuage, bienclasse = None, erreur = None) :
        """appelle self.nuage.ppv_nuage"""
        return self.ppv.ppv_nuage (nuage, bienclasse, erreur)
        
    def __len__ (self) :
        """retourne len (self.nuage)"""
        return len (self.ppv)
                
    def __iter__(self) :
        """retourne iter (self.nuage)"""
        return iter (self.ppv)
        
        
        
if __name__ == "__main__" :

    psyco.full ()
    
    rep_app     = "c:\\temp\\mnist\\app"
    rep_test    = "c:\\temp\\mnist\\test"
    nb_app      = 400
    nb_test     = 400
    html_file1   = "c:\\temp\\mnist\\bienclasse.html"
    html_file2   = "c:\\temp\\mnist\\erreur.html"
    
    # si les images n'existent pas
    if not os.path.exists (rep_app) or not os.path.exists (rep_test) :
        file_image  = "C:\\Downloads\\data_image\\mnist\\t10k-images.idx3-ubyte"
        file_label  = "C:\\Downloads\\data_image\\mnist\\t10k-labels.idx1-ubyte"
        os.makedirs (rep_app)
        os.makedirs (rep_test)
        binar = 220
        nbcl  = 40
        mnist.decompose_mnist (file_image, file_label, None, binar, nbcl, \
                                rep_app, rep_test)
        
    ppv1 = nuage_point_distance_label ()
    ppv2 = nuage_point_distance_label ()

    print "construction du nuage d'apprentissage"
    nuage_app = nuage_image (ppv1, rep_app, nb_app)
    print "nombre de points : ", len (nuage_app)
    
    print "construction du nuage de test"
    nuage_test = nuage_image (ppv2, rep_test, nb_test)
    print "nombre de points : ", len (nuage_test)
    
    print "résultat de la classification"
    erreur      = []
    bienclasse  = []
    temps1      = time.clock ()
    good,bad = nuage_app.ppv_nuage (nuage_test, bienclasse, erreur)
    temps2      = time.clock ()
    print "---------------------------------------------------------------------------"
    print "temps de traitement en secondes ", temps2 - temps1
    print "good, bad = ", good, bad
    print "taux de classification  : ", float (good) / (good + bad)
    print "écriture du fichier ", html_file1
    nuage_app.html_couple (html_file1, bienclasse,   zoom = 4)
    print "écriture du fichier ", html_file2
    nuage_app.html_couple (html_file2, erreur,       zoom = 4)
    


plus proches voisins LAESA

# coding: cp1252
import math
import random
import kppv


class nuage_point_laesa (kppv.nuage_points) :
    """implémente l'algorithme des plus proches voisins,
    version LAESA"""
    
    def __init__ (self) :
        """construit la classe"""
        kppv.nuage_points.__init__ (self)
        
    def selection_pivots (self,nb) :
        """sélectionne nb pivots aléatoirements"""
        nb = min (nb, len (self.nuage))
        self.pivots = []
        while len (self.pivots) < nb :
            i = random.randint (0,len (self.nuage))
            if not self.nuage [i] in self.pivots :
                self.pivots.append (self.nuage [i])
                
        # on calcule aussi la distance de chaque éléments au pivots
        self.dist = []
        for el in self.nuage :
            dl = []
            for p in self.pivots :
                d = self.distance (el, p)
                dl.append (d)
            self.dist.append (dl)                
                
    def ppv (self, obj) :
        """retourne l'élément le plus proche de obj et sa distance avec obj,
        utilise la sélection à l'aide pivots"""
        
        # initialisation
        dp  = [ self.distance (obj, p) for p in self.pivots ]
        
        # pivots le plus proche
        dm  = dp [0]
        im  = self.pivots [0] 
        for i in xrange (0, len(self.pivots)) :
            d = dp [i]
            if d < dm :
                dm = d
                im = self.pivots [i]
        
        # améliorations
        for i in xrange (0, len (self.nuage)) :
            
            # on regarde si un pivots permet d'éliminer l'élément i
            calcul = True
            for j in xrange (0, len (self.pivots)) :
                d = abs (dp [j] - self.dist[i][j])
                if d > dm :
                    calcul = False
                    break 


            # dans le cas contraire on calcule la distance
            if calcul :
                d = self.distance (obj, self.nuage [i])
                if d < dm :
                    dm = d 
                    im = self.nuage [i]
                
        return im,dm



plus proches voisins LAESA sur des images

# coding: cp1252
import os
import os.path
import mnist
import string
import PIL
import PIL.Image
import html_file as html
import psyco
import random
import kppv_laesa
import time
import kppv_image

# définit une classe héritant de kppv.nuage_points qui surcharge les 
# fonctions distance et label
class nuage_point_leasa_distance_label (kppv_laesa.nuage_point_laesa) :
    """hérite de kppv.nuage_point et surcharge les méthodes :
            - distance
            - label
    """

    def distance (self, obj1, obj2) :
        """surcharge de la fonction distance, comme les images sont toutes
        de dimensions identiques, on peut compter les pixels de couleurs différentes,
        le résultat est la distance entre deux images"""
        if len (obj1) != len (obj2) :
            print "erreur, len (obj1) != len (obj2)"
        d = 0
        for i in xrange (2, len (obj1)) :
            if obj1 [i] != obj2 [i] : d += 1
        return d
                
    def label (self, obj) :
        """retourne le label d'un objet"""
        return obj [0]
    
        
class nuage_image_leasa (kppv_image.nuage_image) :
    """nuage de points, chaque élément est une image, 
    les images sont en noir et blanc, liste de 0 ou 1"""
    
    def __init__ (self, nuage_ppv, rep, nb, extension = "tif") :
        """initialise le nuage d'images avec un répertoire
        qui est l'emplacement des images pour ce nuage, 
        le nom des images contient une chaîne de caractères suivi 
        d'un label séparés par un blanc soulignés, 
        extension est le type de images à charger,
        on ne considère que les nb premières images,
        nuage est une instance de la classe nuage_point ou nuage_point_laesa"""
                
        kppv_image.nuage_image.__init__(self, nuage_ppv, rep, nb, extension)
        self.ppv.selection_pivots (20)

        
        
        
        
if __name__ == "__main__" :

    psyco.full ()
    
    rep_app     = "c:\\temp\\mnist\\app"
    rep_test    = "c:\\temp\\mnist\\test"
    nb_app      = 400
    nb_test     = 400
    html_file1   = "c:\\temp\\mnist\\bienclasse.html"
    html_file2   = "c:\\temp\\mnist\\erreur.html"
    
    # si les images n'existent pas
    if not os.path.exists (rep_app) or not os.path.exists (rep_test) :
        file_image  = "C:\\Downloads\\data_image\\mnist\\t10k-images.idx3-ubyte"
        file_label  = "C:\\Downloads\\data_image\\mnist\\t10k-labels.idx1-ubyte"
        os.makedirs (rep_app)
        os.makedirs (rep_test)
        binar = 220
        nbcl  = 40
        mnist.decompose_mnist (file_image, file_label, None, binar, nbcl, \
                                rep_app, rep_test)
        
    ppv1 = nuage_point_leasa_distance_label ()
    ppv2 = nuage_point_leasa_distance_label ()

    print "construction du nuage d'apprentissage"
    nuage_app = nuage_image_leasa (ppv1, rep_app, nb_app)
    print "nombre de points : ", len (nuage_app)
    
    print "construction du nuage de test"
    nuage_test = nuage_image_leasa (ppv2, rep_test, nb_test)
    print "nombre de points : ", len (nuage_test)
    
    print "résultat de la classification"
    erreur      = []
    bienclasse  = []
    temps1      = time.clock ()
    good,bad = nuage_app.ppv_nuage (nuage_test, bienclasse, erreur)
    temps2      = time.clock ()
    print "---------------------------------------------------------------------------"
    print "temps de traitement en secondes ", temps2 - temps1
    print "good, bad = ", good, bad
    print "taux de classification  : ", float (good) / (good + bad)
    print "écriture du fichier ", html_file1
    nuage_app.html_couple (html_file1, bienclasse,   zoom = 4)
    print "écriture du fichier ", html_file2
    nuage_app.html_couple (html_file2, erreur,       zoom = 4)
    


to be filled later

from scipy.stats import norm

def pvalue (p, q, N) :
    theta   = abs(p-q)
    var     = p*(1-p) 
    bn      = (2*N)**0.5 * theta / var**0.5
    ret     = (1 - norm.cdf(bn))*2
    return ret

def pvalue_N (p, q, alpha) :
    theta   = abs(p-q)
    var     = p*(1-p) 
    rev     = abs(norm.ppf (alpha/2))
    N       = 2 * (rev * var**0.5 / theta)** 2
    return int(N+1)

def alphatable (ps, dps, alpha) :
    values = []
    for p in ps :
        row=[]
        for dp in dps :
            q = p+dp
            r = pvalue_N (p,q,alpha) if 1 >= q >= 0 else -1
            row.append (r)
        values.append (row)
    return values
    
def pprint(ps,dps,table, format, fileFormat = "latex") :
    text = []
    if fileFormat == "latex" :
        cc = "r" + ("|r" * len(dps))
        text.append("\\begin{tabular}{" + cc + "}")
        row  = [""] + [ r"\textbf{%1.3f}" % _ for _ in dps ]
        text.append("&".join(row) + r"\\\hline")
        for p,line in zip(ps,table) :
            row  = ["\\textbf{%1.2f}" % p] + \
                   [ format % _ if _ != -1 else ""  for _ in line ]
            text.append("&".join(row) + r"\\\hline")
        text.append("\\end{tabular}")
        return "\n".join(text)
    else :
        # TSV
        row  = [""] + [ r"%1.3f" % _ for _ in dps ]
        text.append("\t".join(row) )
        for p,line in zip(ps,table) :
            row  = ["%1.2f" % p] + \
                   [ format % _ if _ != -1 else ""  for _ in line ]
            text.append("\t".join(row) )
        return "\n".join(text)
        
        
if __name__ == "__main__" :
    print ("norm.ppf(0.025)",norm.ppf (0.025)) # -1.9599639845400545
    ps  = [0.001, 0.002] + [ 0.05*i for i in range (1,20) ]
    dps = [ -0.2, -0.1,  -0.02, -0.01, -0.002, -0.001,
             0.2,  0.1,   0.02,  0.01,  0.002,  0.001, ]
    dps.sort()
    t = alphatable (ps, dps, 0.05)
    print (pprint (ps, dps, t, "%d", "latex"))
    print (pprint (ps, dps, t, "%d", "html")) 

to be filled later

import numpy, matplotlib, random, pylab, math

def matrix_square_root(sigma) :
    eigen, vect = numpy.linalg.eig(sigma)
    dim = len(sigma)
    res = numpy.identity(dim)
    for i in range(0,dim) :
        res[i,i] = eigen[i]**0.5
    return vect * res * vect.transpose()
    
def chi2_level (alpha = 0.95) :
    N = 1000
    x = [ random.gauss(0,1) for _ in range(0,N) ]
    y = [ random.gauss(0,1) for _ in range(0,N) ]
    r = map ( lambda c : (c[0]**2+c[1]**2)**0.5, zip(x,y))
    r = list(r)
    r.sort()
    res = r [ int (alpha * N) ]
    return res
    
def square_figure(mat, a) :    
    x = [ ]
    y = [ ]
    for i in range (0,100) :
        x.append ( a * mat[0][0]**0.5 ) 
        y.append ( (random.random ()-0.5) * a * mat[1][1]**0.5*2 )
        x.append ( -a * mat[0][0]**0.5 ) 
        y.append ( (random.random ()-0.5) * a * mat[1][1]**0.5*2 )

        y.append ( a * mat[1][1]**0.5 ) 
        x.append ( (random.random ()-0.5) * a * mat[0][0]**0.5*2 )
        y.append ( -a * mat[1][1]**0.5 ) 
        x.append ( (random.random ()-0.5) * a * mat[0][0]**0.5*2 )
        
    pylab.plot(x,y, 'ro')
    
    x = [ ]
    y = [ ]
    for i in range (0,100) :
        x.append ( a ) 
        y.append ( (random.random ()-0.5) * a*2 )
        x.append ( -a ) 
        y.append ( (random.random ()-0.5) * a*2  )
        
        y.append ( a ) 
        x.append ( (random.random ()-0.5) * a*2  )
        y.append ( -a ) 
        x.append ( (random.random ()-0.5) * a*2  )
        
    xs,ys = [],[]
    for a,b in zip (x,y) :
        ar = numpy.matrix( [ [a], [b] ] ).transpose()
        we = ar * root
        xs.append ( we [0,0] )
        ys.append ( we [0,1] )
        
    pylab.plot(xs,ys, 'bo')
    pylab.show()

def circle_figure (mat, a) :
    x = [ ]
    y = [ ]
    for i in range (0,200) :
        z = random.random() * math.pi * 2
        i = a * mat[0][0]**0.5 * math.cos(z)
        j = a * mat[0][0]**0.5 * math.sin(z)
        x.append ( i )
        y.append ( j )
    pylab.plot(x,y, 'ro')
    
    x = [ ]
    y = [ ]
    for i in range (0,200) :
        z = random.random() * math.pi * 2
        i = a * math.cos(z)
        j = a * math.sin(z)
        x.append ( i )
        y.append ( j )
        
    xs,ys = [],[]
    for a,b in zip (x,y) :
        ar = numpy.matrix( [ [a], [b] ] ).transpose()
        we = ar * root
        xs.append ( we [0,0] )
        ys.append ( we [0,1] )
        
    pylab.plot(xs,ys, 'bo')
    pylab.show()

if __name__ == "__main__" :
    level = chi2_level ()

    mat   = [ [0.1, 0.05], [0.05, 0.2] ]
    npmat = numpy.matrix(mat)
    root  = matrix_square_root (npmat)

    square_figure (mat, 1.96)
    circle_figure (mat, level)

to be filled later

import random, math

def densite_gauss (mu, sigma, x) :
    e = -(x - mu)**2 / (sigma**2 * 2)
    d = 1. / ((2*math.pi)**0.5 * sigma)
    return d * math.exp (e)
    
def simulation_vector (N, mu, sigma) :
    return [ random.gauss(mu,sigma) for n in range(N) ]
    
def ratio (vector, x, fdensite) :
    under = 0
    above = 0
    fx    = fdensite(x)
    for u in vector :
        f = fdensite (u)
        if f >= fx : above += 1
        else : under += 1
    return float(above) / float (above + under)
        
if __name__ == "__main__" :
    x     = 1.96
    N     = 10000
    mu    = 0
    sigma = 1
    
    v = simulation_vector (N, mu, sigma)
    g = ratio (v, x, lambda y : densite_gauss (mu, sigma, y) )
    print (g)

tracé d'une ligne

# coding: cp1252
"""ce module contient la fonction trace_ligne qui retourne l'ensemble des pixels
concernés par le tracé d'une ligne en 8-connexité entre deux pixels"""
import pygame                 # pour les affichages
import random

def trace_ligne_simple (x1,y1,x2,y2):
    """trace une ligne entre les points de coordonnées (x1,y1) et (x2,y2),
    on suppose que x2 > x1, y2 >= y1, 
    retourne la ligne sous la forme d'un ensemble de pixels (x,y)"""
    
    if y2 - y1 <= x2 - x1 :  # droite en dessous de la première bissectrice
        vx = x2 - x1
        vy = y2 - y1
        b  = vx / 2
        y  = y1
        x  = x1
        
        ligne = []
        while x <= x2 :
            ligne.append ((x,y))
            b -= vy
            x += 1
            if b < 0:
                b += vx
                y += 1
        return ligne
    else :                   # droite au dessus de la première bissectrice
        vx = x2 - x1
        vy = y2 - y1
        b  = vy / 2
        y  = y1
        x  = x1
        
        ligne = []
        while y <= y2 :
            ligne.append ((x,y))
            b -= vx
            y += 1
            if b < 0:
                b += vy
                x += 1
        return ligne
    
def trace_ligne (x1,y1,x2,y2):
    """trace une ligne entre les points de coordonnées (x1,y1) et (x2,y2),
    aucune contrainte sur les coordonnées,
    retourne la ligne sous la forme d'un ensemble de pixels (x,y)"""
    
    if x1 == x2 :
        if y1 <= y2: return [ (x1, i) for i in xrange (y1,y2+1) ]
        else : return [ (x1, i) for i in xrange (y2,y1+1) ]
        
    if y1 == y2 :
        if x1 <= x2: return [ (i, y1) for i in xrange (x1,x2+1) ]
        else : return [ (i, y1) for i in xrange (x2,x1+1) ]
    
    if x1 < x2 :
        if y1 < y2 : 
            return trace_ligne_simple (x1,y1,x2,y2)
        else :
            ligne = trace_ligne_simple (x1,y2,x2,y1)
            return [ (x,y1 + y2 - y) for (x,y) in ligne ]
        
    if x2 < x1 :
        if y1 < y2 : 
            ligne = trace_ligne_simple (x2,y1,x1,y2)
            return [ (x1 + x2 - x, y) for (x,y) in ligne ]
        else :
            ligne = trace_ligne_simple (x2,y2,x1,y1)
            return [ (x1 + x2 - x, y1 + y2 - y) for (x,y) in ligne ]

def display_ligne (ligne, screen):
    """affiche une ligne à l'écran"""
    color = 0,0,0
    for p in ligne:
        pygame.draw.line (screen, color, p,p)
    pygame.display.flip ()
    
    
def attendre_clic (screen):
    """attend la pression d'un clic de souris pour continuer"""
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break

if __name__ == "__main__" :
    pygame.init ()
    
    size      = width, height = x,y = 200, 200
    black     = 0, 0, 0
    white     = 255,255,255
    screen    = pygame.display.set_mode(size)
    screen.fill (white)
    
    print trace_ligne (0,0, 7,3)  
    # affiche [(0, 0), (1, 0), (2, 1), (3, 1), (4, 2), (5, 2), (6, 3), (7, 3)]
    
    for n in xrange (0,10):
        x1      = random.randint (0,x-1)        
        y1      = random.randint (0,y-1)        
        x2      = random.randint (0,x-1)        
        y2      = random.randint (0,y-1)        
        ligne   = trace_ligne (x1,y1,x2,y2)
        display_ligne (ligne, screen)

    attendre_clic (screen)

tracé d'une ligne

# -*- coding: utf-8 -*-
"""ce module contient la fonction trace_ligne qui retourne l'ensemble des pixels
concernés par le tracé d'une ligne en 8-connexité entre deux pixels"""
import pygame                 # pour les affichages
import random

def trace_ligne_simple (x1,y1,x2,y2):
    """trace une ligne entre les points de coordonnées (x1,y1) et (x2,y2),
    on suppose que x2 > x1, y2 >= y1, 
    retourne la ligne sous la forme d'un ensemble de pixels (x,y)"""
    
    if y2 - y1 <= x2 - x1 :  # droite en dessous de la première bissectrice
        vx = x2 - x1
        vy = y2 - y1
        b  = vx / 2
        y  = y1
        x  = x1
        
        ligne = []
        while x <= x2 :
            ligne.append ((x,y))
            b -= vy
            if b < 0:
                b += vx
                y += 1
                ligne.append ((x,y))    # ------ ligne ajoutée
            x += 1                      # ------ ligne déplacée
        return ligne
    else :                   # droite au dessus de la première bissectrice
        vx = x2 - x1
        vy = y2 - y1
        b  = vy / 2
        y  = y1
        x  = x1
        
        ligne = []
        while y <= y2 :
            ligne.append ((x,y))
            b -= vx
            if b < 0:
                b += vy
                x += 1
                ligne.append ((x,y))   # ------ ligne ajoutée
            y += 1                     # ------ ligne déplacée
        return ligne
    
def trace_ligne (x1,y1,x2,y2):
    """trace une ligne entre les points de coordonnées (x1,y1) et (x2,y2),
    aucune contrainte sur les coordonnées,
    retourne la ligne sous la forme d'un ensemble de pixels (x,y)"""
    
    if x1 == x2 :
        if y1 <= y2: return [ (x1, i) for i in xrange (y1,y2+1) ]
        else : return [ (x1, i) for i in xrange (y2,y1+1) ]
        
    if y1 == y2 :
        if x1 <= x2: return [ (i, y1) for i in xrange (x1,x2+1) ]
        else : return [ (i, y1) for i in xrange (x2,x1+1) ]
    
    if x1 < x2 :
        if y1 < y2 : 
            return trace_ligne_simple (x1,y1,x2,y2)
        else :
            ligne = trace_ligne_simple (x1,y2,x2,y1)
            return [ (x,y1 + y2 - y) for (x,y) in ligne ]
        
    if x2 < x1 :
        if y1 < y2 : 
            ligne = trace_ligne_simple (x2,y1,x1,y2)
            return [ (x1 + x2 - x, y) for (x,y) in ligne ]
        else :
            ligne = trace_ligne_simple (x2,y2,x1,y1)
            return [ (x1 + x2 - x, y1 + y2 - y) for (x,y) in ligne ]

def display_ligne (ligne, screen):
    """affiche une ligne à l'écran"""
    color = 0,0,0
    for p in ligne:
        pygame.draw.line (screen, color, p,p)
    pygame.display.flip ()
    
    
def attendre_clic (screen):
    """attend la pression d'un clic de souris pour continuer"""
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break

if __name__ == "__main__" :
    pygame.init ()
    
    size      = width, height = x,y = 200, 200
    black     = 0, 0, 0
    white     = 255,255,255
    screen    = pygame.display.set_mode(size)
    screen.fill (white)
    
    print trace_ligne (0,0, 7,3)  
    # affiche [(0, 0), (1, 0), (1, 1), (2, 1), (3, 1), 
    #          (3, 2), (4, 2), (5, 2), (5, 3), (6, 3), (7, 3)]
    # rappel : résultat en 8-connexité : 
    # [(0, 0), (1, 0), (2, 1), (3, 1), (4, 2), (5, 2), (6, 3), (7, 3)]
    
    for n in xrange (0,10):
        x1      = random.randint (0,x-1)        
        y1      = random.randint (0,y-1)        
        x2      = random.randint (0,x-1)        
        y2      = random.randint (0,y-1)        
        ligne   = trace_ligne (x1,y1,x2,y2)
        display_ligne (ligne, screen)

    attendre_clic (screen)

tracé d'une ellipse

# coding: cp1252
"""ce module contient la fonction trace_ellipse qui retourne l'ensemble des pixels
concernés par le tracé d'une ellipse en 8-connexité"""
import pygame                 # pour les affichages
import random
import math

def trace_ellipse (xc,yc,a,b):
    """dessine une ellipse de centre xc,yc, de demi axe horizontal a, 
    de demi-axe vertical b, l'ellipse a pour équation x²/a² + y²/b² = 1 
    si l'origine est placée en xc,yc,
    l'équation de la tangente au point x0, y0 est :  x x0 / a² + y y0 / b² = 0,
    ou x x0 b² + y y0 a² = 0"""
    
    # on évite les cas litigieux
    if a == 0 :
        return [ (xc, yc + y) for y in xrange (-b,b) ]
    if b == 0 :
        return [ (xc + x, yc) for x in xrange (-a,a) ]
    
    bb = b * b
    aa = a * a
    
    # on trace l'ellipse de centre 0,0
    ellipse = []
    # premier huitième
    vx = a * bb
    vy = 0
    x  = a
    y  = 0
    bl = vx / 2
    
    while vx >= vy and x >= 0 :
        ellipse.append ((x,y))
        y  += 1
        vy += aa        # vy  = y * aa
        bl -= vy
        if bl < 0 :
            x  -= 1
            vx -= bb    # vx  = x * bb
            bl += vx
            
    # second huitième
    while x >= 0 :
        ellipse.append ((x,y))
        x  -= 1
        vx -= bb        # vx  = x * bb
        bl += vx
        if bl > 0 :
            y  += 1
            vy += aa    # vy  = y * aa
            bl -= vy
            
    # second quart, symétrique par rapport à l'axe des ordonnées
    ellipse2 = [ (-x,y) for (x,y) in ellipse ]
    ellipse2.reverse ()
    ellipse.extend (ellipse2)
    
    # troisième et quatrième quarts : symétrique par rapport à l'axe des abscisse
    ellipse2 = [ (x,-y) for (x,y) in ellipse ]
    ellipse2.reverse ()
    ellipse.extend (ellipse2)
    
    return [ (x + xc, y + yc) for (x,y) in ellipse ]
    
def display_ligne (ensemble, screen):
    """affiche un ensemble de pixels à l'écran"""
    color = 0,0,0
    for p in ensemble:
        pygame.draw.line (screen, color, p,p)
    pygame.display.flip ()
    
def attendre_clic (screen):
    """attend la pression d'un clic de souris pour continuer"""
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break

if __name__ == "__main__" :
    pygame.init ()
    
    size      = width, height = x,y = 300, 300
    black     = 0, 0, 0
    white     = 255,255,255
    screen    = pygame.display.set_mode(size)
    screen.fill (white)
    
    print trace_ellipse (0,0,6,6)  
    # pour le premier quart, affiche
    # [(6, 0), (6, 1), (6, 2), (5, 3), (4, 4), (3, 5), (2, 6), (1, 6), (0, 6), ...
    
    for n in xrange (0,10):
        x1      = random.randint (0,x-1)        
        y1      = random.randint (0,y-1)        
        x2      = random.randint (0,x-1)        
        y2      = random.randint (0,y-1)        
        xc,yc   = (x1 + x2) / 2 , (y1 + y2) / 2
        a,b     = abs (x2 - x1) / 2 , abs (y2 - y1) / 2
        ell     = trace_ellipse (xc,yc,a,b)
        display_ligne (ell, screen)

    attendre_clic (screen)

File: portrait.tex, line 52


gamma     = 9    # paramètre gamma
park      = 30   # paramètre k, pas trop petit pour commencer, 
                 # de plus en plus petit par la suite (jusqu'à 3)

# chargement d'une image
image     = pygame.image.load("bette_davis.png") 
size      = image.get_size ()
xx,yy     = size [0], size [1]
X,Y       = int (xx // park) + 1, int (yy // park) + 1

# à cet endroit, il faut déterminer l'emplacement des villes
# en utilisant l'image, la fonction construit_ville
# du programme initial doit être réécrite
villes    =  construit_ville (image, gamma, park)
        
# les lignes qui suivent décrivent la séquence à écrire pour 
# obtenir le plus court chemin passant pour toutes les villes        
arbre     = arbre_poids_minimal (villes,park)
chemin    = circuit_eulerien (villes ,arbre)
neurone   = circuit_hamiltonien (chemin)
neurones  = [ villes [i] for i in neurone ]
amelioration_chemin (neurones, park, X,Y, 6, screen)

algorithme de Kruskal

# coding: cp1252
import random                 # pour tirer aléatoirement des nombres
import math                   # fonctions cos, sin
import pygame                 # pour les affichages
import copy
import bresenham_ligne4 as brl  # pour dessiner des lignes
import psyco                  # pour accélérer le programme

def attendre_clic (screen,x,y):
    """dessine une croix sur l'écran et attend la pression d'un clic de souris"""
    color   = 0,0,0
    pygame.draw.line (screen, color, (0,0), (x-1,y-1))
    pygame.draw.line (screen, color, (x-1,0), (0,y-1))
    pygame.display.flip ()
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break
                
def ajuste_image (image, park):
    """arrondi les dimensions d'une images à park, retourne une partie de l'image"""
    x,y = image.get_size ()
    x = (x // park) * park
    y = (y // park) * park
    image2 = image.subsurface (((0,0),(x,y)))
    image3 = image2.copy ()
    return image3

def construit_ville(image, gamma, park):
    """tire aléatoirement des villes, 
    ces villes sont d'autant plus nombreuses que l'intensité de l'image
    est faible, évite les villes confondues"""
    x,y = image.get_size ()
    nbx = x // park
    nby = y // park
    
    villes = []
    for i in xrange(0,nbx):
        for j in xrange(0,nby):
            x1 = i * park
            x2 = (i+1) * park
            y1 = j * park
            y2 = (j+1) * park
            
            # calcul de l'obscurité moyenne
            moy = 0
            for k in xrange(x1,x2):
                for l in xrange(y1,y2):
                    int = image.get_at ((k,l))
                    moy += int [0] + int [1] + int [2]
            moy /= park * park * 3
            
            # nombre de villes
            nbv = gamma - gamma * moy / 256
            pl  = []
            
            for k in xrange(0,nbv):
                xx = random.randint (x1,x2-1)
                yy = random.randint (y1,y2-1)
                if (xx,yy) not in pl :
                    villes.append ((xx,yy))
                    pl.append ((xx,yy))
                
    return villes

def display_ville(villes,screen):
    """dessine les villes à l'écran"""
    color  = 0,0,0
    for v in villes:
        pygame.draw.line (screen, color, v, v)


def display_neurone(neurones_,screen,mult = 1):
    """dessine les neurones à l'écran"""
    color       = 0,0,0
    color2      = 0,255,0
    if mult != 1 :
        neurones    = [ (n [0] * mult, n [1] * mult ) for n in neurones_ ]
        if mult == 2 : l = 1
        else : l = 1
        for n in neurones :
            pygame.draw.line (screen, color, n, n)
        #pygame.draw.circle (screen, color2, neurones [0], 8)
        if len (neurones) > 1 :
            color3 = 150,0,0
            #pygame.draw.circle (screen, color3, neurones [1], 6)
        if len (neurones) > 1:
            pygame.draw.lines (screen, color, True, neurones, l)
    else :
        neurones    = [ (n [0] * mult, n [1] * mult ) for n in neurones_ ]
        if mult == 2 : l = 1
        else : l = 1
        for n in neurones_ :
            pygame.draw.line (screen, color, n, n)
        #pygame.draw.circle (screen, color2, neurones [0], 8)
        if len (neurones_) > 1 :
            color3 = 150,0,0
            #pygame.draw.circle (screen, color3, neurones [1], 6)
        if len (neurones_) > 1:
            pygame.draw.lines (screen, color, True, neurones_, l)
        
def display_arbre (villes, arbre, mult = 1):
    """dessine le graphe de poids minimal défini par arbre"""
    if mult == 2 : 
        color = 0,255,0
        l = 4
    else :
        l = 1
        color = 0,0,255
    
    for i in xrange (0, len (villes)):
        for j in arbre [i]:
            v  = (villes [i][0] * mult, villes [i][1] * mult)
            vv = (villes [j][0] * mult, villes [j][1] * mult)
            pygame.draw.line (screen, color, v, vv, l)


def repartition_zone (villes, zone_taille, ask_zone = False) :
    """répartit les villes en zones, retourne les villes rangées par zones,
    chaque éléments zones [z][k] contient : 
        - les coordonnées de la ville
        - ses coordonnées en zone, (zx, zy)
        - son indice dans la liste villes
    la fonction retourne également le nombre de zones 
    selon l'axe des abscisses et l'axe des ordonnées,
    retourne aussi le nombre de zones, si ask_zone est True, 
    retourne un paramètre supplémentaire : zone"""
    print "gestion des zones"
    X,Y = 0,0
    for v in villes:
        X = max (v [0] // zone_taille, X)
        Y = max (v [1] // zone_taille, Y)
    X += 1        
    Y += 1
        
    # attribution des zones
    zone    = []
    nb      = len (villes)
    Zmax    = 0
    for i in xrange (0,len (villes)):
        v       = villes [i]
        x       = int (v [0] // zone_taille)
        y       = int (v [1] // zone_taille)
        z       = int (y * X + x)
        Zmax    = max (z,Zmax)
        zone.append ((z, v, (x,y), i))
        
    # rangement par zone
    Zmax   += 1
    zones = [ [] for i in xrange (0,Zmax) ]
    for z in zone:
        zones [ z [0] ].append ((z [1], z [2], z [3]))
        
    if ask_zone :
        return zones,X,Y,Zmax,zone
    else :
        return zones,X,Y,Zmax
    
def voisinage_zone (z,Zmax,X,Y):
    """retourne la liste des voisins d'une zone z 
    sachant qu'il y a X zones sur l'axe des abscisses et Y zones sur l'axe des ordonnées,
    Zmax est le nombre de zones,
    inclus z dans cette liste"""
    x       = z % X
    y       = z // X
    voisin_ = [z]
    if x > 0: voisin_.append (z-1)
    if x < X: voisin_.append (z+1)
    if y > 0: voisin_.append (z-X)
    if y < Y: voisin_.append (z+X)
    if x > 0 and y > 0 : voisin_.append (z-1-X)
    if x > 0 and y < Y : voisin_.append (z-1+X)
    if x < X and y > 0 : voisin_.append (z+1-X)
    if x < X and y < Y : voisin_.append (z+1+X)
    voisin = [ int (i) for i in voisin_ if i >= 0 and i < Zmax ]
    return voisin

def distance (p1,p2):
    """calcule la distance entre deux villes"""
    x = p1 [0] - p2[0]
    y = p1 [1] - p2[1]
    return math.sqrt (x*x + y*y)

def arbre_poids_minimal(villes, zone_taille):
    """construit l'arbre de poids minimal, retourne une liste de 
    listes, chaque sous-liste associée à une ville contient la liste des ses voisins,
    zone_taille permet de découper l'image en zones, 
    les distances ne seront calculées que si 
    deux éléments sont dans la même zone ou dans une zone voisine"""
    
    def tri_distance (u,v):
        if u [2] < v [2] : return -1
        elif u [2] > v [2] : return 1
        else : return 0
        
    zones,X,Y,Zmax = repartition_zone (villes, zone_taille)

    # calcul des distances
    print "calcul des distances"
    li      = []

    for z in xrange (0,len (zones)):
        if z % 1000 == 0 : print "zone ", z, len(zones)
        voisin  = voisinage_zone (z,Zmax,X,Y)
        for v in zones [z]:
            for zz in voisin:
                for u in zones [zz]:
                    d = distance (v [0], u [0])
                    li.append ((v [2], u [2], d))
    
    print "tri ", len(li)
    li.sort (tri_distance)    
    
    # composantes connexes
    print "construction de l'arbre"
    
    # nombre de composantes connexes
    nb_comp     = len (villes)                            
    
    # indice de la composante d'une ville
    num_comp    = [ i for i in xrange(0,len(villes)) ]   
    
    # liste des voisins pour chaque ville
    arbre       = [ [] for i in xrange(0,len(villes)) ]  
    
    # liste des villes par composante connexe
    list_comp   = [ [i] for i in xrange(0,len(villes)) ] 
 
    iii = 0 
    for c in li:
        if iii % 10000 == 0 : print "arête ", iii, len(li)
        iii += 1
        i,j = c [0], c [1]
        if num_comp [i] != num_comp [j]:
            # on relie les villes i et j car elles appartiennent 
            # à des composantes connexes différentes
            arbre [i].append (j)        # i est voisine de j
            arbre [j].append (i)        # j est voisine de i
            cl = num_comp [i]           # composante connexe restante
            ki = num_comp [j]           # composante connexe à aggréger à la précédente
            for k in list_comp [ki]: 
                num_comp [k] = cl
                list_comp [cl].append (k)
            list_comp [ki] = []
            nb_comp -= 1                # une composante connexe en moins
        
        if nb_comp == 0: 
            break  # il n'y a plus qu'une seule composante connexe, inutile de continuer
    
    return arbre
    
def vecteur_points (p1,p2):
    """retourne le vecteur entre les points p1 et p2"""
    return ( p2 [0] - p1 [0], p2 [1] - p1 [1])
    
def vecteur_norme (vec):
    """retourne la norme d'un vecteur"""
    return math.sqrt (vec [0] * vec [0] + vec [1] * vec [1])
    
def vecteur_cosinus (vec1, vec2):
    """retourne le cosinus entre deux vecteurs, utilise le produit scalaire"""
    norm1 = vecteur_norme (vec1)
    norm2 = vecteur_norme (vec2)
    if norm1 == 0: return 1
    if norm2 == 0: return 1
    scal  = vec1 [0] * vec2 [0] + vec1 [1] * vec2 [1]
    return scal / (norm1 * norm2)

def vecteur_sinus (vec1, vec2):
    """retourne le sinus entre deux vecteurs, utilise le produit vectoriel"""
    norm1 = vecteur_norme (vec1)
    norm2 = vecteur_norme (vec2)
    if norm1 == 0:  return 0
    if norm2 == 0:  return 0
    scal  = vec1 [0] * vec2 [1] - vec1 [1] * vec2 [0]
    return scal / (norm1 * norm2)
    
def oppose_vecteur (vec):
    """retourne le vecteur opposé"""
    return (- vec [0], - vec [1])
    
def circuit_eulerien (villes, arbre):
    """définit un circuit eulérien, villes contient la liste des villes,
    tandis que arbre est une liste de listes, arbre [i] est la liste des villes
    connectées à la ville i, 
    on suppose que arbre est un graphe de poids minimal non orienté,
    l'algorithme ne marche pas s'il existe des villes confondues"""
    
    # on choisit une ville qui est une extrémité et parmi celle-là on la choisit au hasard
    has = []
    for i in xrange (0,len (villes)):
        n = len (arbre [i])
        if n == 1: has.append (i)

    bm = random.randint (0, len (has) -1)
    bm = has [bm]
        
    # vecteur, le circuit eulérien contient 
    # nécessairement 2 * len (villes) noeuds puisque c'est
    # le graphe eulérien d'un arbre de poids minimal non orienté
    vec     = (1,1)
    chemin  = [bm]
    while len (chemin) < 2 * len (villes)-1 :
        
        v = villes [bm]
        
        ma      = - math.pi - 1
        bvec    = vec 
        opvec   = oppose_vecteur (vec)
        for k in xrange (0, len (arbre [bm])) :
            l     = arbre [bm][k]
            vec2  = vecteur_points (v, villes [l])
            if opvec == vec2 :
                angle = -math.pi
            else :
                cos   = vecteur_cosinus (vec, vec2)
                sin   = vecteur_sinus   (vec, vec2)
                angle = math.atan2 (sin, cos)
            if angle > ma :
                ma      = angle
                bl      = k
                bvec    = vec2
                
        b   = arbre [bm][bl]
        chemin.append (b)
        del arbre [bm][bl]  # on supprime l'arc pour ne plus l'utiliser
        bm  = b
        vec = bvec
        
    return chemin

def circuit_hamiltonien (chemin):
    """extrait un circuit hamiltonien depuis un circuit eurlérien"""
    nb      = max (chemin) + 1
    res     = []
    coche   = [ False for i in xrange (0, nb) ]
    for c in chemin :
        if coche [c] : continue 
        res.append (c)
        coche [c] = True
        
    return res

def equation_droite (p1,p2) :
    """retourne l'équation d'une droite passant par p1 et p2,
    ax + by + c = 0, retourne les coefficients a,b,c"""
    vec = vecteur_points (p1,p2)
    a = vec [1]
    b = - vec [0]
    c = - a * p1 [0] - b * p1 [1]
    return a,b,c
    
def evaluation_droite (a,b,c,p):
    """l'équation d'une droite est : ax + by + c, retourne la valeur
    de cette expression au point p"""
    return a * p [0] + b * p [1] + c

def intersection_segment (p1,p2,p3,p4):
    """dit si les segments [p1 p2] et [p3 p4] ont une intersection, 
    ne retourne pas l'intersection"""
    # équation de la droite (p1 p2)
    a1,b1,c1 = equation_droite (p1,p2)
    a2,b2,c2 = equation_droite (p3,p4)
    s1 = evaluation_droite (a2,b2,c2,p1)
    s2 = evaluation_droite (a2,b2,c2,p2)
    s3 = evaluation_droite (a1,b1,c1,p3)
    s4 = evaluation_droite (a1,b1,c1,p4)
    if s1 * s2 <= 0 and s3 * s4 <= 0 : return True
    else : return False 
    
def longueur_chemin (chemin):
    """retourne la longueur d'un chemin"""
    s   = 0
    nb  = len (chemin)
    for i in xrange (0,nb) :
        s += distance ( chemin [i], chemin [ (i+1) % nb ])
    return s
    
def retournement_essai (chemin, i,j, negligeable = 1e-5):
    """dit s'il est judicieux de parcourir le chemin entre les sommets i et j
    en sens inverse, si c'est judicieux, change le chemin et retourne True,
    sinon, retourne False, 
    si j < i, alors la partie à inverser est 
    i, i+1, i+2, ..., len(chemin) -1, 0, 1, ..., j"""
    
    nb = len (chemin)
    if i == j : return False
    if j - i == -1 : return False
    if j - i - nb == -1 : return False
    
    ia = (i - 1 + nb) % nb
    ja = (j + 1 ) % nb
    # arcs enlevés
    d_ia_i = distance (chemin [ia], chemin [i])
    d_j_ja = distance (chemin [j],  chemin [ja])
    # arcs ajoutés
    d_ia_j = distance (chemin [ia], chemin [j])
    d_i_ja = distance (chemin [i],  chemin [ja])
    # amélioration ?
    d = d_ia_j + d_i_ja - d_j_ja - d_ia_i 
    if d >= - negligeable : return False
        
    # si amélioration, il faut retourner le chemin entre les indices i et j
    jp = j
    if jp < i : jp = j + nb
    ip = i
    
    while ip < jp :
        i           = ip % nb 
        j           = jp % nb  
        ech         = chemin [i]
        chemin [i]  = chemin [j]
        chemin [j]  = ech
        ip = ip+1
        jp = jp-1
    
    return True
    
def retournement (chemin, taille) :
    """amélioration du chemin par un algorithme simple, 
    utilise des retournements de taille au plus <taille>,
    retourne le nombre de modifications"""
    
    # traitement des petits retournements
    nb = len (chemin)
    nb_change = 1
    nbtout    = 0
    retour      = { }
    while nb_change > 0 :
        nb_change   = 0
        for t in xrange (1,taille+1):
            retour [t] = 0
            for i in xrange (0, nb) :
                j = (i + t) % nb
                b = retournement_essai (chemin, i, j)
                if b : 
                    retour [t] += 1
                    nb_change  += 1
        nbtout += nb_change
    print "nombre de retournements %d longueur : \t %10.0f détail \t" \
                % (nbtout, longueur_chemin (chemin)), " détail : ", retour
    return nbtout
    
def echange_position_essai (chemin, a,b, x, inversion, negligeable = 1e-5):
    """échange la place des villes ka à kb pour les placer entre les villes i et i+1,
    si inversion est True, on inverse également le chemin inséré, si inversion est False,
    on ne l'inverse pas,
    si cela améliore, déplace les villes et retourne True, sinon, retourne False"""
    
    nb = len(chemin)
    xa = (x + 1) % nb
    ka = (a - 1 + nb) % nb
    kb = (b + 1 ) % nb
    
    if not inversion :
    
        if x == ka : return False
        if x == kb : return False
        if xa == ka : return False
        if b < a :
            if a <= x <= b + nb : return False
        elif a <= x <= b : return False
        if b < a :
            if a <= x + nb <= b + nb : return False
        elif a <= x + nb <= b : return False
            
        # arcs enlevés
        d_x_xa = distance (chemin [x],  chemin [xa])
        d_ka_a = distance (chemin [ka], chemin [a])
        d_b_kb = distance (chemin [b],  chemin [kb])
        # arcs ajoutés
        d_ka_kb = distance (chemin [ka], chemin [kb])
        d_x_a   = distance (chemin [x],  chemin [a])
        d_b_xa  = distance (chemin [b],  chemin [xa])
        
        d = d_ka_kb + d_x_a + d_b_xa - d_x_xa - d_ka_a - d_b_kb 
        if d >= -negligeable : return False
    
        # villes à déplacer
        ech = []
        bp = b
        if bp < a : bp = b + nb
        for i in xrange (a,bp+1):
            ech.append (chemin [i % nb] )
        diff = bp - a + 1
        
        xp = x
        if xp < b : xp += nb
        
        for l in xrange (b+1,xp+1) :
            ll              = l % nb
            bp              = (a + l - b-1) % nb
            chemin [bp]     = chemin [ll]
            
        for l in xrange (0,len(ech)) :
            chemin [ (x+l-diff+1 + nb) % nb ] = ech [l]
            
        return True
        
    else :

        if x == ka : return False
        if x == kb : return False
        if xa == ka : return False
        if b < a :
            if a <= x <= b + nb : return False
        elif a <= x <= b : return False
        if b < a :
            if a <= x + nb <= b + nb : return False
        elif a <= x + nb <= b : return False
        
            
        # arcs enlevés
        d_x_xa = distance (chemin [x],  chemin [xa])
        d_ka_a = distance (chemin [ka], chemin [a])
        d_b_kb = distance (chemin [b],  chemin [kb])
        # arcs ajoutés
        d_ka_kb = distance (chemin [ka], chemin [kb])
        d_x_b   = distance (chemin [x],  chemin [b])
        d_a_xa  = distance (chemin [a],  chemin [xa])
        
        d = d_ka_kb + d_x_b + d_a_xa - d_x_xa - d_ka_a - d_b_kb 
        if d >= -negligeable  : return False
    
        # villes à déplacer
        ech = []
        bp = b
        if bp < a : bp = b + nb
        for i in xrange (a,bp+1):
            ech.append (chemin [i % nb] )
        ech.reverse ()
        diff = bp - a + 1

        cop = copy.copy (chemin)
        
        xp = x
        if xp < b : xp += nb
        
        for l in xrange (b+1,xp+1) :
            ll              = l % nb
            bp              = (a + l - b-1) % nb
            chemin [bp]     = chemin [ll]
            
        for l in xrange (0,len(ech)) :
            chemin [ (x+l-diff+1 + nb) % nb ] = ech [l]
            
        return True
        
def dessin_arete_zone (chemin, taille_zone, X,Y):
    """retourne une liste de listes de listes, 
    res [i][j] est une liste des arêtes passant près de la zone (x,y) = [i][j], 
    si k in res [i][j], alors l'arête k,k+1 est dans la zone (i,j),
    X est le nombre de zones horizontalement, Y est le nombre de zones verticalement,
    taille_zone est la longueur du côté du carré d'une zone"""
    res = [ [ [] for j in xrange (0,Y+1) ]  for i in xrange (0,X+1) ]
    nb = len (chemin)
    for i in xrange (0,nb):
        a       = chemin [i]
        b       = chemin [(i+1) % nb]
        x1,x2   = int (a [0] // taille_zone), int (b [0] // taille_zone)
        y1,y2   = int (a [1] // taille_zone), int (b [1] // taille_zone)
        line = brl.trace_ligne (x1,y1,x2,y2)
        for x,y in line:
            res [x][y].append (i)
    return res
    
def voisinage_zone_xy (x,y,X,Y):
    """retourne la liste des voisins d'une zone (x,y) 
    sachant qu'il y a X zones sur l'axe des abscisses et Y zones sur l'axe des ordonnées,
    inclus z dans cette liste"""
    voisin = [(x,y)]
    if x > 0   : voisin.append ((x-1,y))
    if x < X-1 : voisin.append ((x+1,y))
    if y > 0   : voisin.append ((x,y-1))
    if y < Y-1 : voisin.append ((x,y+1))
    if x > 0   and y > 0   : voisin.append ((x-1,y-1))
    if x > 0   and y < Y-1 : voisin.append ((x-1,y+1))
    if x < X-1 and y > 0   : voisin.append ((x+1,y-1))
    if x < X-1 and y < Y-1 : voisin.append ((x+1,y+1))
    return voisin    
    
def echange_position (chemin, taille, taille_zone, X,Y, grande = 0.5) :
    """regarde si on ne peut pas déplacer un segment de longueur taille 
    pour supprimer les arêtes les plus longues,
    au maximum <grande> longues arêtes,
    retourne le nombre de changement effectués,
    X est le nombre de zones horizontalement,
    Y est le nombre de zones verticalement,
    taille_zone est la longueur d'un côté du carré d'une zone"""
    
    nb = len(chemin)

    def tri_arete (x,y):
        """pour trier la liste l par ordre décroissant"""
        if x [2] < y [2] : return 1
        elif x [2] > y [2] : return -1
        else : return 0
            
    # list des arêtes triés par ordre décroissant
    la = []
    for i in xrange (0,nb) :
        im = (i+1) % nb
        la.append ( (i, im, distance (chemin [i], chemin [im]) ) )
    la.sort (tri_arete)
    
    # zone associé à chaque arête
    zone = dessin_arete_zone (chemin, taille_zone, X, Y)

    dseuil    = la [ int (nb * grande) ] [ 2 ]
    nbtout    = 0
    nb_change = 0
    iarete    = 0
    retour    = { }
    for t in xrange (1, taille+1): retour [t] = 0
        
    while iarete < nb :
        nb_change   = 0
        arete       = la [iarete]
        iarete     += 1
        x           = arete [0]
        xm          = arete [1]
        a           = chemin [x]
        b           = chemin [xm]
        d           = distance ( a,b )
        if d < dseuil : break    # arête trop petite
            
        # zone traversée par la ligne
        x1,x2   = int (a [0] // taille_zone), int (b [0] // taille_zone)
        y1,y2   = int (a [1] // taille_zone), int (b [1] // taille_zone)
        ens     = brl.trace_ligne (x1,y1,x2,y2)
        ville   = []
        for k,l in ens:
            voisin = voisinage_zone_xy (k,l,X,Y)
            for u,v in voisin :
                ville.extend (zone [u][v])
                
        # on supprime les doubles
        ville.sort ()
        if len (ville) == 0 : continue 
        sup = []
        mx = -1
        for v in ville:
            if v == mx : sup.append (v)
            mx = v
        for s in sup:
            ville.remove (s)

        # on étudie les possibilités de casser l'arête (x,xm) aux alentours des villes 
        # comprise dans l'ensemble ville
        for t in xrange (1, taille+1):

            for i in ville:

                # on essaye d'insérer le sous-chemin (x- t + 1 + nb)  --> x
                # au milieu de l'arête i,i+1
                b = echange_position_essai (chemin, (x- t + 1 + nb) % nb,x, i, False)
                if b : 
                    nb_change  += 1
                    retour [t] += 1
                    continue
                    
                # on essaye d'insérer le sous-chemin (xm+ t - 1)  --> xm
                # au milieu de l'arête i,i+1
                b = echange_position_essai (chemin, (xm + t - 1) % nb, xm, i, False)
                if b : 
                    nb_change  += 1
                    retour [t] += 1
                    continue

                # on essaye de casser l'arête x,xm en insérant 
                # le sous-chemin i --> (i+t) % nb
                b = echange_position_essai (chemin, i, (i+t) % nb, x, False)
                if b : 
                    nb_change  += 1
                    retour [t] += 1
                    continue
                # idem
                b = echange_position_essai (chemin, i, (i+t) % nb, x, True)
                if b : 
                    retour [t] += 1
                    nb_change  += 1
                    continue
                # idem
                b = echange_position_essai (chemin, (i-t+nb) % nb, i, x, False)
                if b : 
                    nb_change  += 1
                    retour [t] += 1
                    continue
                # idem
                b = echange_position_essai (chemin, (i-t + nb) % nb, i, x, True)
                if b : 
                    retour [t] += 1
                    nb_change  += 1
                    continue
                    
        nbtout += nb_change
        
    print "nombre de déplacements %d longueur :   \t %10.0f détail \t" \
                    % (nbtout, longueur_chemin (chemin)), " détail : ", retour
    return nbtout

def supprime_croisement (chemin, taille_zone, X,Y) :
    """supprime les croisements d'arêtes,
    retourne le nombre de changement effectués,
    X est le nombre de zones horizontalement,
    Y est le nombre de zones verticalement,
    taille_zone est la longueur d'un côté du carré d'une zone"""
    
    nb = len(chemin)
    
    # zone associé à chaque arête
    zone    = dessin_arete_zone (chemin, taille_zone, X, Y)
    nbtout  = 0 

    for i in xrange (0,nb) :
        im      = (i+1) % nb
        a       = chemin [i]
        b       = chemin [im]
        
        # zone traversée par la ligne
        x1,x2   = int (a [0] // taille_zone), int (b [0] // taille_zone)
        y1,y2   = int (a [1] // taille_zone), int (b [1] // taille_zone)
        ens     = brl.trace_ligne (x1,y1,x2,y2)
        ville   = []
        for k,l in ens:
            voisin = voisinage_zone_xy (k,l,X,Y)
            for u,v in voisin :
                ville.extend (zone [u][v])
                
        # on supprime les doubles
        ville.sort ()
        if len (ville) == 0 : continue 
        sup = []
        mx = -1
        for v in ville:
            if v == mx : sup.append (v)
            mx = v
        for s in sup:
            ville.remove (s)
            
        nb_change = 0
        for v in ville :
            b = retournement_essai (chemin, i,v) 
            if b :
                nb_change += 1
                continue
            b = retournement_essai (chemin, im,v) 
            if b :
                nb_change += 1
                continue

        nbtout += nb_change
        
    print "nombre de croisements %d longueur :      \t %10.0f détail \t" \
                    % (nbtout, longueur_chemin (chemin))
    return nbtout
    
def amelioration_chemin (chemin, taille_zone, X, Y, taille = 10, \
                            screen = None, image = None):
    """amélioration du chemin par un algorithme simple, 
    utilise des retournements de taille au plus taille,
    traite les arcs qui se croisent,
    traite les grands arcs, utilise un quadrillage de taille window,
    X est le nombre de zones horizontalement,
    Y est le nombre de zones verticalement,
    taille_zone est la longueur d'un côté du carré d'une zone"""

    white = 255,255,255

    #première étape rapide
    nb = 1
    while nb > 0:
        nb  = retournement (chemin, taille)
        if screen != None:
            screen.fill (white)
            display_neurone(chemin, screen, 1)
            pygame.display.flip ()
        
    # amélioration
    nb      = 1
    size    = image.get_size ()
    dec     = size [0]
    fin     = False
    while nb > 0 and not fin :
        nb  = retournement (chemin, taille)
        if screen != None:
            screen.fill (white)
            if image != None : screen.blit (image, (dec,0))
            display_neurone(chemin, screen)
            pygame.display.flip ()
        nb += echange_position (chemin, taille / 2, taille_zone, X, Y)
        if screen != None:
            screen.fill (white)
            if image != None : screen.blit (image, (dec,0))
            display_neurone(chemin, screen)
            pygame.display.flip ()
        nb += supprime_croisement (chemin, taille_zone,X,Y)
        if screen != None:
            screen.fill (white)
            if image != None : screen.blit (image, (dec,0))
            display_neurone(chemin, screen)
            pygame.display.flip ()
            
        if screen != None :
            for event in pygame.event.get():
                if event.type == pygame.MOUSEBUTTONUP :
                    print "attendre.............................................."
                    attendre_clic (screen,0,0)
                    print "reprise"
                    break
                if event.type == pygame.KEYDOWN and event.key == 27 :
                    # si la touche ECHAP est pressée, l'optimisation s'arrête
                    print "..............arrêter l'optimisation"
                    fin = True
                    break
                
    
################################################################################

if __name__ == "__main__" :
    pygame.init ()
    psyco.full ()
    
    gamma     = 4
    park      = 3
    
    image2 = pygame.image.load("bette_davis.png")
    image = ajuste_image (image2, park)
    
    size      = image.get_size ()
    xx,yy     = size [0], size [1]
    X,Y       = int (xx // park) + 1, int (yy // park) + 1
    dec       = size [0]
    size      = (size [0] * 2, size [1])
    size      = width, height = x,y = size
    black     = 0, 0, 0
    white     = 255,255,255
    screen    = pygame.display.set_mode(size)
    villes    = construit_ville (image, gamma, park)
    
    print "taille de l'image : ", size
    print "nombre de villes : ", len(villes)
    
    screen.fill (white)
    screen.blit (image, (dec,0))
    display_ville (villes, screen)
    pygame.display.flip ()
        
    print "calcul"
    arbre = arbre_poids_minimal (villes,park)
    arbre2 = copy.deepcopy (arbre)
    
    print "dessin"
    display_arbre (villes, arbre)
    attendre_clic(screen,0,0)
    
    print "circuit eulérien"
    chemin = circuit_eulerien (villes ,arbre)
    
    print "circuit hamiltonien"
    neurone = circuit_hamiltonien (chemin)
    
    print "dessin"
    neurones = [ villes [i] for i in neurone ]
    display_neurone(neurones, screen)
    attendre_clic(screen,0,0)
    
    print "amélioration"
    amelioration_chemin (neurones, park, X,Y, 6, screen, image)
    attendre_clic(screen,0,0)
    
    # taille double
    print "taille double"
    size      = (size [0], size [1]*2)
    screen    = pygame.display.set_mode(size)
    screen.fill (white)
    #display_arbre (villes, arbre2, 2)
    display_neurone (neurones, screen, 2)
    attendre_clic(screen,0,0)    

image de synthèse, base

# coding: cp1252
"""définition des objets permettant de construire une image de synthèse"""
import math
import copy

class vecteur (object) :
    """définit ce qu'est un point"""
    __slots__ = "x","y","z"
    
    def __str__ (self):
        """pour l'affichage"""
        return "(%3.2f,%3.2f,%3.2f)" % (self.x, self.y, self.z)
    
    def __init__(self,x,y,z):
        """initialisation"""
        self.x, self.y, self.z = float (x), float (y), float (z)
    
    def __add__ (self,p):
        """addition de deux points"""
        return vecteur (self.x + p.x, self.y + p.y, self.z + p.z)
        
    def __neg__ (self):
        """retourne l'opposé d'un vecteur"""
        return vecteur (-self.x,-self.y,-self.z)

    def __iadd__ (self,p):
        """addition de deux points"""
        self.x += p.x
        self.y += p.y
        self.z += p.z
        return self

    def __sub__ (self,p):
        """soustraction de deux points"""
        return vecteur (self.x - p.x, self.y - p.y, self.z - p.z)

    def __isub__ (self,p):
        """soustraction de deux points"""
        self.x -= p.x
        self.y -= p.y
        self.z -= p.z
        return self
        
    def __mul__ (self,x):
        """multiplication par un scalaire"""
        return vecteur (self.x * x, self.y * x, self.z * x)

    def __imul__ (self,x):
        """multiplication par un scalaire"""
        self.x *= x
        self.y *= x
        self.z *= x
        return self
        
    def __div__ (self,x):
        """division par un scalaire"""
        return vecteur (self.x / x, self.y / x, self.z / x)

    def __idiv__ (self,x):
        """division par un scalaire"""
        self.x /= x
        self.y /= x
        self.z /= x
        return self
        
    def norme2 (self) :
        """retourne la norme du vecteur au carrée"""
        return self.x * self.x + self.y * self.y + self.z * self.z
        
    def scalaire (self, v) :
        """calcule le produit scalaire entre self et v"""
        return self.x * v.x + self.y * v.y + self.z * v.z
        
    def vectoriel (self, v) :
        """calcule le produit vectoriel entre self et v"""
        res   = vecteur (0,0,0)
        res.x = self.y * v.z - self.z * v.y
        res.y = self.z * v.x - self.x * v.z
        res.z = self.x * v.y - self.y * v.x
        return res
        
    def norme (self) :
        """retourne la norme du vecteur"""
        return math.sqrt (self.norme2 ())
        
    def renorme (self) :
        """renorme ce vecteur"""
        n = self.norme ()
        if n > 0 : return self / n
        else : return copy.copy (self)
            
    def cosinus (self, v) :
        """retourne le cosinus de entre le vecteur self et le vecteur r"""
        sc = self.scalaire (v)
        n1 = self.norme ()
        n2 = v.norme ()
        n  = n1 * n2
        if n == 0 : return 0
        return float (sc) / float (n)
        
    def sinus (self, v, norm) :
        """retourne le sinus de entre le vecteur self et le vecteur r, 
        norm est un vecteur normal et de norme 1 permettant d'orienter
        le plan dans lequel se trouve les deux vecteurs dont il faut mesurer le sinus"""
        sc = self.vectoriel (v)
        n1 = self.norme ()
        n2 = v.norme ()
        n  = n1 * n2
        if n == 0 : return 0
        return sc.scalaire (norm) / float (n)
        
    def angle (self, v, norm) :
        """retourne l'angle entre les vecteur self et v,
        retourne un angle compris entre -pi et pi,
        norm est la direction du vecteur normal au plan des deux vecteurs"""
        cos     = self.cosinus (v)
        sin     = self.sinus (v, norm)
        angle   = math.atan2 (sin, cos)
        if angle > math.pi : angle -= math.pi * 2
        return angle
        
    def diff_abs (self, v):
        """retourne la somme des valeurs absolues des différentes entre coordonnées"""
        r  = abs (self.x - v.x)
        r += abs (self.y - v.y)
        r += abs (self.z - v.z)
        return r
        
    def __eq__ (self, v) :
        """définit l'égalité entre deux vecteurs"""
        if v == None : return False
        return self.diff_abs (v) < 1e-10
           
    def __ne__ (self, v) :
        """définit l'égalité entre deux vecteurs"""
        if v == None : return True
        return self.diff_abs (v) > 1e-10


class couleur (vecteur) :
    """une couleur est un vecteur dont les coordonnées sont comprises entre 0 et 1, 
    x <--> rouge, y <--> vert, z <--> bleu"""
    
    def __init__ (self, x,y,z) :
        vecteur.__init__(self, x,y,z)
        self.borne ()
            
    def borne (self) :
        """si une couleur est hors bornes, réajuste la couleur, prend le maximum devient 1,
        les autres intensités sont ajustées selon ce facteur d'échelle"""
        if self.x < 0 : self.x = 0
        if self.y < 0 : self.y = 0
        if self.z < 0 : self.z = 0
        m = max (self.x, self.y)
        m = max (m, self.z)
        if m > 1 :
            self.x /= m
            self.y /= m
            self.z /= m
        
    def __add__ (self,p):
        """addition de deux couleurs"""
        return couleur (self.x + p.x, self.y + p.y, self.z + p.z)

    def produit_terme (self, v) :
        """effectue un produit terme à terme"""
        return couleur (self.x * v.x, self.y * v.y, self.z * v.z)

    def __mul__ (self,x):
        """multiplication par un scalaire"""
        return couleur (self.x * x, self.y * x, self.z * x)
        


class repere (object) :
    """définition d'un repère orthonormé"""
    
    def __init__ (self,   origine = vecteur (0,0,0), \
                            axex    = vecteur (1,0,0), \
                            axey    = vecteur (0,1,0), \
                            axez    = vecteur (0,0,1)) :
        """initialisation, origine et les trois axes"""
        self.origine    = origine
        self.x          = axex
        self.y          = axey
        self.z          = axez
        
    def coordonnees (self, v) :
        """on suppose que les coordonnées de v sont exprimées dans ce repère,
        calcule les coordonnées de v dans le repère d'origine"""
        res      = copy.copy (self.origine)
        res.x  += v.x * self.x.x +  v.y * self.y.x + v.z * self.z.x
        res.y  += v.x * self.x.y +  v.y * self.y.y + v.z * self.z.y
        res.z  += v.x * self.x.z +  v.y * self.y.z + v.z * self.z.z
        return res
        
    def __str__ (self):
        """affichage"""
        s  = "origine : " + str (self.origine) + "\n"
        s += "axe des x : " + str (self.x) + "\n"
        s += "axe des y : " + str (self.y) + "\n"
        s += "axe des z : " + str (self.z) + "\n"
        return s
        
class pixel (object) :
    """définit ce qu'est un pixel"""
    __slots__ = "x","y"
        
    def __init__(self,x,y):
        """initialisation"""
        self.x, self.y = int (x), int (y)
    
    def __str__ (self):
        """pour l'affichage"""
        return "(%d, %d)" % (self.x, self.y)
        
        
        
        
class rayon (object) :
    """définit ce qu'est un rayon"""
    __slots__ = "origine", "direction", "pixel", "couleur"
    
    def __init__ (self, origine, direction, pixel, couleur):
        """initialisation"""
        self.origine, self.direction, self.pixel, self.couleur = \
                origine, direction, pixel, couleur
        
    def __str__ (self):
        """pour l'affichage"""
        s  = "origine   : "     + str (self.origine)
        s += " direction : "    + str (self.direction)
        s += " pixel : "        + str (self.pixel)
        s += " couleur : "      + str (self.couleur)
        return s
    

class objet (object):
    """définit l'interface pour un objet à dessiner dans une image de synthese"""

    def intersection (self, r) :
        """retourne le point d'intersection avec le rayon r, 
        retourne None s'il n'y pas d'intersection"""
        return None
        
    def normale (self, p, rayon) :
        """retourne la normale au point de coordonnée p, et connaissant le rayon"""
        return None
        
    def couleur_point (self, p) :
        """retourne la couleur au point de coordonnée p"""
        return None
    
    def rayon_refracte (self, rayon, p) :
        """retourne le rayon réfracté au point p de la surface,
        si aucune, retourne None"""
        return None
        
    def rayon_reflechi (self, rayon, p) :
        """retourne le rayon réfléchi au point p de la surface,
        si aucune, retourne None"""
        return None
        
    def phong_coefficient (self):
        """retourne un coefficient propre à l'objet pour
        le modèle d'illumination de Phong"""
        return float (0)
        
        
        
class source (object) :
    """définition d'une source ponctuelle"""
    __slots__ = "origine", "couleur"

    def __init__ (self, origine, couleur):
        """initialisation"""
        self.origine, self.couleur = origine, couleur
        
    def __str__ (self) :
        """affichage"""
        return "source : " + str (self.origine) + " couleur : " + str (self.couleur)
        
if __name__ == "__main__" :
    v = vecteur (0,1,2)
    u = vecteur (0,1,2)
    w = u + v
    print u,v,w
    print w * 6
    p = pixel (5,5)
    print p
    c = couleur (1,1,1) 
    print c
    r = rayon (u,w,p,c)
    print r
    s = source (v, c)
    print s


image de synthèse, sphère

# coding: cp1252
"""définition d'une sphère"""
import image_synthese_base as base
import math

class sphere (base.objet):
    """définit une sphère"""
    __slots__ = "centre", "rayon", "couleur"
    
    def __init__ (self, centre, rayon, couleur):
        """initialisation"""
        self.centre, self.rayon, self.couleur = centre, float (rayon), couleur

    def intersection (self, r) :
        """retourne le point d'intersection avec le rayon r, 
        retourne None s'il n'y pas d'intersection"""
        oc      = self.centre - r.origine
        vn      = r.direction.norme2 ()
        s       = r.direction.scalaire (oc)
        delta   = s*s - vn * (oc.norme2 () - self.rayon * self.rayon)
        if delta < 0 : return None
        delta   = math.sqrt (delta)
        l1      = (s - delta) / vn
        l2      = (s + delta) / vn
        
        if      0 < l1 < l2 :   l = l1
        elif    l1 < 0 < l2 :   l = l2
        elif    0 < l2 < l1 :   l = l2
        elif    l2 < 0 < l1 :   l = l1
        else :                  l = None

        if l == None : return None

        v = r.origine + r.direction * l
        return v
        
    def normale (self, p, rayon) :
        """retourne la normale au point de coordonnée p"""
        v = (p - self.centre) / self.rayon
        return v     
        
    def couleur_point (self, p) :
        """retourne la couleur au point de coordonnée p"""
        return self.couleur
        
    def __str__ (self):
        """affichage"""
        s  = "sphère --- centre : " + str (self.centre)
        s += " rayon : " + str (self.rayon)
        s += " couleur : " + str (self.couleur)
        return s
        
        
        
if __name__ == "__main__" :
    s = sphere (base.vecteur (0,0,0), 5, base.couleur (0,1,0))
    r = base.rayon (    base.vecteur (10,0,0), base.vecteur (1,0,0), \
                        base.pixel (0,0), base.couleur (0,0,0))
    print s
    print r
    p = s.intersection (r)
    print p
    


image de synthèse, scène

# coding: cp1252
"""définition d'une scène"""
import image_synthese_base as base
import image_synthese_sphere as obj
import math
import pygame

class scene (object):
    """définit une scène, les axes x,y sont ceux de l'écran, 
    z-1 est la distance à l'écran du point (x,y,z)"""
    
    def __init__ (self, repere, alpha, x,y) :
        """définit la position de l'oeil, l'angle d'ouverture,
        et la taille de l'écran"""
        self.repere = repere
        self.alpha  = float (alpha)
        self.dim    = (int (x), int (y))
        
    def ajoute_source (self, source):
        """ajoute une source ponctuelle de lumière"""
        if not self.__dict__.has_key ("sources") : self.sources = []
        self.sources.append (source)
        
    def ajoute_objet (self, objet):
        """ajoute un objet à la scène"""
        if not self.__dict__.has_key ("objets") : self.objets = []
        self.objets.append (objet)
        
    def __str__ (self) :
        """affichage"""
        s  = "scène ----------------------------\n"
        s += "repère : " + str (self.repere) + "\n"
        s += "angle d'ouverture : " + str (self.alpha) + "\n"
        s += "dimension de l'écran : " + str (self.dim) + "\n"
        if self.__dict__.has_key ("sources") :
            for a in self.sources : s += "   " +str (a) + "\n"
        if self.__dict__.has_key ("objets") :
            for a in self.objets :  s += "   " + str (a) + "\n"
        return s
        
    def intersection (self, rayon) : 
        """calcule le point d'intersection entre un rayon et le plus proche des objets,
        retourne l'objet et le point d'intersection"""
        if not self.__dict__.has_key ("objets") : return None, None
        p       = rayon.origine
        sp,so   = None, None
        for o in self.objets :
            i = o.intersection (rayon)
            if i == None : continue
            if rayon.direction.scalaire (i - p) <= 0 : continue 
            if i == rayon.origine : continue 
            if sp == None : 
                sp  = i
                so  = o
            else :
                v = i - p
                d = sp - p
                if v.norme2 () < d.norme2 () :
                    sp = i
                    so = o
        return so, sp                
                
    def sources_atteintes (self, p) : 
        """retourne la liste des sources atteintes depuis une position p de l'espace,
        vérifie qu'aucun objet ne fait obstacle"""
        res = []
        for s in self.sources:
            r   = base.rayon (s.origine, p - s.origine, base.pixel (0,0), s.couleur)
            o,i = self.intersection (r)
            if i == None : continue
            if (i - p).norme2 () < 1e-10 :   # possible problème d'arrondi
                res.append (s)
                continue
        return res
                        
    def construit_rayon (self, pixel) :
        """construit le rayon correspondant au pixel pixel"""
        x = (pixel.x - self.dim [0] / 2) * math.tan (self.alpha / 2) / min (self.dim)
        y = (pixel.y - self.dim [1] / 2) * math.tan (self.alpha / 2) / min (self.dim)
        v = base.vecteur (x,y,1)
        r = base.rayon (self.repere.origine, self.repere.coordonnees (v), \
                            pixel, base.couleur (1,1,1))
        return r
        
    def modele_illumination (self, rayon, p, obj, source) :
        """calcule la couleur pour un rayon donné, un point p, un objet obj, 
        et une source de lumière source"""
        n   = obj.normale (p, rayon)
        cos = n.cosinus (source.origine - p)
        cl  = obj.couleur_point (p) * cos
        cl  = cl.produit_terme (rayon.couleur)
        return cl
        
    def couleur_fond (self) :
        """retourne la couleur du fond"""
        return base.couleur (0,0,0)
        
    def rayon_couleur (self, rayon, ref = True) :
        """retourne la couleur d'un rayon connaissant les objets,
        cette fonction doit être surchargée pour chaque modèle d'illumination, 
        si ref == True, on tient compte des rayons réfracté et réfléchi"""
        
        list_rayon = [ rayon ]
        c = base.couleur (0,0,0)
        b = False
        while len (list_rayon) > 0 :
            r   = list_rayon.pop ()
            o,p = self.intersection (r)

            if p == None : continue
                
            if ref :
                t   = o.rayon_refracte (r, p)
                if t != None : list_rayon.append (t)
                t   = o.rayon_reflechi (r, p)
                if t != None : list_rayon.append (t)
                
            sources = self.sources_atteintes (p)
            if len (sources) == 0 : return base.couleur (0,0,0)
            for s in sources :
                cl  = self.modele_illumination (r, p, o, s)
                c  += cl
                b   = True

        if not b : c = self.couleur_fond ()
        else : c.borne ()
        return c        
        
    def construit_image (self, screen):
        """construit l'image de synthèse où screen est un objet du module pygame"""
        count   = 0
        nbpixel = int (self.dim [0] * self.dim [1] / 100)
        for y in xrange (0, self.dim [1]) :
            for x in xrange (0, self.dim [0]) :
                p = base.pixel (x,y)
                r = self.construit_rayon (p)
                c = self.rayon_couleur (r, True)
                q = (p.x,self.dim [1] - p.y - 1) 
                d = (int (c.x * 255), int (c.y * 255), int (c.z * 255))
                pygame.draw.line (screen, d, q,q)
                count += 1
                if count % 150 == 0 : pygame.display.flip ()
                if count % nbpixel == 0 : print "avancement " , count // nbpixel , "%"
        pygame.display.flip ()


def attendre_clic ():
    """dessine une croix sur l'écran et attend la pression d'un clic de souris"""
    reste = True
    while reste:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP :
                reste = False
                break


if __name__ == "__main__" :
    s = scene (base.repere (), math.pi / 1.5, 400, 300)
    s.ajoute_source ( base.source (base.vecteur (0,10,10), \
                        base.couleur (1,1,1) ) )
    s.ajoute_source ( base.source (base.vecteur (10,10,5), \
                        base.couleur (0.5,0.5,0.5) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,0,12), \
                        3, base.couleur (1,0,0) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,-400,12), \
                        396, base.couleur (0.5,0.5,0.5) ) )
    print s
    
    screen  = pygame.display.set_mode (s.dim)
    screen.fill ((255,255,255))
    s.construit_image (screen)

    print "image terminée"
    attendre_clic ()


image de synthèse, complet

# coding: cp1252
"""implémentation du modèle d'illumination de Phong"""
import image_synthese_scene as scene
import image_synthese_base as base
import image_synthese_sphere as obj
import math
import pygame


class scene_phong (scene.scene):
    """définit une scène et utilise le modèle d'illumination de Phong
    pour construire l'image de synthèse"""
    
    def __init__ (self, repere, alpha, x,y,
                    ka          = 0.1,
                    kb          = 0.8,
                    kc          = 0.3,
                    reflet      = 6,
                    fond        = base.couleur (200,200,200)) :
        """définit la position de l'oeil, l'angle d'ouverture,
        et la taille de l'écran"""
        scene.scene.__init__ (self, repere, alpha, x, y)
        self.ka, self.kb, self.kc   = ka,kb,kc
        self.reflet                 = reflet
        self.fond                   = fond
        self.constante              = float (1)
        
    def __str__ (self) :
        """affichage"""
        s  = scene.scene.__str__ (self)
        s += "ka = %1.3f   kb = %1.3f   kc = %1.3f\n" % (self.ka,self.kb,self.kc)
        s += "reflet " + str (self.reflet) + "\n"
        s += "couleur du fond " + str (self.fond) + "\n"
        return s
        
    def couleur_fond (self) :
        """retourne la couleur du fond"""
        return self.fond * self.ka
        
    def modele_illumination (self, rayon, p, obj, source) :
        """calcule la couleur pour un rayon donné, un point p, un objet obj, 
        et une source de lumière source"""
        n   = obj.normale (p, rayon).renorme ()
        vr  = rayon.direction.renorme ()
        vr *= float (-1)
        vs  = source.origine - p
        vs  = vs.renorme ()
        bi  = vs + vr
        bi  = bi.renorme ()
        
        # premier terme
        cos      = n.scalaire (vs)
        couleur  = source.couleur.produit_terme (obj.couleur_point (p)) * (cos * self.kb)
        
        # second terme : reflet
        cos      = n.scalaire (bi) ** self.reflet
        couleur += source.couleur.produit_terme (source.couleur) * (cos * self.kc)
        couleur  = couleur.produit_terme (rayon.couleur)
        
        return couleur


if __name__ == "__main__" :
    s = scene_phong (base.repere (), math.pi / 1.5, 400, 300)

    s.ajoute_source ( base.source (base.vecteur (0,10,10), \
                        base.couleur (1,1,1) ) )
    s.ajoute_source ( base.source (base.vecteur (10,10,5), \
                        base.couleur (0.5,0.5,0.5) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,0,12), \
                        3, base.couleur (1,0,0) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,-400,12), \
                        396, base.couleur (0.5,0.5,0.5) ) )
    print s
    
    screen  = pygame.display.set_mode (s.dim)
    screen.fill ((255,255,255))
    s.construit_image (screen)

    print "image terminée"
    scene.attendre_clic ()


image de synthèse, facette

# coding: cp1252
"""définition d'une sphère"""
import image_synthese_base as base
import image_synthese_sphere as obj
import image_synthese_phong as scene
import image_synthese_scene as scene_p
import pygame
import math

class facette (base.objet):
    """définit un triangle dans l'espace"""
    
    def __init__ (self, a,b,c, couleur):
        """initialisation"""
        self.a, self.b, self.c = a,b,c
        ab = b - a
        ac = c - a
        self.vnorm = ab.vectoriel (ac)
        self.vnorm = self.vnorm.renorme ()
        self.couleur = couleur
        
    def intersection_plan (self, r) :
        """retourne le point d'intersection entre le plan et le rayon r"""
        if r.direction.scalaire (self.vnorm) == 0 :
            return None
        oa      = self.a - r.origine 
        l       = self.vnorm.scalaire (oa) / self.vnorm.scalaire (r.direction)
        p       = r.origine + r.direction * l
        return p
        
    def point_interieur (self, p) :
        """dit si un point appartient à l'intérieur du triangle"""
        pa      = self.a - p        
        pb      = self.b - p        
        pc      = self.c - p   
        theta   = pa.angle (pb, self.vnorm)
        theta  += pb.angle (pc, self.vnorm)
        theta  += pc.angle (pa, self.vnorm)
        theta   = abs (theta)
        if theta >= math.pi * 0.9 : return True
        else : return False

    def intersection (self, r) :
        """retourne le point d'intersection avec le rayon r, 
        retourne None s'il n'y pas d'intersection"""
        p = self.intersection_plan (r)
        if p == None : return None
        if self.point_interieur (p) : return p
        else : return None
        
    def normale (self, p, rayon) :
        """retourne la normale au point de coordonnée p et connaissant le rayon"""
        if rayon.direction.scalaire (self.vnorm) < 0 :
            return self.vnorm
        else :
            return - self.vnorm 
        
    def couleur_point (self, p) :
        """retourne la couleur au point de coordonnée p"""
        return self.couleur
        
    def __str__ (self):
        """affichage"""
        s  = "facette --- a : " + str (self.a)
        s += " b : " + str (self.b)
        s += " c : " + str (self.c)
        s += " couleur : " + str (self.couleur)
        return s
        
        
class rectangle (facette):
    """définit un rectangle dans l'espace"""
    
    def __init__ (self, a,b,c,d, couleur):
        """initialisation, si d == None, d est calculé comme étant 
        le symétrique de b par rapport au milieu du segment [ac]"""
        facette.__init__(self, a,b,c, couleur)
        if d != None : self.d = d
        else :
            i       = (a + c) / 2
            self.d  = b + (i-b) * 2
        
    def point_interieur (self, p) :
        """dit si un point appartient à l'intérieur du triangle"""
        pa      = self.a - p        
        pb      = self.b - p        
        pc      = self.c - p   
        pd      = self.d - p   
        theta   = pa.angle (pb, self.vnorm)
        theta  += pb.angle (pc, self.vnorm)
        theta  += pc.angle (pd, self.vnorm)
        theta  += pd.angle (pa, self.vnorm)
        theta   = abs (theta)
        if theta >= math.pi * 0.9 : return True
        else : return False
        
    def __str__ (self):
        """affichage"""
        s  = "rectangle --- a : " + str (self.a)
        s += " b : " + str (self.b)
        s += " c : " + str (self.c)
        s += " d : " + str (self.d)
        s += " couleur : " + str (self.couleur)
        return s
        
       


        
if __name__ == "__main__" :
    
    s = scene.scene_phong (base.repere (), math.pi / 1.5, 400, 300)

    s.ajoute_source ( base.source (base.vecteur (0,8,8), \
                        base.couleur (0.6,0.6,0.6) ) )
    s.ajoute_source ( base.source (base.vecteur (10,0,0), \
                        base.couleur (0.6,0.6,0.6) ) )
    s.ajoute_source ( base.source (base.vecteur (8,8,4.5), \
                        base.couleur (0.6,0.6,0.6) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (1,0,5), \
                        1, base.couleur (1,0,0) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (0,-400,12), \
                        396, base.couleur (0.5,0.5,0.5) ) )
    s.ajoute_objet (facette ( base.vecteur (0,-2.5,6),   \
                               base.vecteur (-2,-2.5,3), \
                               base.vecteur (1,-3.5,4.5), \
                               base.couleur (0.2,0.8,0)))
    s.ajoute_objet (rectangle ( base.vecteur (0,-2.5,6),   \
                               base.vecteur (-2,-2.5,3), \
                               base.vecteur (-2,2.8,3.5), \
                               None, \
                               base.couleur (0,0,1)))
    print s
    
    screen  = pygame.display.set_mode (s.dim)
    screen.fill ((255,255,255))
    s.construit_image (screen)

    print "image terminée"
    scene_p.attendre_clic ()
    
    


image de synthèse, facette image

# coding: cp1252
"""définition d'une sphère"""
import image_synthese_base as base
import image_synthese_sphere as obj
import image_synthese_phong as scene
import image_synthese_scene as scene_p
import image_synthese_facette as facette
import pygame
import math
import psyco

       
        
class rectangle_image (facette.rectangle):
    """définit un rectangle contenant un portrait"""
    
    def __init__(self, a,b,c,d, nom_image, invertx = False):
        """initialisation, si d == None, d est calculé comme étant 
        le symétrique de b par rapport au milieu du segment [ac],
        la texture est une image, 
        si invertx == True, inverse l'image selon l'axe des x"""
        facette.rectangle.__init__(self, a,b,c,d, base.couleur (0,0,0))
        self.image      = pygame.image.load (nom_image)
        self.nom_image  = nom_image
        self.invertx    = invertx

    def __str__ (self):
        """affichage"""
        s  = "rectangle image --- a : " + str (self.a)
        s += " b : " + str (self.b)
        s += " c : " + str (self.c)
        s += " d : " + str (self.d)
        s += " image : " + self.nom_image
        return s
        
    def couleur_point (self, p) :
        """retourne la couleur au point de coordonnée p"""
        ap  = p - self.a
        ab  = self.b - self.a
        ad  = self.d - self.a
        abn = ab.norme2 ()
        adn = ad.norme2 ()
        x   = ab.scalaire (ap) / abn
        y   = ad.scalaire (ap) / adn
        sx,sy = self.image.get_size ()
        k,l   = int (x * sx), int (y * sy)
        k   = min (k, sx-1)
        l   = min (l, sy-1)
        l   = sy - l - 1
        if not self.invertx :
            c   = self.image.get_at ((k,l))
        else :
            c   = self.image.get_at ((sx-k-1,l))
        cl  = base.couleur (float (c [0]) / 255, float (c [1]) / 255, float (c [2]) / 255)
        return cl

class sphere_reflet (obj.sphere) :
    """implémente une sphère avec un reflet"""
    
    def __init__ (self, centre, rayon, couleur, reflet):
        """initialisation, reflet est un coefficient de réflexion"""
        obj.sphere.__init__ (self, centre, rayon, couleur)
        self.reflet = reflet
        
    def __str__ (self):
        """affichage"""
        s  = "sphère reflet --- centre : " + str (self.centre)
        s += " rayon : " + str (self.rayon)
        s += " couleur : " + str (self.couleur)
        return s

    def rayon_reflechi (self, rayon, p) :
        """retourne le rayon réfléchi au point p de la surface,
        si aucune, retourne None"""
        if p == rayon.origine : return None
        n = self.normale (p, rayon)
        n = n.renorme ()
        y = n.scalaire (rayon.direction)
        d = rayon.direction - n * y * 2
        r = base.rayon (p, d, rayon.pixel, rayon.couleur * self.reflet)
        return r

        
if __name__ == "__main__" :
    
    psyco.full ()
    
    s = scene.scene_phong (base.repere (), math.pi / 1.5, 400, 200)

    s.ajoute_source ( base.source (base.vecteur (0,8,8), \
                        base.couleur (0.4,0.4,0.4) ) )
    s.ajoute_source ( base.source (base.vecteur (10,0,0), \
                        base.couleur (0.4,0.4,0.4) ) )
    s.ajoute_source ( base.source (base.vecteur (8,8,4.5), \
                        base.couleur (0.4,0.4,0.4) ) )
    s.ajoute_objet  ( obj.sphere  (base.vecteur (3,-4,7), \
                        1, base.couleur (1,0,0) ) )
    s.ajoute_objet  ( sphere_reflet  (base.vecteur (0,-400,12), \
                        396, base.couleur (0.5,0.5,0.5), 0.5 ) )
                        
    s.ajoute_objet (rectangle_image ( base.vecteur (8,-3.5,9),   \
                               base.vecteur (2,-3.5,8), \
                               base.vecteur (2,3.8,8), \
                               None, \
                               "bette_davis.png",
                               invertx = True))

    s.ajoute_source ( base.source (base.vecteur (7,2,8), \
                        base.couleur (0.2,0.2,0.2) ) )
    s.ajoute_source ( base.source (base.vecteur (12.5,3,5), \
                        base.couleur (0.2,0.2,0.2) ) )
                        
    s.ajoute_source ( base.source (base.vecteur (-12.5,1,6), \
                        base.couleur (0.2,0.2,0.2) ) )
                        
    s.ajoute_objet (facette.rectangle ( base.vecteur (-12.4,0.99,5.9),   \
                               base.vecteur (-12.6,0.99,5.9), \
                               base.vecteur (-12.6,0.99,6.1), \
                               None, \
                               base.couleur (0,0,0)))
                               
    print s
    
    screen  = pygame.display.set_mode (s.dim)
    screen.fill ((255,255,255))
    s.construit_image (screen)

    print "sauvegarde de l'image"
    im = pygame.display.get_surface()
    print "image size : ", im.get_size ()
    pygame.image.save (im, "c:\\temp\\image.jpg")
    pygame.image.save (im, "c:\\temp\\image.tif")
    pygame.image.save (im, "c:\\temp\\image.bmp")

    print "image terminée"
    scene_p.attendre_clic ()
       
    
    


File: usb_window.tex, line 44


import Tkinter as Tk              # import du module Tkinter
 
root = Tk.Tk ()                   # création de la fenêtre principale,
                                  # c'est toujours la première ligne

b = Tk.Button (text = "bouton")   # création d'un bouton
e = Tk.Entry ()                   # création d'une zone de saisie
l = Tk.Label (text = "légende")   # création d'une légende

b.grid (row = 0, column = 0)      # positionnement de b dans la case (0,0)
e.grid (row = 1, column = 1)      # positionnement de e dans la case (1,1)
l.grid (row = 2, column = 2)      # positionnement de e dans la case (2,2)

root.mainloop ()                  # on lance le programme et l'affichage de la fenêtre

File: usb_window.tex, line 83


import Tkinter as Tk              # import du module Tkinter
 
root = Tk.Tk ()                   # création de la fenêtre principale,
                                  # c'est toujours la première ligne

b = Tk.Button (text = "bouton")   # création d'un bouton
e = Tk.Entry ()                   # création d'une zone de saisie
l = Tk.Label (text = "légende")   # création d'une légende

b.grid (row = 0, column = 0)      # positionnement de b dans la case (0,0)
e.grid (row = 1, column = 1)      # positionnement de e dans la case (1,1)
l.grid (row = 2, column = 2)      # positionnement de e dans la case (2,2)

# spécifications
b.config (width = 30, height = 4)       # largeur de 30, hauteur de 4
e.config (width = 50, font = "arial")   # largeur de 50, police arial
l.config (width = 30, height = 6)       # largeur de 30, hauteur de 6

root.mainloop ()                  # on lance le programme et l'affichage de la fenêtre

File: usb_window.tex, line 117


import Tkinter as Tk              # import du module Tkinter
 
root = Tk.Tk ()                   # création de la fenêtre principale,
                                  # c'est toujours la première ligne

b = Tk.Button (text = "bouton")   # création d'un bouton
e = Tk.Entry ()                   # création d'une zone de saisie
l = Tk.Label (text = "légende")   # création d'une légende

b.grid (row = 0, column = 0)      # positionnement de b dans la case (0,0)
e.grid (row = 1, column = 1)      # positionnement de e dans la case (1,1)
l.grid (row = 2, column = 2)      # positionnement de e dans la case (2,2)

e.insert (0, "texte par défaut")  # on insère une chaîne de caractères dans la zone de saisie

root.mainloop ()                  # on lance le programme et l'affichage de la fenêtre

File: usb_window.tex, line 138


class copie_usb_window (copie_usb.copie_usb):

    def fenetre (self) :
        # ici, création de la fenêtre graphique
        # ...

File: usb_window.tex, line 148


# programme principal
ch1             = "C:\\Documents and Settings\\Dupré\\" \
                    "Mes documents\\informatique\\support\\python_td"
ch2             = "c:\\temp\\copie_usb"
filtre_accept   = ".*[.].*"
filtre_refuse   = ".*[.]pdf$|.*[.]html$|.*[.]bmp|programme\\\\.*[.]zip$"

c = copie_usb_window (ch1, ch2, filtre_accept, filtre_refuse)
c.fenetre ()   # affiche la fenêtre graphique

File: usb_window.tex, line 166


import Tkinter as Tk              # import du module Tkinter
 
root = Tk.Tk ()                   # création de la fenêtre principale,
                                  # c'est toujours la première ligne

b = Tk.Button (text = "bouton")   # création d'un bouton
e = Tk.Entry ()                   # création d'une zone de saisie
l = Tk.Label (text = "légende")   # création d'une légende

b.grid (row = 0, column = 0)      # positionnement de b dans la case (0,0)
e.grid (row = 1, column = 1)      # positionnement de e dans la case (1,1)
l.grid (row = 2, column = 2)      # positionnement de e dans la case (2,2)

# fonction à exécuter si le bouton b est pressé
def affichage_bouton ():
    print "chaîne affichée si le bouton est pressé"
    
# on affecte la fonction affichage_bouton au bouton b
b.config (command = affichage_bouton)
    
root.mainloop ()                  # on lance le programme et l'affichage de la fenêtre

File: usb_window.tex, line 192


b.config (command = root.destroy)

File: usb_window.tex, line 215


s = e.get ()    # on récupère le contenu de la zone de saisie
i = len (s)     # i est égal à la longueur de la chaîne s
e.delete (0, i) # on vide la zone de saisie
s = s.upper ()  # mise en majuscules
e.insert (0,s)  # on remplace le contenu de la zone de saisie

File: usb_window.tex, line 233


import selection_file
fs = selection_file.FileSelection (titre, "c:\\temp", file = False)
r  = fs.run ()
print r  # chaîne de caractères ou None

sélection d'un fichier

# coding: cp1252
"""module contenant une boîte de dialogue permettant 
de sélectionner un fichier ou un répertoire,
il utilise l'interface Tkinter"""
import Tkinter as Tk
import os.path
import os

class FileSelection (object) :
    """classe permettant de sélectionner un fichier 
    ou un répertoire à travers une boîte de dialogue"""
    
    def __init__ (self, titre = "Sélection de fichier", \
                    chemin = None, file = True, exist= True) :
        """initialise la classe
        @param      titre           titre de la fenêtre
        @param      chemin          fichier ou répertoire par défaut
        @param      file            True : fichier, False : répertoire
        @param      exist           True : le répertoire ou le fichier 
                                           sélectionné doit exister"""
        self.titre  = titre
        self.chemin = chemin
        self.file   = file
        self.exist  = exist
        
        if self.chemin == None :  self.chemin = os.getcwd ()
            
    def get_list (self) :
        """retourne la liste des fichiers et des répertoires (2 listes), 
        répertoires seulement et [] si self.file == False"""
        if os.path.isdir (self.chemin) :
            list    = os.listdir (self.chemin)
        else : 
            ch,fi   = os.path.split (self.chemin)
            list    = os.listdir (ch)
        
        lifile  = []
        lidir   = []
        for l in list :
            if os.path.isdir (self.chemin + "\\" + l) : 
                lidir.append (l)
            elif self.file : 
                lifile.append (l)
                
        lidir.sort ()
        lifile.sort ()
        return lidir, lifile
        
    def run (self) :
        """lance la boîte de dialogue et retourne la chaîne sélectionnée"""
        top         = Tk.Toplevel ()
        top.wm_title (self.titre)

        fli     = Tk.Frame (top)
        scrollbar = Tk.Scrollbar (fli)
        li      = Tk.Listbox (fli, width = 120, height = 15, \
                               yscrollcommand = scrollbar.set)
        scrollbar.config (command = li.yview)
        ch      = Tk.Entry (top, width = 120)
        f       = Tk.Frame (top)
        prec    = Tk.Button (f, text = "Précédent")
        suiv    = Tk.Button (f, text = "Entre")
        annul   = Tk.Button (f, text = "Annuler")        
        ok      = Tk.Button (f, text = "Ok")        
        
        prec.grid (column = 0, row = 0)
        suiv.grid (column = 1, row = 0)
        annul.grid (column = 3, row = 0)
        ok.grid (column = 4, row = 0)
        li.pack (side = Tk.LEFT)
        scrollbar.pack(side = Tk.RIGHT, fill = Tk.Y)
        fli.pack ()
        ch.pack ()
        f.pack ()

        def update_chemin () :
            """mise à jour du chemin dans la boîte de dialogue"""
            s = ch.get ()
            ch.delete (0, len (s))
            ch.insert (0, self.chemin)

        def update_list () :
            """mise à jour de la liste des fichiers et répertoires 
            à partir de la chaîne dans la boîte de dialogue"""
            self.chemin     = ch.get ()
            lidir, lifile   = self.get_list ()
            li.delete (0, Tk.END)
            if len (lidir) > 0 : 
                for l in lidir : li.insert (Tk.END, "+ "+ l)
            if len (lifile) > 0 : 
                for l in lifile : li.insert (Tk.END, "  "+ l)
                    
        def precedent () :
            """passe au répertoire précédent"""
            if os.path.isdir (self.chemin) :
                ch, last    = os.path.split (self.chemin)
                self.chemin = ch
            else :
                ch, last    = os.path.split (self.chemin)
                ch, last    = os.path.split (ch)
                self.chemin = ch
            update_chemin ()
            update_list ()
        
        def suivant () :
            """rentre dans un répertoire"""
            sel = ch.get ()
            if os.path.isdir (sel) :
                self.chemin = sel
                update_chemin ()
                update_list ()
            
        def update_sel () :
            """mise à jour de la chaîne de caractères 
            dans la boîte de dialogue à partir de la ligne
            sélectionnée dans la liste"""
            li.after (200, update_sel)
            sel = li.curselection ()
            if len (sel) == 1 :
                t = li.get (sel [0])
                c = self.chemin + "\\" +  t [2:len (t)]
                c = c.replace ("\\\\", "\\")
                s = ch.get ()
                ch.delete (0, len (s))
                ch.insert (0, c)
                
        def annuler () :
            """annule la recherche"""
            self.resultat = False
            top.destroy ()
            top.quit ()
        
        def accepter () :
            """accepte le résultat"""
            self.resultat    = True
            self.chemin = ch.get ()
            top.destroy ()
            top.quit ()
            
        prec.config (command = precedent)
        suiv.config (command = suivant)
        annul.config (command = annuler)
        ok.config (command = accepter)
                
        update_chemin ()
        update_list ()
        update_sel ()
        ch.focus_set ()
        top.mainloop ()
        
        if self.resultat : return self.chemin
        else : return None
            
            
if __name__ == "__main__" :
    root = Tk.Tk ()
    
    def run () :
        r = FileSelection ("sélection d'un fichier", "c:\\")
        s = r.run ()
        print "fichier sélectionné ", s
        
    Tk.Button (text = "fenêtre", command = run).pack ()
    Tk.Button (text = "fermer", command = root.destroy).pack ()
    root.mainloop ()
    

copie de fichiers avec interface graphique

# coding: cp1252
"""copie de fichiers sur une clé USB, interface fenêtrée"""

import Tkinter as Tk    # pour la fenêtre
import selection_file   # pour rechercher un répertoire
import copie_usb        # version sans fenêtre
import re               # pour les expressions régulières

class copie_usb_window (copie_usb.copie_usb):
    """recopie des fichiers sur une clé USB avec une fenêtre graphique"""
    
    def chercher (self, s, titre) :
        """modifie un répertoire"""
        fs = selection_file.FileSelection (titre, chemin = s, file = False)
        r  = fs.run ()
        if r != None : return r
        else : return s
            
    def fenetre (self) :
        """change les paramètres de la classe par l'intermédiaire d'une fenêtre"""
        
        # définition de la fenêtre
        root            = Tk.Tk ()

        source          = Tk.Entry (width = 100)
        source_label    = Tk.Label (text = "répertoire source")
        source_label.grid (column = 0, row = 0)
        source.grid (column = 1, row = 0)
        
        dest            = Tk.Entry (width = 100)
        dest_label      = Tk.Label (text = "répertoire destination")
        dest_label.grid (column = 0, row = 1)
        dest.grid (column = 1, row = 1)
        
        filtre_accept   = Tk.Entry (width = 100)
        accept_label    = Tk.Label (text = "filtre pour les fichiers acceptés")
        filtre_accept.grid (column = 1, row = 2)
        accept_label.grid (column = 0, row = 2)

        filtre_refuse   = Tk.Entry (width = 100)
        refuse_label    = Tk.Label (text = "filtre pour les fichiers refusés")
        filtre_refuse.grid (column = 1, row = 3)
        refuse_label.grid (column = 0, row = 3)
        
        def chercher_source () : 
            s = source.get ()
            i = len (s)
            s = self.chercher (s, "répertoire source")
            source.delete (0, i)
            source.insert (0,s)
            
        def chercher_dest () :   
            s = dest.get ()
            i = len (s)
            s = self.chercher (s, "répertoire source")
            dest.delete (0, i)
            dest.insert (0,s)
        
        def copier () :   
            self.ch1    = source.get ()
            self.ch2    = dest.get ()
            self.accept = re.compile (filtre_accept.get ())
            self.refuse = re.compile (filtre_refuse.get ())
            self.copie ()
            
        brepsource      = Tk.Button (text = "chercher", command = chercher_source)
        brepdest        = Tk.Button (text = "chercher", command = chercher_dest)
        brepsource.grid (column = 2, row = 0)
        brepdest.grid (column = 2, row = 1)

        bfermer         = Tk.Button (text = "Fermer", command = root.destroy)
        bfermer.grid (column = 2, row = 4)
        bcopier         = Tk.Button (text = "Copier", command = copier)
        bcopier.grid (column = 2, row = 3)
        
        root.wm_title ("copie de fichiers vers une clé USB")
        
        source.insert (0, self.ch1)
        dest.insert (0, self.ch2)
        filtre_accept.insert (0, self.accept.pattern)
        filtre_refuse.insert (0, self.refuse.pattern)
        
        root.mainloop ()
        
        
if __name__ == "__main__" :
    print "copie de fichiers vers une clé USB"
    ch1             = "C:\\Documents and Settings\\Dupré\\" \
                        "Mes documents\\informatique\\support\\python_td"
    ch2             = "c:\\temp\\copie_usb"
    filtre_accept   = ".*[.].*"
    filtre_refuse   = ".*[.]pdf$|.*[.]html$|.*[.]bmp|programme\\\\.*[.]zip$"
    
    # filtre_accept accepte tout type de fichier
    # filtre_refuse refuse tous les fichiers dont l'extension est pdf, html ou 
    # inclus dans le répertoire programme et ayant l'extension zip
    
    c = copie_usb_window (ch1, ch2, filtre_accept, filtre_refuse)
    c.fenetre ()
    
    


File: usb_window_save.tex, line 15


# ouverture fichier essai.txt en mode écriture
f = open ("essai.txt", "w")
# écriture d'une chaîne de caractères dans le fichier
f.write ("première ligne")
# passage à la ligne
f.write ("\n")
# fermeture du fichier
f.close ()

File: usb_window_save.tex, line 30


# ouverture fichier essai.txt en mode lecture
f = open ("essai.txt", "r")
# lecture de la première ligne du fichier
s = f.readline ()
# on enlève de la chaîne de caractères s le symbole de fin de ligne
s = s.replace ("\n", "")
# affichage de s
print s
# fermeture du fichier
f.close ()

copie de fichiers, sauvergarde des paramètres

# coding: cp1252
"""copie de fichiers sur une clé USB, interface fenêtrée, 
enregistrement des paramètres précédents"""

import copie_usb_window   # version avec fenêtre
import os.path            # pour détecter l'existence d'un fichier
import re                 # pour les expressions régulières

class copie_usb_window_save (copie_usb_window.copie_usb_window):
    """recopie des fichiers sur une clé USB avec une fenêtre graphique,
    et enregistrement des précédents paramètres"""

    def ecrire_parametre (self, txt) :
        """écriture des paramètres dans le fichier txt"""
        # ouverture du fichier en mode écriture
        f = open (txt, "w")
        f.write (self.ch1)
        f.write ("\n")
        f.write (self.ch2)
        f.write ("\n")
        f.write (self.accept.pattern)
        f.write ("\n")
        f.write (self.refuse.pattern)
        f.write ("\n")
        f.close ()
        
    def lire_parametre (self, txt) :
        """relecture des paramètres écrits dans le fichier txt s'il existe"""
        if os.path.exists (txt) :
            f           = open (txt, "r")
            
            s           = f.readline ()
            s = s.replace ("\n", "")
            self.ch1    = s
            
            s           = f.readline ()
            s = s.replace ("\n", "")
            self.ch2    = s
            
            s           = f.readline ()
            s = s.replace ("\n", "")
            self.accept = re.compile (s)
            
            s           = f.readline ()
            s = s.replace ("\n", "")
            self.refuse = re.compile (s)
            
            f.close ()

    def fenetre (self) :
        """méthode fenêtre surchargée pour lire les derniers paramètres
        et enregistrer les nouveaux"""
        # première étape, lire les précédents paramètres
        self.lire_parametre ("copie_usb_window_save.txt")
        # seconde étape, appel de la méthode précédente
        copie_usb_window.copie_usb_window.fenetre (self) 
        # troisième étape, écriture des paramètres
        self.ecrire_parametre ("copie_usb_window_save.txt")
        
        
if __name__ == "__main__" :
    
    print "copie de fichiers vers une clé USB"
    ch1             = "C:\\Documents and Settings\\Dupré\\" \
                        "Mes documents\\informatique\\support\\python_td"
    ch2             = "c:\\temp\\copie_usb"
    filtre_accept   = ".*[.].*"
    filtre_refuse   = ".*[.]pdf$|.*[.]html$|.*[.]bmp|programme\\\\.*[.]zip$"
    
    # filtre_accept accepte tout type de fichier
    # filtre_refuse refuse tous les fichiers dont l'extension est pdf, html ou 
    # inclus dans le répertoire programme et ayant l'extension zip
    
    c = copie_usb_window_save (ch1, ch2, filtre_accept, filtre_refuse)
    c.fenetre ()
    

File: debutant_common_part.tex, line 4


# coding : latin-1    
nom_prenom = "Xavier Dupré"

File: debutant_common_part.tex, line 11


i      = 3                       # i=3 mais on fait référence au 4ème caractère
valeur = ord ( nom_prenom [i] ) 

File: debutant_common_part.tex, line 23


def somme_caractere (nom_prenom) :
    ...
    return ...

File: debutant_common_part.tex, line 31


s   = somme_caractere ("Xavier Dupre") % 200
url = "http://www.xavierdupre.fr/enseignement/tutoriels_data/tutoriel_%d.py" % s
print url

File: debutant_common_part.tex, line 39


from tutoriel_99.py import *

File: debutant_tri.tex, line 16


0.56  # position i   --> tri [i]
0.43  # position i+1 --> tri [i+1]

File: debutant_tri.tex, line 23


def permutation ( tri, ...) :
    ...

File: debutant_tri.tex, line 30

 
tri = ....
for i in xrange (0, len (n)-1) :
    permutation (tri, ...)

File: debutant_tri.tex, line 40

 
tri = ....
for i in xrange (0, len (n)-1) :
    permutation (tri, ...)
for i in xrange (0, len (n)-1) :
    permutation (tri, ...)

File: debutant_tri.tex, line 50


def tri_bulle (tri) :
    ...
    
tri_bulle (tri)
for el in tri :
    print el

File: debutant_tri.tex, line 63


m    = len(tri)/2

tri1 = tri [0:m]
tri2 = tri [m:len(tri)]

tri_bulle(tri1)
tri_bulle(tri2)

File: debutant_tri.tex, line 79


def fusion (tri1, tri2) :
    res = []
    i1  = 0
    i2  = 0
    while i1 + i2 < len (tri1) + len(tri2) :
       if tri1 [i1] < tri2 [i2] :
           res.append ( tri1 [i1] )
           ...
       else :
           res.append ( tri2 [i2] )
           ...
    return res

File: debutant_tri.tex, line 102


m    = len(tri)/4

tri1 = tri [0:m]
tri2 = tri [m:2*m]
tri3 = tri [2*m:3*m]
tri4 = tri [3*m:len(tri)]

tri_bulle(tri1)
tri_bulle(tri2)
tri_bulle(tri3)
tri_bulle(tri4)

...

déterminer la taille des poissons

# coding: cp1252
import poisson
#import scipy.optimize.lbfgsb as Opt    # optimisation
import bfgs                      # optimisation
import numpy as Num           # pour les tableaux
import psyco

def fonction_bfgs (x, cl, l) :
    """fonction retournant l'opposé de la log-vraisemblance 
    de l'instance cl, fonction à minimiser"""
    cl.set (x)
    f = - cl.log_densite_list (l)
    #print f, "\t", x
    return f
    
def fonction_derivee_bfgs (x, cl, l) :
    """fonction retournant l'opposé de la log-vraisemblance 
    de l'instance cl, fonction à minimiser"""
    cl.set (x)
    f           = cl.gradient_total (l)
    return - Num.array (f)

class poisson_loi_bfgs (poisson.poisson_loi) :
    """loi de distribution de la taille des poissons,
    optimisation à l'aide de l'algorithme BFGS"""
    
    def __init__(self, alpha = 0.5, mm = 1, sm = 1, mf = 1, sf = 1) :
        """initialisation des paramètres de la loi"""
        poisson.poisson_loi.__init__(self, alpha, mm, sm, mf, sf)
        
    def set (self, x) :
        """initialisation avec un tableau"""
        self.alpha    = x [0]
        self.mm       = x [1]
        self.sm       = abs (x [2])
        self.mf       = x [3]
        self.sf       = abs (x [4])
        
    def get (self) :
        """retourne un tableau contenant les paramètres"""
        return Num.array ( (self.alpha, self.mm, self.sm, self.mf, self.sf) ) 
        
    def __str__(self) :
        """affichage"""
        s = "classe poisson_loi BFGS\n"
        s += "alpha = " + str (self.alpha) + "\n"
        s += "moyenne male = " + str (self.mm) + "\n"
        s += "sigma male = " + str (self.sm) + "\n"
        s += "moyenne femelle = " + str (self.mf) + "\n"
        s += "sigma femelle = " + str (self.sf) + "\n"
        return s
        
    def optimisation (self, l, epsilon = 0.001) :
        """recherche du maximum de la fonction f"""
        self.init (l)
        x0     = self.get ()
        print x0
        opt    = bfgs.optimisation_bfgs (fonction_bfgs, \
                                        fonction_derivee_bfgs, \
                                        args = (self, l))
        x = opt.optimise (x0)
        #x      = bfgs.Opt.fmin_l_bfgs_b ( fonction_bfgs, \
        #                             x0, \
        #                             fonction_derivee_bfgs, \
        #                             args = (self, l))
        self.set (x)
        print "optimisation terminée"
        print "valeur maximale : ", self.log_densite_list (l)
        print "message ", d


if __name__ == "__main__" :
    psyco.full ()
    # création d'une instance de la classe        
    cl = poisson.poisson_loi (0.55, 0.40, 0.020, 0.35, 0.015)
    print cl                # affichage
    #cl.trace_densite ()     # courbe densité
    
    l = cl.generate (10000)
    cl2 = poisson_loi_bfgs ()
    print "-----------------------------------------------------------"
    print "log densité maximale ", cl.log_densite_list (l)
    (a,b,c,d,e) = cl.gradient_total (l)
    print "gradient idéal ", (a,b,c,d,e)
    print "-----------------------------------------------------------"
    
    (a,b,c,d,e) = cl2.gradient_total (l)
    print "gradient avant", (a,b,c,d,e)
    cl2.optimisation (l)
    (a,b,c,d,e) = cl2.gradient_total (l)
    print "gradient après ", (a,b,c,d,e)
    print "-----------------------------------------------------------"
    print cl2
    cl2.trace_densite (cl)
    print "log vraisemblance  : ", cl2.log_densite_list (l)

File: debutant_common_part.tex, line 4


# coding : latin-1    
nom_prenom = "Xavier Dupré"

File: debutant_common_part.tex, line 11


i      = 3                       # i=3 mais on fait référence au 4ème caractère
valeur = ord ( nom_prenom [i] ) 

File: debutant_common_part.tex, line 23


def somme_caractere (nom_prenom) :
    ...
    return ...

File: debutant_common_part.tex, line 31


s   = somme_caractere ("Xavier Dupre") % 200
url = "http://www.xavierdupre.fr/enseignement/tutoriels_data/tutoriel_%d.py" % s
print url

File: debutant_common_part.tex, line 39


from tutoriel_99.py import *

File: debutant_liste.tex, line 16


(1, 2) >  (0,9) 
(1, 2) >  (1,1) 
(1, 2) == (1, 2)
(1, 2) <  (2, 0)

File: debutant_liste.tex, line 28


[ 4.6,
  6.4,
  4.3,
  7.8 ]

File: debutant_liste.tex, line 37


[ (4.6, 1),
  (6.4, 2),
  (4.3, 3),
  (7.8, 4) ]

File: debutant_liste.tex, line 49


def ajoute_position (tableau) :
    ...
    return matrice

File: debutant_liste.tex, line 66


[ 4.6,    [ "rouge",
  6.4,      "bleu",
  4.3,      "rouge",
  7.8 ]     "bleu" ]

File: debutant_liste.tex, line 76


[ 4.3,    [ "rouge",
  4.6,      "rouge",
  6.4,      "bleu",
  7.8 ]     "bleu" ]

File: debutant_liste.tex, line 88


def rearrange_attribut (attribut, mat) :
    ...
    return nouveau_attribut

File: debutant_liste.tex, line 97


permutation = [ m[1]  for m in mat ]
nouveau     = [ -1    for i in permutation ]

for i in xrange (0, len (permutation)) :
    nouveau [ permutation [i] ] = i

File: debutant_liste.tex, line 113


import numpy                  # import du module numpy
mat  = numpy.array (pmat)     # on transforme une liste en liste en matrice format numpy
l, v = numpy.linalg.eig(mat)  # calcul des valeurs propres et vecteurs propres 
pl   = list (l)               # on tranforme un vecteur numpy en liste
pv   = list (v)               # on tranforme une matrice numpy en liste

File: debutant_liste.tex, line 126


l = range (1, 100)   # soit la liste [ 1, 2, 3, ..., 99 ] 

File: debutant_liste.tex, line 134


l = [ -3, -3, -3, -3, +3, +3, +3, +3, -2, ... ] 

File: debutant_liste.tex, line 140


d = { -3:4, +3:4, -2:10, +2:15, ... } 

déterminer la taille des poissons

# coding: cp1252
import poisson
#import scipy.optimize.lbfgsb as Opt    # optimisation
import bfgs                      # optimisation
import numpy as Num           # pour les tableaux
import psyco

def fonction_bfgs (x, cl, l) :
    """fonction retournant l'opposé de la log-vraisemblance 
    de l'instance cl, fonction à minimiser"""
    cl.set (x)
    f = - cl.log_densite_list (l)
    #print f, "\t", x
    return f
    
def fonction_derivee_bfgs (x, cl, l) :
    """fonction retournant l'opposé de la log-vraisemblance 
    de l'instance cl, fonction à minimiser"""
    cl.set (x)
    f           = cl.gradient_total (l)
    return - Num.array (f)

class poisson_loi_bfgs (poisson.poisson_loi) :
    """loi de distribution de la taille des poissons,
    optimisation à l'aide de l'algorithme BFGS"""
    
    def __init__(self, alpha = 0.5, mm = 1, sm = 1, mf = 1, sf = 1) :
        """initialisation des paramètres de la loi"""
        poisson.poisson_loi.__init__(self, alpha, mm, sm, mf, sf)
        
    def set (self, x) :
        """initialisation avec un tableau"""
        self.alpha    = x [0]
        self.mm       = x [1]
        self.sm       = abs (x [2])
        self.mf       = x [3]
        self.sf       = abs (x [4])
        
    def get (self) :
        """retourne un tableau contenant les paramètres"""
        return Num.array ( (self.alpha, self.mm, self.sm, self.mf, self.sf) ) 
        
    def __str__(self) :
        """affichage"""
        s = "classe poisson_loi BFGS\n"
        s += "alpha = " + str (self.alpha) + "\n"
        s += "moyenne male = " + str (self.mm) + "\n"
        s += "sigma male = " + str (self.sm) + "\n"
        s += "moyenne femelle = " + str (self.mf) + "\n"
        s += "sigma femelle = " + str (self.sf) + "\n"
        return s
        
    def optimisation (self, l, epsilon = 0.001) :
        """recherche du maximum de la fonction f"""
        self.init (l)
        x0     = self.get ()
        print x0
        opt    = bfgs.optimisation_bfgs (fonction_bfgs, \
                                        fonction_derivee_bfgs, \
                                        args = (self, l))
        x = opt.optimise (x0)
        #x      = bfgs.Opt.fmin_l_bfgs_b ( fonction_bfgs, \
        #                             x0, \
        #                             fonction_derivee_bfgs, \
        #                             args = (self, l))
        self.set (x)
        print "optimisation terminée"
        print "valeur maximale : ", self.log_densite_list (l)
        print "message ", d


if __name__ == "__main__" :
    psyco.full ()
    # création d'une instance de la classe        
    cl = poisson.poisson_loi (0.55, 0.40, 0.020, 0.35, 0.015)
    print cl                # affichage
    #cl.trace_densite ()     # courbe densité
    
    l = cl.generate (10000)
    cl2 = poisson_loi_bfgs ()
    print "-----------------------------------------------------------"
    print "log densité maximale ", cl.log_densite_list (l)
    (a,b,c,d,e) = cl.gradient_total (l)
    print "gradient idéal ", (a,b,c,d,e)
    print "-----------------------------------------------------------"
    
    (a,b,c,d,e) = cl2.gradient_total (l)
    print "gradient avant", (a,b,c,d,e)
    cl2.optimisation (l)
    (a,b,c,d,e) = cl2.gradient_total (l)
    print "gradient après ", (a,b,c,d,e)
    print "-----------------------------------------------------------"
    print cl2
    cl2.trace_densite (cl)
    print "log vraisemblance  : ", cl2.log_densite_list (l)

File: debutant_common_part.tex, line 4


# coding : latin-1    
nom_prenom = "Xavier Dupré"

File: debutant_common_part.tex, line 11


i      = 3                       # i=3 mais on fait référence au 4ème caractère
valeur = ord ( nom_prenom [i] ) 

File: debutant_common_part.tex, line 23


def somme_caractere (nom_prenom) :
    ...
    return ...

File: debutant_common_part.tex, line 31


s   = somme_caractere ("Xavier Dupre") % 200
url = "http://www.xavierdupre.fr/enseignement/tutoriels_data/tutoriel_%d.py" % s
print url

File: debutant_common_part.tex, line 39


from tutoriel_99.py import *

File: confirme_graph.tex, line 43


class MonGraphe :
    def __init__ (self, num, valeur) :
        self.valeur = valeur
        self.num    = num
        self.arcs   = [] # liste d’éléments MonGraphe

File: confirme_graph.tex, line 56


def ConstruireMonGraphe (noeuds, arcs) :
    ...
    return mongraphe

File: confirme_graph.tex, line 65


class MonGraphe :
    def NombreTotalNoeud (self) :
        r = 1
        for a in self.arcs :
            r += a.NombreTotalNoeud()
        return r

utilisation de Graphviz

# coding:latin-1
def import_Graphviz () :
    import os, urllib,struct
    files = [ "_graphviz_draw.exe"]
    if not os.path.exists (files[-1]) :
        # on télécharge les fichiers nécessaires d'abord
        for f in files :
            print "téléchargement de ", f
            url = "http://www.xavierdupre.fr/enseignement/tutoriel_python/graphviz/" + f
            u = urllib.urlopen (url, "rb")
            all = u.read ()
            if "404 Not Found" in all :
                raise Exception ("fichier introuvable")
            u.close ()
            u = open (f, "wb")
            u.write ( struct.pack ("c"*len(all), *all))
            u.close()
    if not os.path.exists (files[-1]) :
        raise Exception ("mauvais téléchargement")
    return files
    
def drawDiGraph (text, image) :
    f = open ("graph.gv", "w")
    f.write ( text )
    f.close ()
    
    files = import_Graphviz ()
    cmd = "%s . graph.gv %s png neato" % (files[-1], image)
    import os
    os.system (cmd)
        
def drawGraph (edges, image) :
    """
    dessine un graph en utilisant Graphviz (http://www.graphviz.org/
    edges = [ (1,2), (3,4), (1,3), ... ]  , liste d'arcs
    image = bom d'image (format png)
    """
    li = [ "digraph{" ]
    for i,j in edges :
        li.append ( "%d -> %d ;" % (i,j) )
    li.append ("};")
    text = "\n".join(li)
    drawDiGraph(text, image)
    
def drawGraphEdgesVertices (vertices, edges, image) :
    """
    dessine un graph en utilisant Graphviz (http://www.graphviz.org/
    edges    = [ (1,2, label, couleur), (3,4), (1,3), ... ]  , liste d'arcs
    vertices = [ (1, label, couleur), (2), ... ]  , liste de noeuds
    image = bom d'image (format png)
    """
    memovertex = { }
    for v in vertices :
        if len(v) == 1 : memovertex[v[0]] = None
        else : memovertex[v[0]] = v[1:]
    for edge in edges :
        i,j = edge[:2]
        if i not in memovertex : memovertex[i] = None
        if j not in memovertex : memovertex[j] = None
    
    li = [ "digraph{" ]
    for k,v in memovertex.iteritems() :
        if v == None : li.append("%s ;" % k)
        elif len(v) == 1 : li.append ("\"%s\" [label=\"%s\"];" % (k, v[0]))
        elif len(v) == 2 : li.append ("\"%s\" [label=\"%s\",fillcolor=%s,color=%s];" % (k, v[0], v[1], v[1]))
        else : raise Exception("unable to understand " + str(v))
            
    for edge in edges :
        i,j = edge[:2]
        if len (edge) == 2 : li.append ( "\"%s\" -> \"%s\" ;" % (i,j) )
        elif len (edge) == 3 : li.append ( "\"%s\" -> \"%s\" [label=\"%s\"];" % (i,j,edge[2]) )
        elif len (edge) == 4 : li.append ( "\"%s\" -> \"%s\" [label=\"%s\",color=%s];" % (i,j,edge[2],edge[3]) )
        else : raise Exception("unable to understand " + str(edge))
    li.append ("};")
    
    text = "\n".join(li)
    drawDiGraph(text, image)
    

if __name__ == "__main__" :
    drawGraph ([(1,2),(3,4), (1,3)], "image.png")
    drawGraphEdgesVertices ([(1,"eee","red")], 
                            [(1,2,"blue"),(3,4), (1,3)], "image2.png")
    

recherche du nom

#coding:latin-1

########## Question 1 ################

nom_prenom= "illotevtelo ChMa"

i=3
valeur= ord (nom_prenom [i])
print valeur
print ord('p')

########## Question 2 ################

r=0
for i in xrange(0,len(nom_prenom)):
	r += ord( nom_prenom [i] )
print r

########## Question 3 ################

def somme_caractere (nom_prenom):
	r=0
	for i in xrange(0,len(nom_prenom)):
		r += ord( nom_prenom [i] )
	return r
	
print somme_caractere (nom_prenom)

########## Question 4 ################

s = somme_caractere(nom_prenom) % 200
url = "http://www.xavierdupre.fr/enseignement/tutoriels_data/tutoriel_%d.py" % s
print url

clustering dans un graphe

#coding:latin-1
from tutoriel_119 import *

# tutoriel_graphe
noeuds = {0: 'fr\xe9quemment.', 1: 'je', 2: 'dit', 3: '\xeatre', 4: 'Code",', 5: 'incident', 6: 'dernier', 7: 'de', 8: '\xe0', 9: 'go\xfbt', 10: 'celui-l\xe0.', 11: 'pour', 12: 'plus', 13: 'prendre', 14: 'commenter', 15: '\xe9quilibr\xe9', 16: 'inconsciemment', 17: ':', 18: 'vous', 19: 'pr\xe9f\xe8re', 20: 'moyen', 21: 'doute,', 22: 'de', 23: 'les', 24: 'les', 25: "l'ann\xe9e", 26: 'se', 27: "c'est", 28: 'je', 29: 'am\xe9ricain.', 30: 'de', 31: 'raconter', 32: 'livre,', 33: 'se', 34: 'sarcasmes', 35: 'derni\xe8re', 36: 'ce', 37: '\xe0', 38: 'changent,', 39: 'une', 40: 'soutient', 41: 'sens', 42: 'est', 43: 'Minelli,', 44: 'est', 45: "n'ai", 46: 'est', 47: 'une', 48: '\xe7a,', 49: 'pour'}
arcs   = {(13, 22): None, (0, 7): None, (24, 4): None, (40, 41): None, (2, 22): None, (1, 6): None, (32, 31): None, (42, 35): None, (44, 34): None, (8, 24): None, (6, 7): None, (37, 48): None, (19, 14): None, (25, 26): None, (16, 22): None, (30, 42): None, (29, 34): None, (5, 3): None, (18, 20): None, (37, 41): None, (44, 39): None, (25, 38): None, (31, 38): None, (4, 16): None, (11, 0): None, (10, 24): None, (7, 5): None, (47, 40): None, (17, 20): None, (27, 40): None, (15, 24): None, (15, 1): None, (29, 37): None, (2, 17): None, (41, 45): None, (40, 35): None, (13, 23): None, (34, 41): None, (1, 12): None, (37, 44): None, (5, 14): None, (10, 14): None, (11, 15): None, (15, 16): None, (30, 45): None, (11, 16): None, (30, 32): None, (20, 3): None, (3, 11): None, (42, 47): None, (2, 12): None, (5, 1): None, (30, 43): None, (14, 22): None, (0, 21): None, (49, 41): None, (26, 29): None, (31, 47): None, (25, 43): None, (22, 7): None, (44, 46): None, (26, 33): None, (27, 44): None, (16, 23): None, (4, 14): None, (46, 27): None, (0, 9): None, (1, 19): None, (7, 18): None, (19, 23): None, (29, 46): None, (27, 31): None, (0, 8): None, (23, 24): None, (4, 11): None, (2, 7): None, (43, 39): None, (4, 6): None, (25, 37): None, (9, 23): None, (7, 4): None, (6, 20): None, (5, 20): None, (16, 20): None, (32, 42): None, (32, 39): None, (3, 15): None, (1, 3): None, (28, 29): None, (10, 15): None, (8, 19): None, (45, 48): None, (11, 14): None, (31, 30): None, (1, 20): None, (17, 15): None, (4, 20): None, (29, 40): None, (42, 44): None, (37, 46): None, (23, 15): None, (26, 46): None, (14, 23): None, (29, 48): None, (11, 13): None, (0, 22): None, (6, 18): None, (30, 47): None, (1, 23): None, (36, 46): None, (23, 20): None, (38, 46): None, (43, 49): None, (49, 38): None, (12, 0): None, (11, 8): None, (29, 32): None, (34, 36): None, (1, 18): None, (31, 45): None, (13, 18): None, (33, 42): None, (24, 13): None, (21, 7): None, (33, 31): None, (42, 49): None, (4, 10): None, (38, 43): None, (9, 22): None, (15, 31): None, (27, 42): None, (16, 21): None, (47, 39): None, (13, 8): None, (12, 16): None, (24, 0): None, (18, 19): None, (3, 8): None, (5, 12): None, (3, 14): None, (36, 31): None, (47, 26): None, (30, 38): None, (29, 38): None, (1, 24): None, (41, 46): None, (18, 24): None, (42, 45): None, (37, 45): None, (44, 29): None, (33, 47): None, (19, 20): None, (17, 4): None, (7, 9): None, (26, 27): None, (30, 35): None, (32, 37): None, (22, 5): None, (36, 45): None, (43, 26): None, (2, 15): None}
points = [(0.95267535699124162, 0.82560629131856578), (0.29648364156865914, 0.18050600487154633), (0.79996985136162935, 0.57893660071459829), (0.085376952582970955, 0.031034879282891392), (0.016348760649931293, 0.50115702327334655), (0.74771613576024176, 0.44138768803286821), (0.5492358527201977, 0.81850752511271008), (0.95542745148916108, 0.17816204660413593), (0.99050031891464319, 0.24851774111600722), (0.59460011551737468, 0.37389676235300828), (0.18654793854244078, 0.6840075536088509), (0.14657352787860223, 0.99366919091486383), (0.20017263306996014, 0.36275912353643147), (0.94074045424419872, 0.0072132133182595259), (0.61740384464135112, 0.43686790737625958), (0.66539931762342697, 0.55679917050743688), (0.45015730018055056, 0.31099714183225291), (0.12415928874693283, 0.71076075162623464), (0.68924309228021652, 0.31141865520722745), (0.10516400088906552, 0.58731899757629535), (0.12188375680883579, 0.51881747990793747), (0.07558429625479568, 0.043497856810040703), (0.13026049803968498, 0.54683395827968562), (0.52712532997481876, 0.17157989187856604), (0.45114145954948592, 0.70617762309961618), (0.56406777662890695, 0.71132385696741118), (0.55461691931730994, 0.29547405922511316), (0.099441144430514661, 0.36779227191569108), (0.49402620743521286, 0.35145024932175195), (0.63613038961532231, 0.51163660427562563), (0.55581345719517494, 0.071142652579506804), (0.33592381455203424, 0.42007024413872029), (0.40672043722017814, 0.056365679688573422), (0.62027382936709818, 0.35952751815993511), (0.71720130482031286, 0.92410962623683579), (0.32551467496845776, 0.065920384323213677), (0.84569564126604313, 0.23703980163205995), (0.42807674751831126, 0.054150904243620013), (0.64062636462843214, 0.15042491134125857), (0.48100807171343629, 0.14134222101625216), (0.40180636763784205, 0.99474182532249189), (0.27948653677901758, 0.71630115956590457), (0.15535336634912322, 0.34851408508671899), (0.45298028214932573, 0.32066296654826165), (0.44862985083939377, 0.30547670650187053), (0.029256933006530872, 0.73724241682736447), (0.15622132444455183, 0.21521612682099767), (0.11690710489512957, 0.4786251875596268), (0.50738236737590658, 0.51986175679349422), (0.55108314047038542, 0.57095630870069658), (0.73093092106169111, -3.9925338781977224), (1.9199614425637721, -4.9962543381481126), (4.0439915887357065, 3.8498484270922391), (-3.40709035308348, 0.39775864157910079), (4.0730819072938669, 3.2890212795827303), (-3.7742136951993408, -3.1123669548128072), (-4.9860229704641412, -0.33930202390130337), (1.1480453006246507, 5.3709879064645794), (4.0440299719273201, -3.1359324647302684), (-0.44887083769379277, -3.3799423541322735), (3.4398670515279557, 3.8334059332033497), (0.76952265995298075, -4.0625181910119244), (1.6956587062968544, -3.3744478144946441), (-0.10396158258453836, -5.0743258686216315), (-3.9534018707169429, -2.5038913982934172), (4.7680866941585229, 0.81715016175569477), (-0.42862569608862167, 5.8432707351932933), (1.518614059709694, 5.1977766227862325), (-1.1242218799970169, -4.6179402103967639), (-1.4258244150043791, -4.1685616113702944), (1.9409162750433124, -4.7404641006556236), (1.1435464790122816, 4.0279467283359454), (0.38121779630834041, 3.8382568106291739), (4.2044759346207483, -2.3148006282830065), (-5.7363326915308024, -2.9192244608795028), (3.2495073925554618, -4.0573216044653897), (0.32372336455076411, -3.9912555547264752), (-0.90791219358485331, 3.9787696565918154), (3.6256474234954226, 4.8226560186800373), (-3.8963553456339688, 1.1198210722224913), (3.3604780169461765, -3.5642594588211649), (1.687058366889852, -6.210927082177248), (-5.0088975511144023, 2.2360658464462815), (0.37106204009035448, -4.4457015129313913), (3.9649514458322459, -3.3070905420671415), (-1.8819631023110905, 3.3200252718097296), (-2.6843465848858159, 2.0533835595291654), (-3.2557819026437267, 1.5973998477974416), (4.6885709328444847, -1.2173870239662024), (2.404962474396116, 5.5064199228937731), (4.1216693489758471, -3.5030595862817462), (1.0944087405444316, 4.9129405674584641), (-5.9103174847844873, 1.9114254460109923), (-4.132188963311493, 1.4022043343548183), (-1.1020149832348243, 3.5636367949517318), (2.664931398644931, -4.3052248468766985), (-3.5601955924295829, -1.9443401692133171), (-4.201585463270586, -3.8511178493837335), (-4.5260781255083566, -1.3173319537940902), (-3.5520622021177473, 4.5357043246405819), (-2.3077280555810677, -2.6714981243721976), (-1.8571447222954365, -1.9519861881351419), (-3.2255068414551546, 3.1795664716329615), (-4.4482213664716559, -4.2185611163633974), (-3.9997974009755564, -2.5517555288239171), (-4.8699798695561576, -3.9692238738753982), (3.3151561188844925, -0.55206233883637235), (3.9438026346904129, -3.0304323218823326), (-4.7094073035463007, -3.8287671974811586), (2.1914918183775023, 1.1556602211075755), (2.239822051268634, -5.2980602701664683), (2.3595979948449535, -0.3398618231136934), (3.4516151992690514, -1.4120593478012067), (-4.1621980502057756, 1.8975419998882086), (2.7428097192268956, -0.30002875549521779), (4.3605014242243074, 1.3503549800798575), (5.2613590378052635, 2.1022774759999576), (3.6367225250843793, -3.1716591169498045), (4.6726118996244095, -1.2790433464904203), (4.9058044780104595, -2.1364525616895911), (0.069636008996937004, -2.5735387007511115), (-2.3129926401371748, -2.8967224927343578), (4.8127318966269534, -1.0852430298581375), (-4.3260746865404673, -1.5492672712798914), (2.302625177338677, -3.7148086473256443), (5.1338859559296068, 2.9533293912327001), (1.3625934799042121, 3.1298364974715676), (-4.5114122266499832, -3.3542526117819542), (-4.326594346630996, -1.7921498252383388), (2.7026843300795145, -0.014530189102330074), (-2.722907308307938, 2.7453464789348763), (-5.083591175043483, -0.30615128717542933), (-4.4586660147794506, -5.0971750441048398), (-2.2315188766141807, 1.9005390242378848), (-5.987594485873192, 2.4785543875512492), (1.1221786043911814, -4.0861810554465618), (4.1750084684753421, 1.6969862360709904), (3.6859080775408026, 6.1851460026850944), (2.9214278188299945, -2.9093405748617487), (3.7000980748880048, 3.1807433447418449), (-3.3630507245753694, -4.8588967519552382), (-0.26921474742305929, 4.9015232652416945), (3.1407992489793077, 2.501535088460213), (-4.6378352522239554, 0.71224131017907655), (2.9680366726671408, 3.8057463470229771), (-4.3923934213067932, -1.3791542744104026), (-4.2053686108626351, -3.6915210305842443), (-2.0746723787889829, -5.4464802222512967), (-4.0996534303685408, 3.3267880265107594), (-1.8128378443025992, -3.9344867995823476), (-3.2353459560678726, 0.0078487639308876256), (-5.2567050348371964, -2.8358582468324252), (-2.2350770635882338, 4.8035421802935794), (4.5454547247951318, 3.8505415523103865), (0.77852150481602367, -6.304360789570536), (2.8006251537057874, -3.4054180128674925), (0.80971629500490194, 3.8065008164142045), (-4.6893071013407308, 2.2137047680876876), (3.3741845332290392, 0.1809403893940662), (-3.2918652308459055, 0.090757607140976582), (-2.731021645889272, -1.6662800739451944), (4.1392456836843463, -2.6535938902245615), (0.46602710316953699, 2.1099910099056247), (-0.99288504381124265, -3.635131537333915), (-3.4662675388435948, -0.058701426738028029), (-2.9999952003703356, 0.97385236270124387), (3.2650338417095948, -3.8196135607333344), (-3.9456323778158917, 1.6498531850237104), (3.4959780062736767, -4.7693709944976597), (-6.3793247897778178, 3.7936917868316788), (-2.8361948828141816, -1.4723239541777753), (-3.4585466204767146, -3.8744844913637744), (2.960095790660457, -4.8884709834126614), (-1.2993953267806311, 4.0973104894384376), (-3.0970989922258405, 0.22866598184118958), (3.4437835364866913, -0.8809379622205642), (-1.2881813072780375, -4.1229601681474559), (5.4862812324101551, 1.836628009823206), (3.1236304949998903, -4.1524561478238979), (0.61467544773508809, -5.1189666093912951), (1.8730432423071945, -4.3249847084872606), (2.0752011951950715, -4.4488200981023773), (-5.3418920228459292, -2.9894449162072085), (0.88838354958991195, 4.7891995309050168), (-2.9815280097655044, 0.75974611993798513), (-4.4459283100583553, -2.8427774445017384), (-4.064198055377803, -0.26016925859548712), (3.9592858553113812, 5.7062659782102383), (-4.0776456770357399, -2.1108468150902038), (2.80041795823937, 3.9790775056847605), (0.78487223802603201, -4.2564317334246189), (-4.9580286073678153, -4.3043816295110746), (-2.7669760995888444, -2.5651126393631269), (-3.9254876523953905, -3.5085487626888177), (-3.7540103697600991, 3.7300659425632596), (3.6783559669906869, -2.351144064434612), (4.0933414500950187, 4.5060014596068578), (3.7335394329236813, 1.0973237757208787), (1.1442075030227594, -4.2316977637013782), (-3.6220150980624424, 3.185201907480816), (-2.2337125392446318, 4.3478035180013368), (2.6781697617925388, 2.2280922113698827), (-1.6681130570090124, 4.7186880822137711), (3.4525222878110728, 2.8129919629877103), (-4.2615596708093531, -2.7146058843073311), (-3.4402593724261346, -3.1673759335208658), (3.1774382402490873, -4.8863913791911475), (3.5356594608336036, -2.1183528278045651), (5.4668883824812955, 0.96389044748342978), (-3.6545253298129072, 1.191029553432321), (2.4693389761239732, -4.3812421972626314), (-4.7093027774610103, 3.965026191026729), (3.2404707985524244, 0.77619181600786824), (3.0540906215419827, -0.28806712267986057), (-3.6028130521113049, 1.935895100383537), (-3.3489404619836742, 2.4563658827640311), (-2.4889130194431983, -2.2068778228055628), (-4.8626794620087885, -2.8453503859189597), (-5.281369798564187, 3.5735280155556834), (1.6030813205100574, 3.5731475337773819), (-2.1025461390993794, 3.4422700241336504), (-4.2729514664802686, 0.98295236061849844), (-2.7317907928709642, 3.817432925064046), (-3.347758848146241, -2.5448741023523311), (0.8915743485505736, -2.2569697596670535), (3.5045925916795215, 3.2722443198059601), (3.5998395703577524, 3.2190081781102129), (1.4334706104985417, -4.0424849300410903), (-4.0667426219862737, -1.4761924494221059), (2.1740645996991859, -3.0289758518776351), (-2.4038443669649543, 3.0160752773304909), (-4.0303363017873819, 2.7543768490206029), (0.47537794879953099, 2.8085335721228395), (1.6413771309213714, -4.3558686770090542), (-5.1433034570264313, 1.9430061162740762), (1.8276873292623577, -3.6790602249992337), (4.1406942586495843, 1.3675393354116923), (3.3480076038224218, 4.721175565871162), (4.4634711149083595, -2.8871256008130279), (5.7357361409997534, 3.4008106446903601), (-3.0916329376751204, -4.0216467418174098), (-0.3493957952197404, -3.9951380224963402), (-4.7778083762237662, 0.26542128046507107), (1.403043362648535, -5.9337467353513125), (-3.8601684384095898, 2.4274964923790896), (-2.3093328988302524, 2.5925313771583451), (5.1033208593702017, -0.46327358367228422), (-4.1094019584172159, -2.6861910724662836), (-0.57183320351506084, -4.365390016818222), (-5.0613329560272344, -0.92832778971832219)]


###################################### Question 3 ################
#je définis une fonction qui va me servir pour NombreTotalNoeud
def action(a,liste):
		for e in a.arcs:
			if e not in liste:
				liste+=[e]
				action(e,liste)
	
	
class MonGraphe :
	def __init__ (self, num, valeur) :
		self.valeur = valeur
		self.num = num
		self.arcs = []
	def NombreTotalNoeud (self) :
		connus=[self]       #je définis ma liste de sommets connus
		for a in self.arcs: action(a,connus)   #j'applique l'action qui consiste à ajouter des sommets non connus
		return len(connus)
	def Degre (self):
		return len(self.arcs)

	
###################################### Question 4 ################




def ConstruireMonGraphe (noeuds, arcs):
	l = []
	for i in noeuds:
		l += [ MonGraphe(i,noeuds[i]) ]
	for (a,b) in arcs :
		l [a].arcs += [ l [b] ]
		l [b].arcs += [ l [a] ]
	return l
	
graphe = ConstruireMonGraphe(noeuds,arcs)

#definition d'une fonction pour afficher le graphe
def afficher(graphe):
	for e in graphe:
		print e.num, e.valeur, [a.num for a in e.arcs]
			
afficher(graphe)
#print '**********************'






###################################### Question 5 ################


 
#for i in xrange(0,len(graphe)):
#	print graphe[i].NombreTotalNoeud()

#cette fonction retourne une erreur car elle boucle sur elle-même
#si b est dans a.arcs alors elle se rappelle car a est dans b.arcs
#il faut retenir les noeuds déja traités

#voir question 3 pour la fonction corrigée
#sinon on peut faire le meme principe que pour le graphe sur les amis

###################################### Question 6 ################

#voir partie de la question 3



###################################### Question 7 ################

#l'algorithme permet de diminuer le nombre d'aretes
#ici il reviendrait à recouvrir avec le moinds d'aretes possibles
#mais il ne permet pas de faire ce qu'on veut
#une fois qu'on a l'arbre minimal, si on coupe on ne sait pas combien d'aretes on coupe en réalité


###################################### Question 8 ################

#voir dans la définition de class MonGraphe
#ou sinon
def Deg(numero):
	return len( graphe[numero].arcs )
	
print graphe[0].Degre()
print '*****************'



###################################### Question 9 ################

n=len(graphe)    #n*n sera la taille de la matrice
import numpy as np  
import scipy.linalg
M = np.matrix(  [[0 for i in xrange(0,n)] for j in xrange(0,n)]   )   #construction d'une matrice de 0 de taille n*n

#je définis une fonction qui me donne le coefficient i,j
def laplacien(i,j):
	if i==j : return graphe[i].Degre()
	elif graphe[j] in graphe[i].arcs: return -1
	else: return 0

#je modifie ma matrice en appliquant cette fonction
for i in xrange(0,n):
	for j in xrange(0,n):
		M[i,j] = laplacien(i,j)
		
#quelques vérifications
print M[2,2]
print Deg(2) 
print M[20,17]
print M[41,0]

###################################### Question 10 ################

#pour vérifier que toutes les sommes de ligne sont nulles
b=True
i=0
while b==True and i<n:
	if sum ( M[:,j] ) <>0: b=False
	i+=1
print b

V=np.matrix ( [1 for i in xrange(0,n) ])
#print M*V.transpose()

###################################### Question 11 ################

L,P = np.linalg.eig(M)
print L,P
P=P.transpose()
print P[2]
#print M*P[2].transpose()-L[2]*M

###################################### Question 12 ################

pos=[ (L[i],i) for i in xrange(0,len(L)) ]
pos.sort()
print pos
vecteursp= [ P[i] for (a,i) in pos ]
#le premier vecteur propre associé à une valeur propre non nulle est le 2e


V = vecteursp[1]
print V
	
#une fois qu'on a le vecteur propre en question
#on peut construire une liste pour chaque composante
compneg = []
comppos = []
for i in xrange(0,50):
	if V[0,i]<0 : compneg += [graphe [i]]
	else : comppos += [graphe [i]]

def nombre_arcs(sommet):
	def nombre_arcs_liste(comp):
		r=0
		for n in comp:
			if n in sommet.arcs : r += 1
		return r
	if sommet in compneg : return nombre_arcs_liste(comppos)
	else : return nombre_arcs_liste(compneg)
	
print [a.num for a in comppos], [a.num for a in compneg]

r=0
for sommet in graphe:
	if sommet in comppos:
		r+= nombre_arcs(sommet)
print r
	
r=0
for sommet in graphe:
	if sommet in compneg:
		r+= nombre_arcs(sommet)
print r

#pour savoir quelle est l'arête à couper
for a in comppos:
	for b in compneg:
		if a in b.arcs : print (a.num,b.num)

File: confirme_viterbi.tex, line 21


r   s t a i r   n t s 
r e s t a u r a n t

File: confirme_viterbi.tex, line 38


entier DistanceDeLevenshtein(caractere chaine1[1..longueurChaine1],
                             caractere chaine2[1..longueurChaine2])
   // d est un tableau de longueurChaine1+1 rangées et longueurChaine2+1 colonnes
   declarer entier d[0..longueurChaine1, 0..longueurChaine2]
   // i et j itèrent sur chaine1 et chaine2
   declarer entier i, j, coût
 
   pour i de 0 à longueurChaine1
       d[i, 0] := i
   pour j de 0 à longueurChaine2
       d[0, j] := j
 
   pour i de 1 à longueurChaine1
       pour j de 1 à longueurChaine2
           si chaine1[i] = chaine2[j] alors coût := 0
                                sinon coût := 1
           d[i, j] := minimum(
                                d[i-1, j  ] + 1,     // effacement
                                d[i,   j-1] + 1,     // insertion
                                d[i-1, j-1] + coût   // substitution
                             )
 
   retourner d[longueurChaine1, longueurChaine2]

File: confirme_viterbi.tex, line 68


d[i, j] := minimum(
                     d[i-1, j  ] + 1,     // effacement
                     d[i,   j-1] + 1,     // insertion
                     d[i-1, j-1] + coût   // substitution
                  )

File: confirme_viterbi.tex, line 78


e = d[i-1, j  ] + 1
i = d[i,   j-1] + 1
s = d[i-1, j-1] + coût
if s <= min (e,i) :                        # ligne A
    d [i, j] := s
    predecessor [i,j] = (i-1, j-1)
elif e < min (s,i) :
    d [i, j] := e
    predecessor [i,j] = (i-1, j)
else :
    d [i, j] := i
    predecessor [i,j] = (i, j-1)

distance de Levenstein et Viterbi

#HERMANT Bettina

#import-*-coding:cp1252-*
import numpy as np
import random

# PARTIE I 
# Question 1
def  DistanceDeLevenshtein(c1,c2) :
	d=[[0 for i in xrange(0,len(c2)+1)] for j in xrange(0,len(c1)+1)]
	for i in xrange(0,len(c1)) :
		d[i][0]=i
	for j in xrange(0,len(c2)) :
		d[0][j]=j
	for i in xrange(1,len(c1)+1) :
		for j in xrange(1,len(c2)+1) :
			if c1[i-1]==c2[j-1] :
				cout=0
			else : 
				cout=1
			d[i][j]=min(d[i-1][ j ] + 1, d[i][ j-1] + 1, d[i-1][ j-1] + cout)
	return d[len(c1)][len(c2)]
	
print DistanceDeLevenshtein("rstairnts","restaurant")
# On obtient bien une disctance de 4 pour l'exemple cité

# Question 2
def  DistanceDeLevenshtein2(c1,c2) :
	d=[[0 for i in xrange(0,len(c2)+1)] for j in xrange(0,len(c1)+1)]
	predecessor=[[(i-1,j-1) for j in xrange(0,len(c2)+1)] for i in xrange(0,len(c1)+1)]
	for i in xrange(0,len(c1)) :
		d[i][0]=i
	for j in xrange(0,len(c2)) :
		d[0][j]=j
	for i in xrange(1,len(c1)+1) :
		for j in xrange(1,len(c2)+1) :
			if c1[i-1]==c2[j-1] :
				cout=0
			else : 
				cout=1				
			e = d[i-1][ j ] + 1
			ins = d[i][j-1] + 1
			s = d[i-1][j-1] + cout
			if s < min (e,ins) :
				d [i][j] = s
				predecessor [i][j] = (i-1, j-1)
			elif e < min (s,ins) :
				d [i][ j] = e
				predecessor [i][j] = (i-1, j)
			else :
				d [i][j] = ins
				predecessor [i][j] = (i, j-1)
	print predecessor
	print i,j
	print predecessor[len(c1)][len(c2)]
	return d[len(c1)][len(c2)]
# predecessor permet d'avoir la trace des modifications effectuées sur le mot

# Question 3
#prodecessor[len(c1),(c2)] contient l'information sur la nature de la transformation donnant la dernière lettre du mot modifié

# Question 4

# PARTIE II

l1=[0.1,0.2,0.3,0.1,0.1,0.2]
l2=[0.3,0.1,0.1,0.1,0.1,0.3]
l3=[0.1,0.2,0.2,0.2,0.1,0.2]

# Question 5
def tirage(l) :
	#creation de la fonction de repartition
	m=[0 for i in xrange(0,7)]
	for i in xrange(0,6) :
		m[i+1]=m[i]+l[i]
	import random
	a=random.random()
	for i in xrange(0,6) : 
		if m[i]<a<m[i+1] :
			return i+1
print tirage(l1)

#Question 6
def simulation(l1,l2,l3) :
	l=[0,0,0]
	l[0]=tirage(l1)
	for i in xrange(0,2) :
		if l[i]==1 or l[i]==2 : l[i+1]=tirage(l1)
		if l[i]==3 or l[i]==4 : l[i+1]=tirage(l2)
		if l[i]==5 or l[i]==6 : l[i+1]=tirage(l3)
	return str(l)
	


print simulation (l1,l2,l3)

#Question 7
def sim10000() :
	sim=[simulation() for i in xrange(0,10000)]
	d={}
	for l in sim :
		d[l]=0
	for l in sim :
		d[l]+=1
	return d

# Question 8 
# P([6,6,6])=0.2*0.2*0.2=0.008

l=[l1,l2,l3]

#Question 9
def trivalues (d):
	l = [ (m,n) for (n,m) in d.iteritems () ]
	l.sort (reverse = True)
	l = [ (m,n) for (n,m) in l]
	return l

def proba() :
	p={}
	for i in xrange(1,7) :
		for j in xrange(1,7) :
			for k in xrange(1,7) :
				if j==1 or j==2 : p[i,j,k]=l[0][k-1]
				if j==3 or j==4 : p[i,j,k]=l[1][k-1]
				if j==5 or j==6 : p[i,j,k]=l[2][k-1]
				if i==1 or i==2 : p[i,j,k]*=l[0][j-1]
				if i==3 or i==4 : p[i,j,k]*=l[1][j-1]
				if i==5 or i==6 : p[i,j,k]*=l[2][j-1]		
				p[i,j,k]*=l[0][i-1]
	return trivalues (p)[0]

print proba()
# La sequence la plus probable est 313 avec une probabilite de 0.027

#PARTIE III
#Question 10
# Chaque proba ne dépend que du tirage précédent (et seulement de celui-ci). Ainsi la matrice du premier au second tirage sera la même que celle du second au troisième tirage.
a1=[l1,l1]
a2=[l2,l2]
a3=[l3,l3]
A=a1+a2+a3
print "A: \n", A

#PARTIE IV
#Question 11
#Il faut absolument que le premier tirage soit effectué avec le dé 1. On a donc S0(1)=1 et S0(2)=1 et les autres valeurs sont nulles. 
S=[[0 for j in xrange(0,6)] for i in xrange(0,4)]
for i in xrange(0,2) :
		S[0][i]=1
print "S: \n", S

#Question 12
def Sc(t,j) :
	a=max(S[t-1][i]*A[i][j] for i in xrange(0,6))
	return a           

#Question 13
for t in xrange(1,4) :
	for j in xrange(0,6) :
		S[t][j]=Sc(t,j)

print max(S[3])
print S[3].index(max(S[3]))+1
print np.array(S)
#La sequence la plus probable se termine par un 3 et pour probabilite 0.027.

#Question 14
def B(t,j) :
	l=[S[t-1][i]*A[i][j] for i in xrange(0,6)]
	a=max(l)
	b=l.index(max(l))
	return [a,b]

def seq_plus_probable(t) :
	S=[[0 for j in xrange(0,6)] for i in xrange(0,t+1)]
	R=[[0 for j in xrange(0,6)] for i in xrange(0,t-1)]
	for i in xrange(0,2) :
		S[0][i]=1
	for u in xrange(1,t+1) :
		for j in xrange(0,6) :
			S[u][j]=B(u,j)[0]
			if u>1 : R[u-2][j]=B(u,j)[1]
	print np.array(R)
	l=[]
	l+=[S[t].index(max(S[t]))+1]
	for i in xrange(t-2,-1,-1) :
		l+=[R[i][S[i+2].index(max(S[i+2]))]+1]
	l.reverse()
	return l
print seq_plus_probable(3)
# On retrouve bien que la séquence la plus probable est 3 1 3. 

#Question 15
# La première méthode est à proscrire car le nombre de lancés est trop faible pour obtenir un résultat cohérent. 

File: description_cours.tex, line 52


1.       Boucles, tests

2.       Fonctions, fichiers 1

3.       Fonctions, fichiers 2

4.       Présentation d’un tri

5.       Recherche dichotomique à l’aide d’un dictionnaire

6.       Classes 1

7.       Classes 2

8.       Calcul matriciel (implémentation de la régression)

9.       Chaînes de caractères, expression régulières

10.   Interfaçage, présentation des modules les plus utilisés

11.   Interface graphique

12.   Plus court chemin

13.   TD noté (à répartir sur deux autres séances)

Idéalement, le tutoriel s’appuierait sur un article pour bien montrer aux étudiants à quoi peut servir Python, sans toutefois trop s’éloigner du cours. Les TD devraient être également plus centrés sur les cœurs de métier ENSAE : stat ou éco.

File: recherche_dichotomique_minute.tex, line 19


x = 3
y = x + 5
print x
print x,y
# commentaire

File: recherche_dichotomique_minute.tex, line 34


i = 3                    # entier
r = 3.3                  # réel 
s = "exemple"            # chaîne de caractères   
c = (4,5)                # couple de valeurs (ou tuple)
l = [ 4, 5, 6.5]         # listes de valeurs ou tableaux
x = l [0]                # obtention du premier élément de la liste l
d = { "un":1, "deux":2 } # dictionnaire de valeurs
y = d ["un"]             # obtention de la valeur associée à l'élément "un"
couple = 4, 5            # collage de deux valeurs en un couple ou (tuple)
print type (l)           # on affiche le type de la variable l
mat = [ [0,1], [2,3] ]   # liste de listes
print mat [0][1]         # obtention du second élément de la première liste
n = None                 # None signifie que la variable existe mais qu'elle ne contient rien
                         # elle est souvent utilisé pour signifier qu'il n'y a pas de résultat
                         # car... une erreur s'est produite, une liste était vide...

File: recherche_dichotomique_minute.tex, line 54


i = 3
i = i + 5

File: recherche_dichotomique_minute.tex, line 63


print x + y          # addition
print x - y          # soustraction
print x / y          # division 
print x * y          # multiplication
print x % y          # modulo
print x == y         # égalité
print x < y          # inférieur
print x <= y         # inférieur ou égal
print min (x,y)      # minimum
print max (x,y)      # maximum
print zip (x,y)      # zip ( [4,5], ["a", "b"] ) donne [ (4,"a"), (5,"b") ]
                     # de deux listes, on passe à une sorte de matrice
print True and False # et logique
print True or False  # ou logique
print (5 < 4) or (5 > 4) # condition                   

File: recherche_dichotomique_minute.tex, line 83


print -x             # opposé   
print len ( [ 4,5] ) # obtention du nombre d'éléments d'une liste 
print not False      # négation

File: recherche_dichotomique_minute.tex, line 91


print [ 3,4 ] * 5
print "azerty" * 4
print 4 * "azerty" 
print [ 3,4 ] + (3,4) 

File: recherche_dichotomique_minute.tex, line 114


print int (3.4)
print list ( (4,5) )
print tuple ( [ 4,5] )
print dict ( [4,5] )
print str ( { "un":1, "deux":2 } )

File: recherche_dichotomique_minute.tex, line 125


x = 1.2
y = 1.2 * 6.55
print "Le prix de la baguette est ", x, "francs."
print "Le prix de la baguette est " + x + "francs."
print "Le prix de la baguette est " + str(x) + "francs."

File: recherche_dichotomique_minute.tex, line 142


l = [ 4, 6, 3, 4, 2, 9]  # n'importe quelle liste au hasard
l.sort ()
print l                  # le programme affiche la liste triée

File: recherche_dichotomique_minute.tex, line 152


for i in xrange (0, len (l)) :
    print l [i]

File: recherche_dichotomique_minute.tex, line 161


resultat = ...
for i in xrange (0, ...) :
    if ... > ... :
        resultat = False
        break
print "le tableau est-il trié : ", resultat

File: recherche_dichotomique_minute.tex, line 172


resultat = ...
i = ...
while i < ...
    if ... > ... :
        resultat = False
        break
print "le tableau est-il trié : ", resultat

File: tri_minute.tex, line 17


# première moyenne
poids = [1, 2, 1, 2]
notes = [12, 14, 8, 9] 
s = 0                             #
w = 0                             # 
for p,n in zip (poids, notes) :   # calcule du résultat
    s += p*n                      #
    w += p                        # 
resultat = s * 1.0 / w    # * 1.0 évite le problème dus aux divisions entières
                          # 1/2 --> 0,   1 * 1.0 / 2 --> 0.5
                          
# seconde moyenne                          
poids = [1, 1, 2]
notes = [12, 14, 8] 
s = 0
w = 0
for p,n in zip (poids, notes) :
    s += p*n
    w += p
resultat = s * 1.0 / w

File: tri_minute.tex, line 42


def moyenne_ponderee (poids, notes) :
    s = 0
    w = 0
    for p,n in zip (poids, notes) :
        s += p*n
        w += p
    return s * 1.0 / w        # le mot-clé return désigne le résultat que la fonction calcule

poids = [1, 2, 1, 2]
notes = [12, 14, 8, 9] 
resultat = moyenne_ponderee (poids, notes)


poids = [1, 1, 2]
notes = [12, 14, 8] 
resultat = moyenne_ponderee (poids, notes)

File: tri_minute.tex, line 74


def trie_tableau (tableau) :
    tableau.sort ()
    return tableau

tab = [ 3,5,4]
tri = trie_tableau (tab)
print tab
print tri

File: tri_minute.tex, line 92


def trie_tableau (tableau) :
    tableau.sort ()
    return tableau

tab = ( 3, 5, 4 ) 
tri = trie_tableau (tab)
print tab
print tri

File: tri_minute.tex, line 110


l = [ 4, 5, 3, 7, 7, 9, 10, 0 ]

File: tri_minute.tex, line 116


l.sort ()

File: tri_minute.tex, line 124


l = [ 4, 5, "ee", 7, "aa", 7, 9, 10, 0, "gg" ]

File: tri_minute.tex, line 131


print l [1]
print l [ len (l)-1 ]

File: tri_minute.tex, line 152


def permutation (l, i, j) :
    ...

File: tri_minute.tex, line 165


def comparaison_permutation (l, i) :
    ...

File: tri_minute.tex, line 173


for i in xrange (0, 10) : 
    print i

File: tri_minute.tex, line 180


def plusieurs_comparaison_permutation (l) :
    ...

File: tri_minute.tex, line 193


def n_fois_plusieurs_comparaison_permutation (l) :
    ...

File: vigenere_minute.tex, line 20


ABCDEFGHIJKLMNOPQRSTUVWXZ
BCDEFGHIJKLMNOPQRSTUVWXZA
CDEFGHIJKLMNOPQRSTUVWXZAB
DEFGHIJKLMNOPQRSTUVWXZABC
EFGHIJKLMNOPQRSTUVWXZABCD
FGHIJKLMNOPQRSTUVWXZABCDE
GHIJKLMNOPQRSTUVWXZABCDEF
HIJKLMNOPQRSTUVWXZABCDEFG
IJKLMNOPQRSTUVWXZABCDEFGH
JKLMNOPQRSTUVWXZABCDEFGHI
KLMNOPQRSTUVWXZABCDEFGHIJ
LMNOPQRSTUVWXZABCDEFGHIJK
MNOPQRSTUVWXZABCDEFGHIJKL
NOPQRSTUVWXZABCDEFGHIJKLM
OPQRSTUVWXZABCDEFGHIJKLMN
PQRSTUVWXZABCDEFGHIJKLMNO
QRSTUVWXZABCDEFGHIJKLMNOP
RSTUVWXZABCDEFGHIJKLMNOPQ
STUVWXZABCDEFGHIJKLMNOPQR
TUVWXZABCDEFGHIJKLMNOPQRS
UVWXZABCDEFGHIJKLMNOPQRST
VWXZABCDEFGHIJKLMNOPQRSTU
WXZABCDEFGHIJKLMNOPQRSTUV
XZABCDEFGHIJKLMNOPQRSTUVW
ZABCDEFGHIJKLMNOPQRSTUVWX
ABCDEFGHIJKLMNOPQRSTUVWXZ

File: vigenere_minute.tex, line 52


s = ""
for i in xrange (0,26) :
    s += chr (65+i)
print s

File: vigenere_minute.tex, line 66


lescodessecretsontjoueunrolediscretmaisimportantdanslhistoire
CODECODECODECODECODECODECODECODECODECODECODECODECODECODECODEC
NSV...

File: vigenere_minute.tex, line 74


def lettre_codee (lettre_message, lettre_cle, carre_vigenere) :
    ...
    return lettre_codee

File: vigenere_minute.tex, line 82


print chr(65)  # retourne la lettre correspondant au code 65 --> A
print ord("A") # retourne le code associé à la lettre "A" --> 65 

File: vigenere_minute.tex, line 96


def cryptage (message, cle, carre_vigenere) :
    ...
    return message_code

File: vigenere_minute.tex, line 111


f = open ("nom_de_fichier", "r")
text = f.read ()
f.close ()

File: vigenere_minute.tex, line 119


import urllib2
f = urllib2.urlopen ("http://www.gutenberg.org/files/30696/30696-h/30696-h.htm")
text = f.read ()

File: vigenere_minute.tex, line 127


import urllib2
req = urllib2.Request("http://www.gutenberg.org/files/30696/30696-h/30696-h.htm", headers={'User-Agent' : "Magic Browser"})  
f = urllib2.urlopen (req)
text = f.read ()

File: vigenere_minute.tex, line 147


h = { }
h ["A"] = 50
h ["B"] = 50
print h ["A"]
print h

File: vigenere_minute.tex, line 157


def histogramme_lettre (texte) :
    h = { }
    ...
    return h

File: langue_minute.tex, line 32


def normalise (dico) :
    # faire la somme en une ligne avec la fonction sum
    
    # diviser
    
    # fin
    return nouveau_dico

File: langue_minute.tex, line 75


import os
for fichier in os.listdir (".") :
    print fichier

File: carre_minute.tex, line 37


class CarreMagique :
    def __init__ (self, ...) :
        ...

File: carre_minute.tex, line 45


class CarreMagique :
    def __init__ (self, a,b,c, d,e,f, g,h,i) :
        self.carre = [ [ a,b,c ], [ d,e,f ], [ g,h,i ] ]

File: carre_minute.tex, line 53


c = CarreMagique ( 1,2,3, 4,5,6, 7,8,9 )

File: carre_minute.tex, line 59


print c.carre

File: carre_minute.tex, line 66


l = range (1,10)
c = CarreMagique ( l )

File: carre_minute.tex, line 74


class CarreMagique :
    def __init__ (self, a,b,c, d,e,f, g,h,i) :
        self.carre = [ [ a,b,c ], [ d,e,f ], [ g,h,i ] ]
        
c = CarreMagique (2,7,6, 9,5,1, 4,3,8)
print c        

File: carre_minute.tex, line 85


class CarreMagique :
    def __init__ (self, a,b,c, d,e,f, g,h,i) :
        self.carre = [ [ a,b,c ], [ d,e,f ], [ g,h,i ] ]
    def __str__ (self) :
        return "carre magique : " + str (self.carre)
        
c = CarreMagique (2,7,6, 9,5,1, 4,3,8)
print c        

File: carre_minute.tex, line 99


s = "un deux"
print s
s = "un \n deux"  # ajout du caractère \n
print s

File: carre_minute.tex, line 114


class CarreMagique :
    def __init__ (self, a,b,c, d,e,f, g,h,i) :
        self.carre = [ [ a,b,c ], [ d,e,f ], [ g,h,i ] ]
    def __str__ (self) :
        return "carre magique : " + str (self.carre)
        
    def somme_ligne (self, i) :                # ajout
        return sum ( self.carre [i] )          # ajout
        
c = CarreMagique (2,7,6, 9,5,1, 4,3,8)
print c.somme_ligne (0)   # somme des nombres sur la première ligne

File: carre_minute.tex, line 135


class CarreMagique :
    ...
    
    def carre_est_magique (self) :
        li   = [ self.somme_ligne (i) for i in xrange (0,3) ]
        lj   = [ self.somme_colonne (j) for j in xrange (0,3) ]
        diag = [ self.somme_diagonal (k) for k in xrange (0,2) ]
        tout = li + lj + diag
        tout.sort ()
        return .................

File: carre_minute.tex, line 163


d = {}
d [ 1,-1 ] = 1

File: carre_minute.tex, line 170


for i in xrange (0,9) :
    print i % 3           # affiche 0,1,2, 0,1,2, 0,1,2    

File: carre_minute.tex, line 208


class CarreMagique :
    ...
    def etape_damier_1 (self, dimension) :
        d = { }
        ...
        return d

File: carre_minute.tex, line 226


class CarreMagique :
    ...
    def damier_crenele (self, dimension) :
        d = self.etape_damier_1 ( dimension )
        self.carre = [ [ 0 for i in xrange (0, ... ) ] for j in xrange (0, ... ) ]
        ...
        
c = CarreMagique ([])
c.damier_crenele ()
print c
print c.carre_est_magique ()

File: graphe_minute.tex, line 26


coleman,frank
dana,lara
dana,melanie
dana,ralph
danny,dylan
dona,jenny
...

File: graphe_minute.tex, line 38


def lit_donnees_depuis_un_fichier_ou_internet (fichier) :
    """
    cette fonction lit un fichier où le télécharge depuis un site internet,
    si le fichier n'existe pas, il est téléchargé puis enregisté sur disque
    """
    if not os.path.exists (fichier) :
        url = "http://www.xavierdupre.fr/enseignement/complements/" + fichier
        import urllib2
        f = urllib2.urlopen (url)
        t = f.read()
        f.close()
        f = open(fichier, "w")
        f.write(t)
        f.close()

File: graphe_minute.tex, line 58


f = open (".......", "r")
lines = f.readlines ()
f.close ()

# la partie après le if sert à enlever les lignes vides
couples = [ l.strip(" \n\r").split ( ... ) for l in lines if ... ]

File: graphe_minute.tex, line 80


class Personne :
    def __init__ (self, nom):
        self.nom = nom
        self.amis = []
        
    def ajout_ami (self, ami) :
        self.amis.append (ami)

File: graphe_minute.tex, line 94


graph = { }
for prenom in liste_prenoms :
    graph [ prenom ] = Personne ( prenom )

File: graphe_minute.tex, line 102


for a,b in couples :
    graph [ ... ].ajout_ami ( ... )
    graph [ ... ].ajout_ami ( ... )

File: graphe_minute.tex, line 116


class Personne :
    ...
    def nombre_amis_amis(self) :
        nb = 0
        ....
        return nb 

chargement de données depuis internet

#coding:latin-1
import urllib, os, os.path
def charge_donnees () :
    if os.path.exists ("marathon.txt") :
        # si le fichier existe (il a déjà été téléchargé une fois)
        f = open ("marathon.txt", "r")
        text = f.read ()
        f.close ()
    else :
        # si le fichier n'existe pas
        link = "http://www.xavierdupre.fr/enseignement/complements/marathon.txt"
        url = urllib.urlopen (link)
        text = url.read ()
        # on enregistre les données pour éviter de les télécharger une seconde fois
        f = open ("marathon.txt", "w")
        f.write (text)
        f.close ()
        
    lines = text.split ("\n")
    lines = [ l.split("\t") for l in lines if len(l) > 3 ]
        
    # conversion en réel des données numérique
    for l in lines :
        l [1] = float(l[1])
        l [3] = float(l[3])
    return lines
    
if __name__ == "__main__" :
    matrice = charge_donnees ()
    print "nombre de lignes ", len(matrice)

dessin des données du marathon

# coding:latin-1
import marathon
# cette première ligne suppose que le programme de la la première question 
# a été enregistrée dans un fichier marathon.py
# il n'y a alors pas besoin de le recopier ici
import matplotlib
import matplotlib.pyplot as plt

def dessin (donnees, titre = "titre") :
    x = [ d[0] for d in donnees ]
    y = [ d[1] for d in donnees ]
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(x,y, 'o')
    ax.set_title(titre)
    plt.show()    

if __name__ == "__main__" :
    matrice = marathon.charge_donnees()
    mat      = [ (m[1], m[3]) for m in matrice ]
    dessin (mat)

File: regression_minute.tex, line 32


from marathon import *
import numpy as np

donnees = charge_donnees ()
mat = np.matrix(donnees)

File: regression_minute.tex, line 42


print mat.ndim
print mat.shape
print mat.size

File: regression_minute.tex, line 50


a = mat[0,0]
b = mat[:,0]
c = mat[0,:]
d = mat[4:10,:]
e = mat.transpose()

File: regression_minute.tex, line 61


ms = np.column_stack ( (mat[:,1], mat[:,3]))
ms = mat[:,[1,3]]  # seconde écriture

File: regression_minute.tex, line 67


ms * 3.0

File: regression_minute.tex, line 74


xy = np.matrix ( ms, dtype=float)
xy * 3.0

File: regression_minute.tex, line 81


print xy [ ... ].sum() / xy.shape [ ...]

File: regression_minute.tex, line 87


z   = np.zeros ( mat.shape[ ... ] )
mat = np.column_stack ( (mat, z))

File: regression_minute.tex, line 94


mat [:,4] = 1.0

File: regression_minute.tex, line 165


mat[ mat[:,0] == "PARIS" , 4 ] = nouvelle valeur

File: decorrelation_minute.tex, line 21


import random
import numpy as np

def combinaison () :
    x = random.gauss(0,1) # génère un nombre aléatoire
    y = random.gauss(0,1) # selon une loi normale
    z = random.gauss(0,1) # de moyenne null et de variance 1
    x2 = x
    y2 = 3*x + y
    z2 = -2*x + y + 0.2*z
    return [x2, y2, z2]
    
mat = [ ............. ]
npm = np.matrix ( mat )

File: decorrelation_minute.tex, line 40


npm = ...               # voir question précédente
t   = npm.transpose ()
a   = t * npm 
a  /= npm.shape[0]

File: decorrelation_minute.tex, line 57


import copy
b = copy.copy (a)    # remplacer cette ligne par b = a
b [0,0] = 44444444  
print b              # et comparer le résultat ici

File: decorrelation_minute.tex, line 67


def correlation ( npm ) :
    ..........
    return .....

File: decorrelation_minute.tex, line 104


L,P = np.linalg.eig(a)

File: decorrelation_minute.tex, line 112


print np.diag(L)

File: decorrelation_minute.tex, line 129


np.linalg.inv(a)

File: decorrelation_minute.tex, line 149


def simultation (N, cov) :
    # simule un échantillon de variables corrélées
    # N : nombre de variables
    # cov : matrice de covariance
    ...
    return M

chargement de v\oe ux des présidents depuis internet

#coding:latin-1
import urllib, os, os.path
def charge_discours () :
    discours = { }
    for annee in [2001, 2005, 2006, 2007, 2008, 2009, 1974, 1975,
                    1979, 1983, 1987, 1989, 1990, 1994] :
        nom = "VOEUX%02d.txt" % (annee % 100)
        if os.path.exists (nom) :
            # si le fichier existe (il a déjà été téléchargé une fois)
            f = open (nom, "r")
            text = f.read ()
            f.close ()
        else :
            # si le fichier n'existe pas
            link = "http://www.xavierdupre.fr/enseignement/td_python/" + \
                     "python_td_minute/data/voeux_presidents/" + nom
            url = urllib.urlopen (link)
            text = url.read ()
            # on enregistre les données pour éviter de les télécharger une seconde fois
            f = open (nom, "w")
            f.write (text)
            f.close ()
        
        discours [annee] = text
    return discours        
    
if __name__ == "__main__" :
    discours = charge_discours ()
    print "nombre de discours ", len(discours)

File: regex_minute.tex, line 21


import discours
textes = discours.charge_discours()

File: regex_minute.tex, line 28


import discours
textes = discours.charge_discours()

def somme_texte (textes):
    ...
    return ...

File: regex_minute.tex, line 39


accent = {     'à':'a', 'â':'a',  'ä':'a',  
                    'é':'e', 'è':'e', 'ê':'e', 'ë':'e',
                    'î':'i', 'ï':'i',
                    'ù':'u', 'û':'u', 'ü':'u',
                    'ô':'o', 'ö':'o',
                }
    
def pas_daccent (texte) :
    res = ""
    for c in texte :
        c = c.lower ()
        res += accent.get (c,c)
    return res

File: regex_minute.tex, line 59


def decoupe_mot (texte) :
    return ....

File: regex_minute.tex, line 65


def compte_mots (mots) :
    d = { }
    for mot in mots :
        ...
        ...
    return d

File: regex_minute.tex, line 75


def mot_tries (d):
    l = [ (n,m) for ... in d.iteritems () ]
    l.sort (reverse = True)
    return l

File: regex_minute.tex, line 88


def decoupe_mot2 (texte) :
    exp = re.compile ("\\w+", re.IGNORECASE)
    return exp.findall(texte)

File: regex_minute.tex, line 102


def trouver_expression(texte) :
    exp = re.compile ("je .{1,60}", re.IGNORECASE)
    return exp.findall(texte)

récupération de la définition d'un graphe

#coding:latin-1
import urllib, os, os.path
from importme import *
GV = import_module ("use_graphivz")
webhelper = import_module ("webhelper")
drawGraph = GV.drawGraphScript
graphviz_script = GV.graphviz_script

# coding:latin-1

def charge_donnees (file = "matrix_distance_7398.txt") :
    webhelper.import_module_or_file_from_web_site(file)
    f = open (file, "r")
    text = f.read ()
    f.close ()
    lines = text.split ("\n")
    lines = [ l.split("\t") for l in lines if len(l) > 1 ]
    return lines
    
def conversion_en_dictionnaire (lines) :
    res = { }
    for a,b,c in lines :
        c = int (c)
        res [a,b] = c
        res [b,a] = c
    return res
    
if __name__ == "__main__" :
    matrice_line = charge_donnees ()
    mat = conversion_en_dictionnaire (matrice_line)
    script = graphviz_script (mat)
    drawGraph([], script , "im.png")

File: meilleur_chemin_minute.tex, line 145


Fonction Dijkstra (nœuds, fils, distance, début, fin)
     Pour n parcourant nœuds
         n.parcouru = infini   // Peut être implémenté avec -1
         n.précédent = 0
     Fin pour
     début.parcouru = 0
     pasEncoreVu = nœuds
     Tant que pasEncoreVu != liste vide
         n1 = minimum(pasEncoreVu)   // Le nœud dans pasEncoreVu avec parcouru le plus petit
         pasEncoreVu.enlever(n1)
         Pour n2 parcourant fils(n1)                         // Les nœuds reliés à n1 par un arc
             Si n2.parcouru > n1.parcouru + distance(n1, n2) // distance correspond au 
                                                             // poids de l'arc reliant n1 et n2
                 n2.parcouru = n1.parcouru + distance(n1, n2)
                 n2.précédent = n1   // Dit que pour aller à n2, il faut passer par n1
             Fin si
         Fin pour
     Fin tant que
     chemin = liste vide
     n = fin
     Tant que n != début
         chemin.ajouterAvant(n)
         n = n.précédent
     Fin tant que
     chemin.ajouterAvant(debut)
     Retourner chemin
 Fin fonction Dijkstra

Pas 1

 
x = 5
y = 10
z = x + y
print (z)    # affiche z

Pas 2

 
x = 2
x = x + 1
print (x)    # affiche 3
x += 5
print (x)    # affiche 8

Pas 3

 
a = 0
for i in range (0, 10) :
    a = a + i             # répète dix fois cette ligne
print (a)   

Pas 4

  
a = 10
if a > 0 :
    print(a)     # un seul des deux blocs est pris en considération
else :
    a -=  1
    print (a)  	  

Pas 5

 
a = 10
print (a)     # quelle est la différence
print ("a")   # entre les deux lignes
s = "texte"
s += "c"
print (s)     

Pas à reculons 1


a = 5
a + 4
print (a)   # ou voudrait voir 9 mais c'est 5 qui apparaît

Pas à reculons 2


a = 0
for i in range (0, 10) 
    a = a + i
print (a)   

-


File "i.py", line 2
  for i in range (0, 10) 
                        ^
SyntaxError: invalid syntax  

Pas à reculons 3


a = 0
for i in range (0, 10) 
    a = a + i
  print (a)   

-


File "i.py", line 4
  print (a)   
             ^
IndentationError: unindent does not match any outer indentation level

Pas à reculons 4


a = 0
s = "e"
print (a + s)

-

 
Traceback (most recent call last):
	File "i.py", line 3, in <module>
	  print (a + s)
TypeError: unsupported operand type(s) for +: 'int' and 'str'

Pas à reculons 5

  
a = 0
for i in range (0, 10) :
	  a = (a + (i+2)*3
print (a)   

-

 
File "i.py", line 4
  print (a)   
      ^
SyntaxError: invalid syntax'

calcule la somme des 10 premiers entiers au carré


#coding:latin-1
s = 0
for i in range(1,11) :  # 11 car range va de 1 à 11 exclu
    s += i**2
print (s)

calcule la somme des 5 premiers entiers impairs au carré (1)


s = 0
for i in range(1,11) : 
    if i % 2 == 1 :
        s += i**2
print (s)

calcule la somme des 5 premiers entiers impairs au carré (2)


s = 0
for b in range(1,5) : 
    i = 2*b+1
    s += i**2
print (s)

somme des qui 10 premmières factorielles


s = 0
f = 1
for i in range(1,11) : 
    f *= i
    s += f
print (s)

types très simples

   
i = 3                    # entier = type numérique (type int)
r = 3.3                  # réel   = type numérique (type float)
s = "exemple"            # chaîne de caractères = type str (exemple n'est pas une variable)
n = None                 # None signifie que la variable existe mais qu'elle ne contient rien
                         # elle est souvent utilisée pour signifier qu'il n'y a pas de résultat
                         # car... une erreur s'est produite, il n'y a pas de résultat
                         # (racine carrée de -1 par exemple)

affectation, print

   
v = anything         # affectation
print ( v )          # affichage
v1, v2 = 5, 6        # double affectation

format

  
x,y = 4,5 
s = "addition"
print ( "{3} de {0} et {1} donne : {0} + {1} = {2}".format (x,y,x+y,s) )

File: seance2_boucle_test_var.tex, line 61

  
additition de 4 et 5 donne : 4 + 5 = 9

type d'une variable

   
print ( type ( v ) )           # affiche le type d'une variable
print ( isinstance (v, str) )  # pour déterminer si v est de type str

tableaux

   
c  = (4,5)                # couple de valeurs (ou tuple)
l  = [ 4, 5, 6.5]         # listes de valeurs ou tableaux
x  = l [0]                # obtention du premier élément de la liste l
y  = c [1]                # obtention du second élément
le = [ ]                  # un tableau vide

tableau : ajouter supprimer

   
l  = [ 4, 5 ]
l += [ 6 ]      # ajouter un élément
l.append ( 7 )  # ajouter un élément
l.insert (1, 8) # insérer un élément en seconde position
del l [0]       # supprimer un élément
del l [0:2]     # supprimer les deux premiers éléments

tableau : longueur d'un tableau et autres

   
l = [ 4, 5, 6 ]
print ( len(l) )    # affiche la longueur du tableau
print ( max(l) )    # affiche le plus grand élément
s = l * 3           # création de la liste [ 4, 5, 6, 4, 5, 6, 4, 5, 6 ]
t = s [ 4:7 ]       # extraction de la sous-liste de la position 4 à 7 exclu
s [4:7] = [ 4 ]     # remplacement de cette liste par [ 4 ]

boucle for

   
for i in range (0, 10) :   # on répète 10 fois
    print (i)              # l'affichage de i
    # ici, on est dans la boucle
# ici, on n'est plus dans la boucle

boucle while

   
i = 0
while i < 10 :
    print (i)
    i += 1

interruption d'une boucle

   
for i in range (0, 10) : 
    if i == 2 :
        continue           # on passe directement au suivant
    print (i)            
    if i > 5 :
        break              # interruption définitive

parcours d'une liste

   
l = [ 5, 3, 5, 7 ]
for i in range (0, len(l)) :
    print ("élément ",i, "=", l [ i ] ) 

parcours d'une liste sans indice

   
l = [ 5, 3, 5, 7 ]
for v in l :
    print ("élément ", v ) 

parcours d'une liste avec enumerate

   
l = [ 5, 3, 5, 7 ]
for i,v in enumerate(l) :
    print ("élément ",i, "=", v ) 

programme mystère

   
l = [ 4, 3, 0, 1, 2 ]
i = 0
while l[i] != i :
    i = l[i]
print (i)            # que vaut l[i] ?

un test

   
v = 2
if v == 2 :
    print ("v est égal à 2")
else :
    print ("v n'est pas égal à 2")

un test tronqué

   
v = 2
if v == 2 :
    print ("v est égal à 2")

plusieurs tests

   
v = 2
if v == 2 :
    print ("v est égal à 2")
elif v > 2 :
    print ("v est supérieur à 2")
else :
    print ("v est inférieur à 2")

liste non compacte

    
l = [ ]
for i in range (10) :
    l.append( i*2+1)

liste compacte

    
l = [ i*2+i for i in range(10) ]

notations abrégée

    
l = [ i*2 for i in range(0,10) ]
print (l)  # qu'affiche l ?

un exemple de liste

    
l = [ 3, 6, 2 , 7, 9 ]
x = 7

# ...

print ( position )

recherche de la position d'un élément

l = [ 3, 6, 2 , 7, 9 ]
x = 7

for i,v in enumerate(l) :
    if v == x :
        position = i

print ( position )

recherche dichotomique de la position d'un élément

# coding:latin-1
l = [2, 3, 6, 7, 9]
# si la liste n'est pas triée, il faut écrire : 
l.sort ()
x = 7

a = 0
b = len(l)-1
while a <= b :
    m = (a+b)//2  # ne pas oublier // sinon la division est réelle
    if l[m] == x : 
        position = m   # ligne A
        break
    elif l[m] < x :
        a = m+1
    else :
        b = m-1

print ( position )

# si le nombre qu'on cherche x n'est pas dans la liste,
# le programme produit l'erreur suivante car la ligne A n'est jamais exécutée :
"""
Traceback (most recent call last):
  File "seance2_recherche_dicho.py", line 19, in <module>
    print ( position )
NameError: name 'position' is not defined
"""
# soit n la longueur de la liste l
# le coût d'une recherche simple est en O(n)
# le coût d'une recherche dichotomique est en O(ln(n))

import d'un module


import math
print (math.cos(1))

from math import cos
print (cos(1))

from math import *    # cette syntaxe est déconseillée car il est possible qu'une fonction
print (cos(1))        # porte le même nom qu'une des vôtres

premier fichier : monmodule.py


import math

def fonction_cos_sequence(seq) :
    return [ math.cos(x) for x in seq ]
		
if __name__ == "__main__" :
    print ("ce message n'apparaîtra pas toujours")

second fichier : le programme principal


import monmodule

print ( monmodule.fonction_cos_sequence ( [ 1, 2, 3 ] )

écrire un fichier texte


mat = ...                                        # matrice de type liste de listes
with open ("mat.txt", "w") as f :                # création d'un fichier
    for i in range (0,len (mat)) :               # 
        for j in range (0, len (mat [i])) :      # 
            f.write ( str (mat [i][j]) + "\t")   # 
        f.write ("\n")                           # 

écrire un fichier texte (version condensée)


mat = ...                                        # matrice de type liste de listes
with open ("mat.txt", "w") as f :                # création d'un fichier
    f.write ( '\n'.join ( [   '\t'.join( [ str(x) for x in row ] ) for row in mat ] ) )

lecture d'un fichier texte


with open ("mat.txt", "r") as f :                # ouverture d'un fichier
    mat = [ row.strip(' \n').split('\t') for row in f.readlines() ]

contenu d'un répertoire


import os
for f in os.listdir('.'):
    print (f)

téléchargement des discours du président


import pyensae
discours = pyensae.download_data('voeux.zip', website = 'xd')

File: seance4_module_fichier_regexp.tex, line 170


[0-9]{4}/[0-9]{2}/[0-9]{2}

File: seance4_module_fichier_regexp.tex, line 174


a{2,10}

téléchargement de discours du président Sarkozy (issue de secours)

#coding:latin-1
import urllib.request, os, os.path
def charge_discours () :
    discours = { }
    for annee in [2001, 2005, 2006, 2007, 2008, 2009, 1974, 1975,
                    1979, 1983, 1987, 1989, 1990, 1994] :
        nom = "VOEUX%02d.txt" % (annee % 100)
        if os.path.exists (nom) :
            # si le fichier existe (il a déjà été téléchargé une fois)
            with open (nom, "r") as f :
                text = f.read ()
        else :
            # si le fichier n’existe pas
            link = "http://www.xavierdupre.fr/enseignement/td_python/" + \
            "python_td_minute/data/voeux_presidents/" + nom
            url = urllib.request.urlopen (link)
            text = url.read ().decode("latin-1")
            # on enregistre les données pour éviter de les télécharger une seconde fois
            with open (nom, "w") as f :
                f.write (text)
        discours [annee] = text
    return discours

if __name__ == "__main__" :
    discours = charge_discours ()
    print ("nombre de discours ", len(discours))

nombres aléatoires


import random
alea = [ random.random() for i in range(10) ]
print (alea)
random.shuffle(alea)
print (alea)

dates


from datetime import datetime
date1 = datetime(2013,9,9)
date0 = datetime(2013,8,1)
print (date1 - date0)
birth = datetime (1975,8,11)
print (birth.weekday())  # lundi

manipulation de colonnes et Excel


with open ("seance4_excel.txt", "r") as f :
    mat = [ row.strip(' \n').split('\t') for row in f.readlines() ]
    
mat = mat [1:]
res = [ [ None ] * 3 for i in range(5) ] 
for i,j,v in mat :
    res [ int(j)-1 ] [ int (i)-1 ] = float(v)

with open ("seance4_excel_mat.txt", "w") as f :
    f.write ( '\n'.join ( [   '\t'.join( [ str(x) for x in row ] ) for row in res ] ) )    

corrections de l'exercice sur les expressions régulières

		
import pyensae
discours = pyensae.download_data('voeux.zip', website = 'xd')

exp = re.compile ("je .{1,60}", re.IGNORECASE)
for d,text in discours.items() :
		je = exp.findall(text)    
		for t in je :
				print (t)
		print ("")

recherche des phrases commençant par je (issue de secours)

#coding:latin-1
import urllib.request, os, os.path, re
def charge_discours () :
    discours = { }
    for annee in [2001, 2005, 2006, 2007, 2008, 2009, 1974, 1975,
                    1979, 1983, 1987, 1989, 1990, 1994] :
        nom = "VOEUX%02d.txt" % (annee % 100)
        if os.path.exists (nom) :
            # si le fichier existe (il a déjà été téléchargé une fois)
            with open (nom, "r") as f :
                text = f.read ()
        else :
            # si le fichier n’existe pas
            link = "http://www.xavierdupre.fr/enseignement/td_python/" + \
            "python_td_minute/data/voeux_presidents/" + nom
            url = urllib.request.urlopen (link)
            text = url.read ().decode("latin-1")
            # on enregistre les données pour éviter de les télécharger une seconde fois
            with open (nom, "w") as f :
                f.write (text)
        discours [annee] = text
    return discours

if __name__ == "__main__" :
    discours = charge_discours ()
    print ("nombre de discours ", len(discours))
    
    exp = re.compile ("je .{1,60}", re.IGNORECASE)
    for d,text in discours.items() :
        je = exp.findall(text)    
        for t in je :
            print (t)
        print ("")

classe Point


class Point :
    def __init__ (self, x,y) :
        self.x = x
        self.y = y

instance Point


p = Point (4,5)

self ou moi


class Point :
    def __init__ (moi, x,y) :
        moi.x = x
        moi.y = y
				
p1 = Point(4,5)  # moi désigne p1 ici
p2 = Point(6,7)  # moi désigne p2 ici

print point


print (p1)
# affiche <__main__.Point object at 0x0288E470>

print x,y


print (p1.x, p1.y)

__str__


class Point :
    def __init__ (moi, x,y) :
        moi.x = x
        moi.y = y
    def __str__(moi):
        return "point: ({0},{1})".format(moi.x, moi.y)
p = Point(4,5)
print (p)  # affiche point: (4,5)

addition avec __add__


class Point :
    def __init__ (moi, x,y) :
        moi.x = x
        moi.y = y
    def __str__(moi):
        return "{0},{1}".format(moi.x, moi.y)
    def __add__(moi, autre_point) :
        return Point(moi.x + autre_point.x, moi.y + autre_point.y) 
p = Point(4,5)
print (p + p)   # affiche 8,10

classe CarreMagique


class CarreMagique :
    def __init__(self, ...) :
        ....
    def __str__(self) :
        ....
    def __add__(self) :
        ....

méthode norm


class Point :
    def __init__ (moi, x,y) :
        moi.x = x
        moi.y = y
    def norm(moi) :
        return (moi.x**2 + moi.y**2) ** 0.5
p = Point(4,5)
print (p.norm())

méthode norm


class Point :
    def __init__ (moi, x,y) :
        moi.x = x
        moi.y = y
    def norm(moi, lx = 2) :
        return (abs(moi.x)**lx + abs(moi.y)**lx) ** (1.0 / lx)
print (p.norm(1))
print (p.norm(2))
print (p.norm(3))
print (p.norm(100))

appel d'une méthode depuis une autre méthode


class Point :
    def __init__ (moi, x,y) :
        moi.x = x
        moi.y = y
    def norm(moi, lx = 2) :
        if lx == 0 : return moi.est_nul()
        else : return (abs(moi.x)**lx + abs(moi.y)**lx) ** (1.0 / lx)
    def est_nul(moi):
        return  moi.x == 0 and moi.y == 0

classe CarreMagique


class CarreMagique :
    def __init__(self, coef) :
        self.mat = [ [ coef[i+j*3] for i in range(3) ] for j in range(3) ]
    def __str__(self) :
        return "\n".join ( [ ",".join( [ str(n) for n in row ] ) for row in self.mat ] )
    def __add__ (self, carre) :
        coef = []
        for i in range(3) :
            for j in range(3) :
                coef.append ( self.mat[i][j] + carre.mat[i][j])
        return CarreMagique(coef)

c = CarreMagique ( [ 1,3,4, 2,6,9, 8,7,5 ] )
print (c)
print (c + c)

fonction est_magique


Fonction \codes{est\_magique}:
class CarreMagique :
    def __init__(self, coef) :
        self.mat = [ [ coef[i+j*3] for i in range(3) ] for j in range(3) ]
    def __str__(self) :
        return "\n".join ( [ ",".join( [ str(n) for n in row ] ) for row in self.mat ] )
    def __add__ (self, carre) :
        coef = []
        for i in range(3) :
            for j in range(3) :
                coef.append ( self.mat[i][j] + carre.mat[i][j])
        return CarreMagique(coef)

    def somme_ligne_colonne_diagonale(self):
        tout = [ sum ( ligne ) for ligne in self.mat ] + \
               [ sum ( [ self.mat[i][j] for j in range(3) ] ) for i in range(3) ] + \
               [ sum ( [ self.mat[i][i] for i in range(3) ] ) ] + \
               [ sum ( [ self.mat[2-i][i] for i in range(3) ] ) ] 
        return tout
        
    def coefficient_unique(self): 
        d = { }
        for ligne in self.mat :
            for c in ligne :
                d [c] = d.get(c,0) + 1
        return len(d) == 9
        
    def est_magique(self):
        unique = self.coefficient_unique()
        if not unique : return False
        somme = self.somme_ligne_colonne_diagonale()
        return min(somme) == max(somme) 
        

c = CarreMagique ( [ 1,1,1, 1,1,1, 1,1,1 ] )
print (c.est_magique())
c = CarreMagique ( [ 1,4,8, 5,2,6, 7,9,3 ] )
print (c.est_magique())

tous les carrés, de façon naïve (1)


def tous_les_carre_naif() :
    res = []
    for a1 in range(9) :
        for a2 in range(9) :
            for a3 in range(9) :
                for b1 in range(9) :
                    for b2 in range(9) :
                        for b3 in range(9) :
                            for c1 in range(9) :
                                for c2 in range(9) :
                                    for c3 in range(9) :
                                        carre = CarreMagique( [a1,a2,a3, b1,b2,b3, c1,c2,c3 ])
                                        if carre.est_magique() :
                                            res.append (carre)
                                            print (carre)
    return res

tous les carrés, de façon naïve (2)


def tous_les_carre_naif2() :
    # on choisit l'ensemble de tous les tableaux de 9 chiffres compris entre 1 et 9
    coef = [ 1 ] * 9
    res = [ ]
    while coef [0] < 10 :
        carre = CarreMagique(coef)
        if carre.est_magique() :
            res.append (carre)
            print (carre)
        coef[-1] += 1
        if coef[-1] >= 10 :
            i = len(coef)-1
            while coef[i] >= 10 and i > 0 :
                coef[i] = 1
                coef[i-1] += 1
                i -= 1

tous les carrés, permutation


#coding:latin-1
def tous_les_carres_permutation( permut = None, pos = 0):
    if pos == 9 :
        carre = CarreMagique (permut) 
        if carre.est_magique() :
            print (carre)
            print ()
            return [ carre ]
        else :
            return []
    else :
        res = [ ]
        if permut == None :
            permut = [ i+1 for i in range(9) ]
        for i in range (pos,9) :
            # on permute les éléments i et pos
            a = permut[i]
            permut[i] = permut[pos]
            permut[pos] = a

            res += tous_les_carres_permutation(permut, pos+1)
            
            # on effectue la permutation inverse
            a = permut[i]
            permut[i] = permut[pos]
            permut[pos] = a
        return res
        
       
res = tous_les_carres_permutation()
print ("nombre de carrés", len(res))

mesure du temps d'exécution


import time
d = time.clock()    
res = tous_les_carres_permutation()
d = time.clock() - d
print ("nombre de carrés", len(res), " en ", d)

carré magique, réduction du nombre de permutations évaluées


def tous_les_carres_permutation_ligne12_meme_somme( permut = None, pos = 0):
    if pos == 9 :
        carre = CarreMagique (permut) 
        if carre.est_magique() :
            #print (carre)
            #print ()
            return [ carre ]
        else :
            return []
    else :
        if pos >= 6 :                                       # ajout
            if sum ( permut[:3]) != sum(permut[3:6]) :      # ajout
                return [ ]                                  # ajout
        
        res = [ ]
        if permut == None :
            permut = [ i+1 for i in range(9) ]
        for i in range (pos,9) :
            # on permute les éléments i et pos
            a = permut[i]
            permut[i] = permut[pos]
            permut[pos] = a

            res += tous_les_carres_permutation_ligne12_meme_somme(permut, pos+1)  # changé
            
            # on effectue la permutation inverse
            a = permut[i]
            permut[i] = permut[pos]
            permut[pos] = a
        return res

parcours des carrés magiques, version complète

#coding:latin-1
class CarreMagique :
    def __init__(self, coef) :
        self.mat = [ [ coef[i+j*3] for i in range(3) ] for j in range(3) ]
    def __str__(self) :
        return "\n".join ( [ ",".join( [ str(n) for n in row ] ) for row in self.mat ] )
    def __add__ (self, carre) :
        coef = []
        for i in range(3) :
            for j in range(3) :
                coef.append ( self.mat[i][j] + carre.mat[i][j])
        return CarreMagique(coef)
        
    def somme_ligne_colonne_diagonale(self):
        tout = [ sum ( ligne ) for ligne in self.mat ] + \
               [ sum ( [ self.mat[i][j] for j in range(3) ] ) for i in range(3) ] + \
               [ sum ( [ self.mat[i][i] for i in range(3) ] ) ] + \
               [ sum ( [ self.mat[2-i][i] for i in range(3) ] ) ] 
        return tout
        
    def coefficient_unique(self): 
        d = { }
        for ligne in self.mat :
            for c in ligne :
                d [c] = d.get(c,0) + 1
        return len(d) == 9
        
    def est_magique(self):
        unique = self.coefficient_unique()
        if not unique : return False
        somme = self.somme_ligne_colonne_diagonale()
        return min(somme) == max(somme) 
        
def tous_les_carres_permutation_ligne12_meme_somme( permut = None, pos = 0):
    if pos == 9 :
        carre = CarreMagique (permut) 
        if carre.est_magique() :
            #print (carre)
            #print ()
            return [ carre ]
        else :
            return []
    else :
        if pos >= 6 :                                       # ajout
            if sum ( permut[:3]) != sum(permut[3:6]) :      # ajout
                return [ ]                                  # ajout
        
        res = [ ]
        if permut == None :
            permut = [ i+1 for i in range(9) ]
        for i in range (pos,9) :
            # on permute les éléments i et pos
            a = permut[i]
            permut[i] = permut[pos]
            permut[pos] = a

            res += tous_les_carres_permutation_ligne12_meme_somme(permut, pos+1)  # changé
            
            # on effectue la permutation inverse
            a = permut[i]
            permut[i] = permut[pos]
            permut[pos] = a
        return res
        
import time
d = time.clock()    
res = tous_les_carres_permutation_ligne12_meme_somme()
d = time.clock() - d
print ("nombre de carrés", len(res), " en ", d)

obtenir les données


import pyensae
file = pyensae.download_data("velib_vanves.zip", website = "xd")
print (file)   # affiche ['velib_vanves.txt']

aperçu des données


address	available_bike_stands	available_bikes	banking	bike_stands	bonus	contract_name	last_update	lat	lng	name	number	status	idr
112 RUE VERCINGETORIX - 75014 PARIS	65	2	0	67	0	Paris	15/07/2013 15:00	48,83425925	2,313391647	14029 - GERGOVIE VERCINGETORIX	14029	OPEN	669
112 RUE VERCINGETORIX - 75014 PARIS	65	2	0	67	0	Paris	15/07/2013 15:05	48,83425925	2,313391647	14029 - GERGOVIE VERCINGETORIX	14029	OPEN	1898
112 RUE VERCINGETORIX - 75014 PARIS	66	1	0	67	0	Paris	15/07/2013 15:10	48,83425925	2,313391647	14029 - GERGOVIE VERCINGETORIX	14029	OPEN	3127
112 RUE VERCINGETORIX - 75014 PARIS	66	1	0	67	0	Paris	15/07/2013 15:15	48,83425925	2,313391647	,.,

lecture des données avec pandas


import pandas
df = pandas.read_table(file, header = False, sep = "\t", decimal = ",")

accéder ou modifier une place de données


une_colonne = df.ix[:,"available_bikes"])

accéder ou modifier une place de données


mx_col = df["available_bikes"].max()      # maximum d'une colonne
mx_col = df.ix[:,"available_bikes"].max() # même maximum, autre écriture
mx = df.max()                             # maximum sur toutes les colonnes

décrire un dataframe


df.describe()

nombre de ligne d'un dataframe


len(df)

sous-ensemble d'un dataframe vérifiant une condition


zero =  df [ df["available_bikes"]==0 ]

ajouter deux colonnes


add = df["available_bikes"] + df["available_bike_stands"]

visualisation des données avec pandas


df = df.set_index("last_update")  # on identifie chaque ligne avec une date
import matplotlib.pyplot as plt   # module matplotblig
ts = df.ix[:,"available_bikes"]   # on extrait la série à dessiner
ts.plot()                         # on dessine
plt.show()                        # on affiche le dessin

sélection de deux colonnes


df2 = df.ix[:, ["last_update","available_bikes"]]

opérations avec les objets datetime


import datetime    
d = datetime.datetime.now()
print (d.weekday())
print (d.strftime("%H:%M"))
print (d.isocalendar())

exercice 1 : matrix de numpy


mat = numpy.matrix ( [ 0.0, 0.1, 0.3, 0.4 ] ).transpose()  # crée une matrice 4x1
print (mat [ 1:-1,:] )    # enlève la première et la dernière ligne
mat = mat + mat * 2.4     # fait des additions avec cette matrice

exercice 2 : conversion d'un DataFrame sous Excel


piv.to_excel("pivot.xlsx")  # cela nécessite le module openpyxl
# si celui n'est pas installé, il faut enregistré le fichier au format texte
piv.to_csv("pivot.txt", sep="\t")

exercice 2 : ajout de valeur NaN


piv.ix['4-16:00':,31] = numpy.NaN
# vous pouvez vérifier que sous Excel (en utilisant les lignes précédentes), 
# les cellules sont vides.

exercice 2 : autres fonctionnalités utiles


# on crée une matrice de type numpy.array
mx = numpy.array ( [ [ 10.0, 1.0], [2.0, 3.] ] )

# on calcule la moyenne de la première colonne
print ( numpy.average( mx[:,0] ))

# on remplace la première valeur par NaN
mx[0,0] = numpy.NaN

# on calcule la moyenne de la première colonne sans les valeurs NaN
print ( numpy.average( mx[~numpy.isnan(mx[:,0]),0]) )

# on utilise la fonction isnan car numpy.NaN != numpy.NaN est vrai
print ( numpy.NaN != numpy.NaN )  # aussi surprenant que cela soit

# on parcourt toutes les dates de la matrice obtenue après pivot :
for i,k in enumerate(piv.index) :
    print (i,k)

lire les données


import pandas
df = pandas.read_table(file, header = False, sep = "\t", decimal = ",", parse_dates = ["last_update"],
                       date_parser = lambda s : datetime.datetime.strptime (s, "%d/%m/%Y %H:%M"))

la première et la dernière dates


print ("min_date", df["last_update"].min())
print ("max_date", df["last_update"].max())

le nombre maximum de vélos et de places vides


print ("max velo", df["available_bikes"].max())
print ("max_place", df["available_bike_stands"].max())

la proportion du temps durant lequel la station n'a pas de vélos disponibles


print ("pas de vélo", len(df [ df["available_bikes"]==0 ]) / len(df) )

la proportion du temps durant lequel la station n'a pas de places disponibles


print ("pas de place", len(df [ df["available_bike_stands"]==0 ]) / len(df) )

le nombre d'emplacements de vélos à cette station


add = df["available_bikes"] + df["available_bike_stands"]
print (add.max())

visualisation des données avec pandas


import matplotlib.pyplot as plt
df = df.set_index("last_update")
ts = df.ix[:,"available_bikes"]
ts.plot()
plt.show()

seconde visualisation avec matplotlib


import numpy
from matplotlib.mlab import csv2rec
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
from matplotlib.ticker import Formatter

class MyFormatter(Formatter):
    def __init__(self, dates, fmt='%Y-%m-%d'):
        self.dates = dates
        self.fmt = fmt

    def __call__(self, x, pos=0):
        'Return the label for time x at position pos'
        ind = int(round(x))
        if ind>=len(self.dates) or ind<0: return ''

        return self.dates[ind].strftime(self.fmt)

formatter = MyFormatter(df["last_update"])

fig, ax = plt.subplots()
ax.xaxis.set_major_formatter(formatter)
ax.plot(numpy.arange(len(ts)), ts, '-')
fig.autofmt_xdate()
plt.show() 

ajouter une colonne contenant le jour de la semaine et l'heure


df2["weekday"] = df2['last_update'].map(lambda d: str(d.weekday()) + "-" + d.strftime("%H:%M"))

aligner les données par jour de la semaine


df2["weekno"] = df2['last_update'].map(lambda d: d.isocalendar()[1])
sp = "available_bikes weekday weekno".split()
sem = df2.ix[:,sp]
piv = sem.pivot ('weekday', "weekno", "available_bikes")

piv.plot()    # pour visualiser les données
plt.show()

exercice 1 : lissage


# on somme la série complète 12 fois mais décalé à chaque fois
nbperiod = 12
mat = numpy.matrix ( [0.0] * (len( df2 ) - nbperiod+1) ).transpose()
for i in range(0,nbperiod) :
    r = df2.ix[i:len(df2)-nbperiod+i,'available_bikes']
    m = numpy.matrix(list(r)).transpose()
    mat += m
mat /= 1.0 * nbperiod

# on élimine les premières et dernières valeurs
df2 = df2[nbperiod/2:-nbperiod/2+1]
df2["lisse"] = mat

# on répète la même manipulation pour superposer les semaines
sp = "lisse weekday weekno".split()
sem = df2.ix[:,sp]
piv = sem.pivot ('weekday', "weekno", "lisse")
piv.plot()
plt.show()

exercice 1 : lissage avec les fonctions évoluées de pandas


df2 = df.ix[:, ["last_update","available_bikes"]]

# on ajoute une colonne lissage qui contient la moyenne mobile sur 12 périodes via la fonction rolling_mean
df2["lissage"] = pandas.stats.moments.rolling_mean(df2["available_bikes"],12)

# on fait la meme transformation que dans l'exercice précédent pour afficher la valeur lissée par semaine, par timebox
df2["weekday"] = df2['last_update'].map(lambda d: str(d.weekday()) + "-" + d.strftime("%H:%M"))
df2["weekno"] = df2['last_update'].map(lambda d: d.isocalendar()[1])
serietemp = df2.ix[:,["lissage","weekday","weekno"]]
piv = serietemp.pivot ("weekday", "weekno", "lissage")
piv.plot() # pour visualiser les données
plt.show()

exercice 2 : données manquantes


beg = "4-16:00"
piv = thispiv 
piv.ix[beg:,31] = numpy.NaN
mx = numpy.array(piv.as_matrix())

for i,k in enumerate(piv.index) :
    if k >= beg and numpy.isnan(piv.ix[k,31]):
        ave_week = numpy.average( mx[~numpy.isnan(mx[:,2]),2]) 
        ave_hour = numpy.average( mx[i, ~numpy.isnan(mx[i,:])] ) 
        piv.ix[k,31] = (ave_week*ave_hour)**0.5
    
piv.plot()
plt.show()

obtenir les données


from pyensae import download_data
download_data("SQLiteSpy.zip", website = 'xd')  # 2 secondes
download_data("td8_velib.zip", website = 'xd')  # 22 secondes (~7 Mo)

obtenir les données


from pyensae import import_flatfile_into_database
dbf = "td8_velib.db3"
import_flatfile_into_database(dbf, "td8_velib.txt")                   # 2 secondes 
import_flatfile_into_database(dbf, "stations.txt", table="stations")  # 2 minutes

obtenir les données (2)


from pyensae import download_data
download_data("td8_velib.db3.zip", website = 'xd')  # 40 secondes (~12 Mo)

SELECT ... WHERE


-- sélectionner les données sur une plage horaire donnée
SELECT * FROM td8_velib WHERE last_update >= '2013-09-13 10:00:00' AND last_update <= '2013-09-13 11:00:00'

-- sélectionner certaines colonnes et ordonner les valeurs
SELECT available_bike_stands, available_bikes FROM td8_velib 
WHERE last_update >= '2013-09-13 10:00:00' AND last_update <= '2013-09-13 11:00:00'
ORDER BY available_bike_stands DESC ;

-- compter le nombre d'emplacements de chaque station
SELECT last_update, available_bike_stands + available_bikes AS place, number FROM td8_velib 
WHERE last_update >= '2013-09-13 10:00:00' AND last_update <= '2013-09-13 11:00:00'
ORDER BY place DESC ;

SELECT ... MIN, MAX


-- maximum de vélos disponibles sur toutes la base
SELECT MAX(available_bike_stands) FROM td8_velib

-- minimum, maximum de vélos disponibles sur toutes la base
SELECT MIN(available_bike_stands) FROM td8_velib 
UNION ALL 
SELECT MAX(available_bike_stands) FROM td8_velib 

-- ajouter des informations
SELECT "min" AS label, MIN(available_bike_stands) FROM td8_velib 
UNION ALL 
SELECT "max" AS label, MAX(available_bike_stands) FROM td8_velib 

SELECT DISTINCT COUNT FROM


-- tous les numéros de stations de façon unique
SELECT DISTINCT number FROM td8_velib

-- compter le nombre de stations (1230)
SELECT COUNT(*) FROM (
    SELECT DISTINCT number FROM td8_velib
)

nombre de vélo par date


SELECT last_update, SUM(available_bikes) AS velo_disponible
FROM td8_velib
GROUP BY last_update
ORDER BY last_update

GROUP BY, COUNT, DISTINCT


SELECT last_update, SUM(available_bikes) AS velo_disponible, COUNT(DISTINCT number) AS stations
FROM td8_velib
--WHERE last_update >= "2013-09-10 11:30:19"
GROUP BY last_update
ORDER BY last_update

deux clés


SELECT last_update, 
       CASE  WHEN available_bikes>0 THEN 1 ELSE 0 END AS vide, 
       COUNT(*) AS nb 
FROM td8_velib
WHERE last_update >= "2013-09-10 11:30:19"
GROUP BY last_update, vide
ORDER BY last_update

intersection entre deux tables


SELECT A.*, B.name  -- ajout du nom au bout de chaque ligne
FROM td8_velib AS A
JOIN stations AS B
ON A.number == B.number

distribution temporelle


SELECT A.*, 1.0 * A.available_bikes / B.nb_velo  AS distribution_temporelle
FROM td8_velib AS A
JOIN (
  SELECT number, SUM(available_bikes) AS nb_velo
  FROM td8_velib
	WHERE last_update >= "2013-09-10 11:30:19"
  GROUP BY number
) AS B
ON A.number == B.number
WHERE A.last_update >= "2013-09-10 11:30:19"

lire des données depuis une base de données SQLite3


import sqlite3
conn = sqlite3.connect(dbf)  # on ouvre une connexion sur la base de données
data = conn.execute("SELECT * FROM stations")  #on exécute une requête SQL
for d in data :    # on affiche le résultat
    print (d)      #  
conn.close()       # on ferme la connexion

compter le nombre de dates distinctes


SELECT COUNT(*) FROM (
    SELECT DISTINCT last_update FROM td8_velib
) ;

première et dernière date


SELECT MIN(last_update), MAX(last_update) FROM td8_velib ;

exercice 2


SELECT number, COUNT(*) AS nb 
FROM td8_velib
WHERE available_bikes==0 AND last_update >= '2013-09-10 11:30:19'
GROUP BY number
ORDER BY nb DESC

exercice 3 : plage horaires de cinq minutes où il n'y a aucun vélo disponible


SELECT nb, COUNT(*) AS nb_station
FROM (
  -- requête de l'exercice précédent
  SELECT number, COUNT(*) AS nb 
  FROM td8_velib
  WHERE available_bikes==0 AND last_update >= '2013-09-10 11:30:19'
  GROUP BY number
)
GROUP BY nb

exercice 4 : distribution horaire par station et par tranche de 5 minutes


SELECT A.number, A.heure, A.minute, 1.0 * A.nb_velo / B.nb_velo_tot  AS distribution_temporelle
FROM (
  SELECT number, heure, minute, SUM(available_bikes) AS nb_velo
  FROM td8_velib
  WHERE last_update >= '2013-09-10 11:30:19'
  GROUP BY heure, minute, number
) AS A
JOIN (
  SELECT number, heure, minute, SUM(available_bikes) AS nb_velo_tot
  FROM td8_velib
  WHERE last_update >= '2013-09-10 11:30:19'
  GROUP BY number
) AS B
ON A.number == B.number
--WHERE A.number in (8001, 8003, 15024, 15031)  -- pour n'afficher que quelques stations
ORDER BY A.number, A.heure, A.minute

Zone de travail et zone de résidence


SELECT number, SUM(distribution_temporelle) AS velo_jour
FROM (
  -- requête de l'exercice 4
	SELECT A.number, A.heure, A.minute, 1.0 * A.nb_velo / B.nb_velo_tot  AS distribution_temporelle
	FROM (
		SELECT number, heure, minute, SUM(available_bikes) AS nb_velo
		FROM td8_velib
		WHERE last_update >= '2013-09-10 11:30:19'
		GROUP BY heure, minute, number
	) AS A
	JOIN (
		SELECT number, heure, minute, SUM(available_bikes) AS nb_velo_tot
		FROM td8_velib
		WHERE last_update >= '2013-09-10 11:30:19'
		GROUP BY number
	) AS B
	ON A.number == B.number
)
WHERE heure >= 10 AND heure <= 16 
GROUP BY number

JOIN avec la table stations et les stations "travail"


SELECT C.number, name, lat, lng, velo_jour FROM 
(
  -- requête de la partie précédente
	SELECT number, SUM(distribution_temporelle) AS velo_jour
	FROM (
		-- requête de l'exercice 4
		SELECT A.number, A.heure, A.minute, 1.0 * A.nb_velo / B.nb_velo_tot  AS distribution_temporelle
		FROM (
			SELECT number, heure, minute, SUM(available_bikes) AS nb_velo
			FROM td8_velib
			WHERE last_update >= '2013-09-10 11:30:19'
			GROUP BY heure, minute, number
		) AS A
		JOIN (
			SELECT number, heure, minute, SUM(available_bikes) AS nb_velo_tot
			FROM td8_velib
			WHERE last_update >= '2013-09-10 11:30:19'
			GROUP BY number
		) AS B
		ON A.number == B.number
	)
	WHERE heure >= 10 AND heure <= 16 
	GROUP BY number
) AS C
INNER JOIN stations
ON C.number == stations.number 

récupération des données velib pour ce TD


from pyensae import download_data
import pandas

download_data("td9_data.zip", website = 'xd')
file1 = "td9_full.txt"
tbl = pandas.read_csv (file1, sep = "\t")

premier graphe


import pylab
from pandas.tools.plotting import scatter_plot

gr = tbl.groupby(['lat','lng'], as_index = False).agg(lambda x: len(x))
scatter_plot(gr, "lat", "lng" )
pylab.show()

fichier osm_essai.html


<html><body>
  <div id="mapdiv"></div>
  <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
  <script>
    map = new OpenLayers.Map("mapdiv");
    map.addLayer(new OpenLayers.Layer.OSM());
    var proj =  new OpenLayers.Projection("EPSG:4326");
 
    var zoom=16;
 
    var markers = new OpenLayers.Layer.Markers( "Markers" );
    map.addLayer(markers);
 
    var lonLat = new OpenLayers.LonLat( -0.1279688 ,51.5077286 ).transform(proj, map.getProjectionObject() );
    markers.addMarker(new OpenLayers.Marker(lonLat));

    var lonLat2 = new OpenLayers.LonLat( -0.1279688 ,51.5067286 ).transform(proj, map.getProjectionObject() );
    markers.addMarker(new OpenLayers.Marker(lonLat2));
 
    map.setCenter (lonLat, zoom);
  </script>
</body></html>

fichier osm_essai.html


# ... ajouter des choses ici
lines = [ ]
for i,row in enumerate(gr.values) :
    y = lat = row[1]
    x = lng = row[0]
    # utiliser i,x,y pour construire la ligne de javascript correspondant à la station i
    lines.append(line)
    
text = "\n".join( lines )
html = html.replace("__VELIB__", text)
with open("velib.html", "w") as f : f.write(html)

lancer directement le navigateur


import webbrowser
webbrowser.open(<url>)

File: seance9_d3js.tex, line 134


agatha,frank
agatha,toni
alice,andrew
alice,april
alice,bette
...

File: seance9_d3js.tex, line 145


var links = [
  {source: "Microsoft", target: "Amazon", type: "licensing"},
  {source: "Microsoft", target: "HTC", type: "licensing"},
  {source: "Samsung", target: "Apple", type: "suit"},
	// ...
	] ;

conversion des données d'un fichier texte au javascript

with open("td9_graph_lworld.txt", "r") as f :
    lines = f.readlines()
    
links =[]
for line in lines :
    spl = line.strip("\n\r ").split(",")
    if len(spl) == 2 :
        l = { "source":spl[0],"target":spl[1],"type":"-"}
        links.append(l)
        l = { "source":spl[1],"target":spl[0],"type":"-"}
        links.append(l)
        
with open("td9_graph_lworld.js", "w") as f :
    f.write ("var links = [\n")
    for l in links :
        f.write("{")
        f.write( ",".join ( [ "{0}:'{1}'".format (k,v) for k,v in l.items() ] ) )
        f.write("},\n")
    f.write("\n];\n")
    

lancer directement le navigateur


import pyensae
pyensae.download_data("td9_graph_lworld.zip", website = 'xd') 

astuce pour modifier le texte et sa taille


// bien placé, le code suivant modifie le texte affiché et sa taille
d3.select(this)
	.select("text")
			.style("font-size", "10px")
			.text(function(d,i){return d.name + "**" ;});

Utilisation d'OpenStreetMap pour visualiser des données

#coding:latin-1
import sys
sys.path.append("../../../../program/python/pyensae/src")  # ligne inutile

from pyensae import download_data
import pandas

download_data("td9_data.zip", website = 'xd')
file1 = "td9_full.txt"
tbl = pandas.read_csv (file1, sep = "\t")

from pandas.tools.plotting import scatter_plot

gr = tbl.groupby(['lng','lat'], as_index = False).agg(lambda x: len(x))

# voir http://dev.openlayers.org/docs/files/OpenLayers/Marker-js.html pour changer le marker
html = """
<html><body>
  <div id="mapdiv"></div>
  <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
  <script>
    map = new OpenLayers.Map("mapdiv");
    map.addLayer(new OpenLayers.Layer.OSM());
    var proj =  new OpenLayers.Projection("EPSG:4326");
 
    var zoom=13;
 
    var markers = new OpenLayers.Layer.Markers( "Markers" );
    map.addLayer(markers);
    
    __VELIB__
 
    map.setCenter (lonLat0, zoom);
  </script>
</body></html>    
"""

position ="""
    var lonLat{0} = new OpenLayers.LonLat( {1} ,{2} ).transform(proj, map.getProjectionObject() );
    markers.addMarker(new OpenLayers.Marker(lonLat{0}));
"""    

lines = [ ]
for i,row in enumerate(gr.values) :
    y = lat = row[1]
    x = lng = row[0]
    line = position.format(i,x,y)
    lines.append(line)
    
text = "\n".join( lines )
html = html.replace("__VELIB__", text)
with open("velib.html", "w") as f : f.write(html)

        


Les stations Vélib dans les zones de travail

#coding:latin-1
import sys
sys.path.append("../../../../program/python/pyensae/src")  # ligne inutile

from pyensae import download_data
import pandas

download_data("td9_data.zip", website = 'xd')
file1 = "td9_full.txt"
tbl = pandas.read_csv (file1, sep = "\t")

from pandas.tools.plotting import scatter_plot

gr = tbl.groupby(['lng','lat'], as_index = False).agg(lambda x: len(x))

# voir http://dev.openlayers.org/docs/files/OpenLayers/Marker-js.html pour changer le marker
html = """
<html><body>
  <div id="mapdiv"></div>
  <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
  <script>
    map = new OpenLayers.Map("mapdiv");
    map.addLayer(new OpenLayers.Layer.OSM());
    var proj =  new OpenLayers.Projection("EPSG:4326");
 
    var zoom=13;
 
    var markers = new OpenLayers.Layer.Markers( "Markers" );
    map.addLayer(markers);
    
    __VELIB__
 
    map.setCenter (lonLat0, zoom);
  </script>
</body></html>    
"""

position ="""
    var lonLat{0} = new OpenLayers.LonLat( {1} ,{2} ).transform(proj, map.getProjectionObject() );
    markers.addMarker(new OpenLayers.Marker(lonLat{0}));
"""    

lines = [ ]
for i,row in enumerate(gr.values) :
    y = lat = row[1]
    x = lng = row[0]
    line = position.format(i,x,y)
    lines.append(line)
    
text = "\n".join( lines )
html = html.replace("__VELIB__", text)
with open("velib.html", "w") as f : f.write(html)

        


Le réseau L-World

<!DOCTYPE html>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v2.js?2.9.1"></script>
<script src="td9_graph_lworld.js"></script>
<style>

.link {
  fill: none;
  stroke: #666;
  stroke-width: 1.5px;
}

.node circle {
  fill: #ccc;
  stroke: #fff;
  stroke-width: 1.5px;
}

text {
  font: 10px sans-serif;
  pointer-events: none;
}

</style>
<body>
<script>

var nodes = {};

// Compute the distinct nodes from the links.
links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
  link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});

var width = 960,
    height = 500;

var force = d3.layout.force()
    .nodes(d3.values(nodes))
    .links(links)
    .size([width, height])
    .linkDistance(60)
    .charge(-300)
    .on("tick", tick)
    .start();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var link = svg.selectAll(".link")
    .data(force.links())
  .enter().append("line")
    .attr("class", "link");

var node = svg.selectAll(".node")
    .data(force.nodes())
  .enter().append("g")
    .attr("class", "node")
    .call(force.drag);

node.append("circle")
    .attr("r", 8);

node.append("text")
    .attr("x", 12)
    .attr("dy", ".35em")
    .text(function(d) { return d.name; });

function tick() {
  link
      .attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

  node
      .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}

</script>

Le réseau L-World avec des événements

<!DOCTYPE html>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v2.js?2.9.1"></script>
<script src="td9_graph_lworld.js"></script>
<style>

.link {
  fill: none;
  stroke: #666;
  stroke-width: 1.5px;
}

.node circle {
  fill: #ccc;
  stroke: #fff;
  stroke-width: 1.5px;
}

text {
  font: 10px sans-serif;
  pointer-events: none;
}

</style>
<body>
<script>

var nodes = {};

// Compute the distinct nodes from the links.
links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
  link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});

var width = 960,
    height = 800;

var force = d3.layout.force()
    .nodes(d3.values(nodes))
    .links(links)
    .size([width, height])
    .linkDistance(30)
    .charge(-300)
    .on("tick", tick)
    .start();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var link = svg.selectAll(".link")
    .data(force.links())
  .enter().append("line")
    .attr("class", "link");

var node = svg.selectAll(".node")
    .data(force.nodes())
  .enter().append("g")
    .attr("class", "node")
    .on("mouseover", mouseover)   // on ajoute deux événements: la souris passe au-dessus d'un noeud
    .on("mouseout", mouseout) // la sortie sort de la zone du noeud
    .call(force.drag);   // pour qu'on puisse tirer les noeuds

node.append("circle")
    .attr("r", 8);

node.append("text")
    .attr("x", 12)
    .attr("dy", ".35em")
    .text(function(d) { return d.name; })
    .style("font-size", "10px")
   ;    

function tick() {
  link
      .attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

  node
      .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}

// la fonction suivante définit ce qui doit se passe au cas où le curseur passe au-dessus d'un noeud
function mouseover() {
  d3.select(this)
    .select("text")
        .style("font-size", "30px")
        .text(function(d,i){return "** " + d.name + " **" ;});
        
  d3.select(this)
    .style("fill", "red")
    .select("circle").transition()
      .duration(750)
      .attr("r", 16)
      .style("fill", "yellow");
}

// la fonction suivante définit ce qui doit se passe au cas où le curseur sort de la zone du noeud
function mouseout() {
  d3.select(this)
    .select("text")
        .style("font-size", "10px")
        .text(function(d,i){return d.name ;});
        
  d3.select(this)
      .style("fill", "grey")
    .select("circle").transition()
      .duration(350)
      .attr("r", 8)
      .style("fill", "grey");
}

</script>

Le fichier HTML contenant le code javascript.

<!DOCTYPE html>
<!-- http://jsfiddle.net/KSAbK/1/ -->
<!-- https://leanpub.com/D3-Tips-and-Tricks/read -->
<meta charset="utf-8">
<style>

body {
    font: 10px sans-serif;
}
.plot {
    fill: rgba(250, 250, 255, 0.6);
}
.grid .tick {
    stroke: lightgrey;
    opacity: 0.7;
}
.grid path {
    stroke-width: 0;
}
.axis path, .axis line {
    fill: none;
    stroke: #000;
    shape-rendering: crispEdges;
}
.x.axis path {
    display: none;
}
.line {
    fill: none;
    stroke: steelblue;
    stroke-width: 1.5px;
}

</style>
<body>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="td9_by_hours_data.js"></script>   <!-- the data, contains the variable data  used by the following script, it looks like the following -->
<!--
data = 
[
{'velo': 12817.0, 'last_update': '10/9/13 11:35', 'minute': 35.0, 'heure': 11.0, 'place': 25202.0, 'name': '10/9/13 11:35', 'roulant': 225.0, 'somme': 38019.0}
,{'velo': 12744.0, 'last_update': '10/9/13 11:40', 'minute': 40.0, 'heure': 11.0, 'place': 25273.0, 'name': '10/9/13 11:40', 'roulant': 227.0, 'somme': 38017.0}
...
] ;
-->
<script>

// defines the graph area (usually the same for for every graph)
margin = {
    top: 20,
    right: 20,
    bottom: 20,
    left: 45
};

width = 800 - margin.left - margin.right;
height = 500 - margin.top - margin.bottom;

// defines the range of each axis
var x = d3.time.scale()
    .domain(d3.extent(data, function (d) {
    return d.last_update;
}))
    .range([0, width]);

var y = d3.scale.linear()
    .domain(d3.extent(data, function (d) {
    return d.velo;
}))
    .range([height, 0]);

// graph type, also defines the columns to be used (last_update and velo in this case)
var line = d3.svg.line()
    .x(function (d) {
    return x(d.last_update);
})
    .y(function (d) {
    return y(d.velo);
});

// defines the function to call when zooming
var zoom = d3.behavior.zoom()
    .x(x)
    //.y(y)
    .on("zoom", zoomed);

// creates a svg section in the body section
svg = d3.select('body')
    .append("svg")
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
    .call(zoom);

svg.append("rect")
    .attr("width", width)
    .attr("height", height)
    .attr("class", "plot");

// two functions uses for the zoom
var make_x_axis = function () {
    return d3.svg.axis()
        .scale(x)
        .orient("bottom")
        .ticks(5);
};

var make_y_axis = function () {
    return d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(10);
};

// defines the axis
var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .ticks(10);

svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0, " + height + ")")
    .call(xAxis);

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .ticks(10);

svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

svg.append("g")
    .attr("class", "x grid")
    .attr("transform", "translate(0," + height + ")")
    .call(make_x_axis()
    .tickSize(-height, 0, 0)
    .tickFormat(""));

svg.append("g")
    .attr("class", "y grid")
    .call(make_y_axis()
    .tickSize(-width, 0, 0)
    .tickFormat(""));

// objects for the zooming
var clip = svg.append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", width)
    .attr("height", height);

var chartBody = svg.append("g")
    .attr("clip-path", "url(#clip)");

chartBody.append("path")
    .datum(data)
    .attr("class", "line")
    .attr("d", line);

// zooming functions
function zoomed() {
    //console.log(d3.event.translate);     // display information in the logging console of the browser (using developping tools)
    //console.log(d3.event.scale);
    svg.select(".x.axis").call(xAxis);
    svg.select(".y.axis").call(yAxis);
    svg.select(".x.grid")
        .call(make_x_axis()
        .tickSize(-height, 0, 0)
        .tickFormat(""));
    svg.select(".y.grid")
        .call(make_y_axis()
        .tickSize(-width, 0, 0)
        .tickFormat(""));
    svg.select(".line")
        .attr("class", "line")
        .attr("d", line);
}

</script>
</body>
</html>

données incluses dans un script javascript

data = 
[
{'velo': 12817.0, 'last_update': '10/9/13 11:35', 'minute': 35.0, 'heure': 11.0, 'place': 25202.0, 'name': '10/9/13 11:35', 'roulant': 225.0, 'somme': 38019.0}
,{'velo': 12744.0, 'last_update': '10/9/13 11:40', 'minute': 40.0, 'heure': 11.0, 'place': 25273.0, 'name': '10/9/13 11:40', 'roulant': 227.0, 'somme': 38017.0}
,{'velo': 12674.0, 'last_update': '10/9/13 11:45', 'minute': 45.0, 'heure': 11.0, 'place': 25349.0, 'name': '10/9/13 11:45', 'roulant': 221.0, 'somme': 38023.0}
,{'velo': 12646.0, 'last_update': '10/9/13 11:50', 'minute': 50.0, 'heure': 11.0, 'place': 25380.0, 'name': '10/9/13 11:50', 'roulant': 218.0, 'somme': 38026.0}
,{'velo': 12568.0, 'last_update': '10/9/13 11:55', 'minute': 55.0, 'heure': 11.0, 'place': 25457.0, 'name': '10/9/13 11:55', 'roulant': 219.0, 'somme': 38025.0}
// ... 
]
;

var parseDate = d3.time.format("%d/%m/%Y %H:%M").parse;

for (var i = 0; i < data.length; i++) {
    element = data[i] ;
    element['last_update'] = parseDate(element['last_update']) ;
}


récupération des données pour le plus court chemin


import pyensae
pyensae.download_data("matrix_distance_7398.zip", website  = "xd")

File: seance10_pdyn.tex, line 30


Boulogne-Billancourt	Beauvais	85597
Courbevoie	Sevran	26564
Colombes	Alfortville	36843
Bagneux	Marcq-En-Baroeul	233455
...

lire le fichiers des distance avec pandas


import pandas
df = pandas.read_csv("matrix_distance_7398.txt", sep="\t")
print (df.head())

choix aléatoires des skieurs et des paires


import random
skieur = [ random.gauss(1.75, 0.1) for i in range(0,10) ]
paires = [ random.gauss(1.75, 0.1) for i in range(0,15) ]
skieurs.sort()
paires.sort()

récupération de la liste des villes (sans doublons)


vil = { }
for row in df.values :
    vil [row[0]] = 0
    vil [row[1]] = 1
vil = list(vil.keys())
print (len(vil))

construction d'un dictionnaire { (a,b):d, (b,a):d }


dist = { }
for row in df.values :
    a = row[0]
    b = row[1]
    dist[a,b] = dist[b,a] = row[2]
print (len(dist))

distance Charleville-Mezieres --> Bordeaux


print ( dist["Charleville-Mezieres","Bordeaux"] )

initialisation du tableau d


d = { }
d['Charleville-Mezieres'] = 0
for v in vil : d[v] = 1e10
for v,w in dist :
    if v == 'Charleville-Mezieres': 
        d[w] = dist[v,w]

une itération de l'algorithme de Dikjstra


for v,w in dist :
    d2 = d[v] + dist[v,w]
    if d2 < d[w] :
        d[w] = d2

l'algorithme de Dikjstra


for i in range(0,len(d)) :        
    for v,w in dist :
        d2 = d[v] + dist[v,w]
        if d2 < d[w] :
            d[w] = d2

coût de la meilleure distribution des skis


p = { }
p [-1,-1] = 0
for n,taille in enumerate(skieurs) : p[n,-1] = p[n-1,-1] + taille
for m,paire  in enumerate(paires ) : p[-1,m] = 0
for n,taille in enumerate(skieurs) :
    for m,paire in enumerate(paires) :
        p1 = p.get ( (n  ,m-1), 1e10 ) 
        p2 = p.get ( (n-1,m-1), 1e10 ) + abs(taille - paire)
        p[n,m] = min(p1,p2)
        
print (p[len(skieurs)-1,len(paires)-1])

récupération de la meilleure distribution


p = { }
p [-1,-1] = 0
best = { }
for n,taille in enumerate(skieurs) : p[n,-1] = p[n-1,-1] + taille
for m,paire  in enumerate(paires ) : p[-1,m] = 0
for n,taille in enumerate(skieurs) :
    for m,paire in enumerate(paires) :
        p1 = p.get ( (n  ,m-1), 1e10 ) 
        p2 = p.get ( (n-1,m-1), 1e10 ) + abs(taille - paire)
        p[n,m] = min(p1,p2)
        
        if p[n,m] == p1 : best [n,m] = n,m-1
        else : best [n,m] = n-1,m-1
        
print (p[len(skieurs)-1,len(paires)-1])

chemin = [ ]
pos = len(skieurs)-1,len(paires)-1
while pos in best :
    print (pos)
    chemin.append(pos)
    pos = best[pos]
chemin.reverse()
print (chemin)

construction aléatoire d'un mot


import random
def mot_alea (l) :
    l = [ chr(97+random.randint(0,25)) for i in range(l) ]
    return "".join(l)

mesure du temps


for k in cherche :
    i = mots.index(k)

construction aléatoire d'un mot


import random
def mot_alea (l) :
    l = [ chr(97+random.randint(0,25)) for i in range(l) ]
    return "".join(l)
		
taille  = 20
N       = 100000
mots    = [ mot_alea(10) for _ in range (N) ]

mesure du temps recherche simple


import time
debut = time.clock()
for k in cherche :
    i = mots.index(k)
fin = time.clock()
print ("recherche simple",fin - debut)

mesure du temps recherche dichotomique


# recherche dichotomique
def dicho (mots, x) :
    a = 0
    b = len(mots)-1
    while a < b :
        m = (a+b)//2
        t = mots[m] 
        if t < x : b = m-1 
        elif t == m :
            return 
        else :
            a = m+1
    return a

mots.sort()

debut = time.clock()
for k in cherche :
    i = dicho(mots, k)
fin = time.clock()
print ("dichotomie",fin - debut)

construction du trie


def build_trie(mots) :
    trie = { }
    for m in mots :
        r = trie
        for c in m :
            if c not in r : r[c] = { }
            r = r[c]
    return trie

rechercher dans le trie


def lookup(trie, m) :
    r = trie
    for c in m :
        if c in r :
            r = r[c]
        else :
            return False
    return True

mesurer du temps pour le trie


debut = time.clock()
for k in cherche :
    i = lookup(trie, k)
fin = time.clock()

programme pour mesurer les différents temps de recherche

import random, time

def mot_alea (l) :
    l = [ chr(97+random.randint(0,25)) for i in range(l) ]
    return "".join(l)
    
for N in [100,200,500,1000,2000,5000,10000,20000,50000,100000,200000] :
    for taille in [5,10,20,50,100] :
        n       = 1000
        mots    = [ mot_alea(10) for _ in range (N) ]
        cherche = [ mot_alea(10) for _ in range(0,n) ]
        mots   += cherche

        if True :
            # recherche dichotomique
            def dicho (mots, x) :
                a = 0
                b = len(mots)-1
                while a < b :
                    m = (a+b)//2
                    t = mots[m] 
                    if t < x : b = m-1 
                    elif t == m :
                        return 
                    else :
                        a = m+1
                return a

            mots.sort()

            debut = time.clock()
            for k in cherche :
                i = dicho(mots, k)
            fin = time.clock()
            print ("dichotomie\t",N,"\t",taille,"\t",(fin - debut)/len(cherche))
            
        if True :
            # recherche dichotomique
            dico = { m:0 for m in mots }

            debut = time.clock()
            for k in cherche :
                i = dico[k]
            fin = time.clock()
            print ("dictionnaire\t",N,"\t",taille,"\t",(fin - debut)/len(cherche))
            
        if True :
            # trie
            
            def build_trie(mots) :
                trie = { }
                for m in mots :
                    r = trie
                    for c in m :
                        if c not in r : r[c] = { }
                        r = r[c]
                return trie
                
            def lookup(trie, m) :
                r = trie
                for c in m :
                    if c in r :
                        r = r[c]
                    else :
                        return False
                return True
                
            trie = build_trie(mots)
            
            debut = time.clock()
            for k in cherche :
                assert lookup(trie, k)
            fin = time.clock()
            print ("trie\t",N,"\t",taille,"\t",(fin - debut)/len(cherche))
            
        if False :
            # recherche simple
            debut = time.clock()
            for k in cherche :
                i = mots.index(k)
            fin = time.clock()
            print ("recherche simple\t",N,"\t",taille,"\t",(fin - debut)/len(cherche))