def valeurs_somme_prod():  # cree 3 fractions et un tuple de signes (+,*)
    while True:
        (base1, base2) = (valeur_alea(-13, 13), valeur_alea(-13, 13))
        lepgcd = pgcd(base1, base2)
        (base1, base2) = (base1 // lepgcd, base2 // lepgcd)
        if base1 != 1 and base2 != 1:
            break
    (n2, d2) = (base1 * valeur_alea(-10, 10), abs(base2 * valeur_alea(2, 10)))
    lepgcd = pgcd(n2, d2)
    (n2, d2) = (n2 // lepgcd, d2 // lepgcd)
    (n3, d3) = (base2 * valeur_alea(-10, 10), abs(base1 * valeur_alea(2, 10)))
    lepgcd = pgcd(n3, d3)
    (n3, d3) = (n3 // lepgcd, d3 // lepgcd)
    (n1, d1) = (base1 * valeur_alea(-10, 10), abs(pgcd(d2, base2 * valeur_alea(2, 10))))
    lepgcd = pgcd(n1, d1)
    (n1, d1) = (n1 // lepgcd, d1 // lepgcd)
    if randrange(2) == 0:
        s1 = "+"
    else:
        s1 = "-"
    if randrange(2) == 0:
        s2 = "*"
    else:
        s2 = ":"
    if s2 == "*":
        return ((n1, d1), (n2, d2), (n3, d3), (s1, s2))
    else:
        return ((n1, d1), (n2, d2), (d3, n3), (s1, s2))
def valeurs_puissances():  # renvoie un tuple contenant les valeurs pour les deux exercices sur les puissances
    from math import floor, log10
    (max, emax) = (10, 2)
    while True:
        (b1, b2) = (valeur_alea(2, max), valeur_alea(2, max))
        (b1, b2) = (b1 / pgcd(b1, b2), b2 / pgcd(b1, b2))
        if b1 != 1 and b2 != 1:
            break
    while True:
        (n1, n2) = ((b1 * valeur_alea(2, max)) * 10 ** randrange(-emax,
                    emax), (b2 * valeur_alea(2, max)) * 10 ** randrange(-emax,
                    emax))
        n3 = ((b1 * b2) * choice((2, 4, 5, 8))) * 10 ** randrange(-emax,
                emax)
        if int(floor(log10(((n1 * n2) * 1.) / n3))) != 0 and n1 != 1 and \
            n2 != 1 and n3 != 1:
            break
    (e1, e2, e3, e4) = (valeur_alea(-10, 10), valeur_alea(-10, 10),
                        valeur_alea(2, 10), valeur_alea(2, 5))
    a = verifie_type((n1, n2, n3, e1, e2, e3, e4))
    while True:
        (b1, b2) = (valeur_alea(2, max), valeur_alea(2, max))
        (b1, b2) = (b1 / pgcd(b1, b2), b2 / pgcd(b1, b2))
        if b1 != 1 and b2 != 1:
            break
    (n1, n2) = ((b1 * valeur_alea(2, max)) * 10 ** randrange(-emax, emax +
                1), (b2 * valeur_alea(2, max)) * 10 ** randrange(-emax,
                emax + 1))
    n3 = ((b1 * b2) * choice((1, 2, 4, 5, 8))) * 10 ** randrange(-emax,
            emax + 1)
    (e1, e2, e3, e4) = (valeur_alea(-10, 10), valeur_alea(-10, 10),
                        valeur_alea(-10, -2), valeur_alea(2, 5))
    b = verifie_type((n1, n2, n3, e1, e2, e3, e4))
    return (a, b)
def valeurs_prod_parenth():  # cree 3 fractions et un tuple de signes (*,+)
    while True:
        (base1, base2) = (valeur_alea(2, 13), valeur_alea(2, 13))
        lepgcd = pgcd(base1, base2)
        (base1, base2) = (base1 // lepgcd, base2 // lepgcd)
        if base1 != 1 and base2 != 1:
            break
    while True:
        n2 = valeur_alea(-13, 13)
        lepgcd = pgcd(n2, base1)
        if lepgcd == 1:
            break
    while True:
        n3 = valeur_alea(-13, 13)
        lepgcd = pgcd(n3, base2)
        if lepgcd == 1:
            break
    while True:
        (n1, d1) = (valeur_alea(-10, 10), valeur_alea(2, 10))
        lepgcd = pgcd(n1, d1)
        if lepgcd != n1 and lepgcd != d1:
            break
    (n1, d1) = (n1 // lepgcd, d1 // lepgcd)
    if randrange(2) == 0:
        s1 = "*"
    else:
        s1 = ":"
    if randrange(2) == 0:
        s2 = "+"
    else:
        s2 = "-"
    return ((n1, d1), (n2, base1), (n3, base2), (s1, s2))
def decomp_prod(a, b):  #renvoie un tuple contenant les deux fractions apres simplification et un tuple contenant les nb par lesquels on simplifie le produit de fractions
    c = pgcd(a[0], b[1])
    d = pgcd(a[1], b[0])
    sgn1 = signe(a[1])
    sgn2 = signe(b[1])
    if c == d == 1:
        return (((sgn1 * a[0]) // c, (sgn1 * a[1]) // d), ((sgn2 * b[0]) // d, (sgn2 * b[1]) // c), '')
    else:
        return (((sgn1 * a[0]) // c, (sgn1 * a[1]) // d), ((sgn2 * b[0]) // d, (sgn2 * b[1]) // c), (c, d))
def valeur_fraction(nombre_min, nombre_max):
    n = valeur_alea( nombre_min, nombre_max)
    d = valeur_alea( nombre_min, nombre_max)
    while pgcd( n , d ) == 1:
        n = valeur_alea( nombre_min, nombre_max)
        d = valeur_alea( nombre_min, nombre_max)
    fr = Fractions(n, d)
    return fr
def valeur_decimal(nombre_min, nombre_max):
    n = valeur_alea( nombre_min, nombre_max)
    longueur_n = len(str(n))
    d = 10 ** random.randrange(longueur_n-1, longueur_n+3)
    while pgcd( n , d ) == 1:
        n = valeur_alea( nombre_min, nombre_max)
        longueur_n = len(str(n))
        d = 10 ** random.randrange(longueur_n-1, longueur_n+3)
    fr = Fractions(n, d)
    return float(n)/d, fr
def valeurs_quotient_frac():  # cree 4 fractions et un tuple de signes (+,+)
    while True:
        (n1, d1) = (valeur_alea(-10, 10), valeur_alea(2, 10))
        lepgcd = pgcd(n1, d1)
        if lepgcd != n1 and lepgcd != d1:
            break
    (n1, d1) = (n1 // lepgcd, d1 // lepgcd)
    while True:
        (n3, d3) = (valeur_alea(-10, 10), valeur_alea(2, 10))
        lepgcd = pgcd(n3, d3)
        if lepgcd != n3 and lepgcd != d3:
            break
    (n3, d3) = (n3 // lepgcd, d3 // lepgcd)
    (n2, n4) = (valeur_alea(1, 10), valeur_alea(1, 10))
    if randrange(2) == 0:
        s1 = "+"
    else:
        s1 = "-"
    if randrange(2) == 0:
        s2 = "+"
    else:
        s2 = "-"
    return ((n1, d1), (n2, 1), (n3, d3), (n4, 1), (s1, s2))
def simplifie(a):  #renvoie la fraction a simplifiee
    b = pgcd(a[0], a[1])
    if b != 1:
        return (a[0] // b, a[1] // b)
    else:
        return ''
def valeur_quotient(nombre_min, nombre_max):
    (a, b) = (valeur_alea(nombre_min, nombre_max), valeur_alea(nombre_min, nombre_max))
    while pgcd(a, b) == b:
        (a, b) = (valeur_alea(nombre_min, nombre_max), valeur_alea(nombre_min, nombre_max))
    return (a // pgcd(a, b), b // pgcd(a, b))
def simprad(liste):
    """Simplifie la fraction d'un angle en radians."""
    p = pgcd(liste[0],liste[1])
    return [f/p for f in liste]
def deg2rad(n):
    """Effectue la conversion de degrés entre 0 et 360° vers radians."""
    p = pgcd(n,180)
    return [n/p,180/p]
def diagramme_tex(typed=2,val=[[],[]],aide=0):
    """Génère un diagramme en bâtons (type 1), circulaire (type2) ou semi-circulaire (type3) à partir des fréquences (liste val[1]) et son tableau de calculs."""
    diag = ""
    
    couleur = ["AliceBlue", "Bisque", "PaleGreen", "Thistle", "LightGray", "Khaki", "LightBlue", "LightSalmon", "PaleGoldenrod", "PapayaWhip", "Plum", "Gainsboro"]
    
    if typed == 1: # Diagramme en bâtons
        
        grad = len(val[1])+1
        diag += u"\\begin{pspicture}(-1,-1)("+str(grad)+",11)\n"
        diag += u"\\psset{xunit=1cm,yunit=1cm}\n"
        diag += u"\\psgrid[subgriddiv=1,griddots=5,gridlabels=0]("+str(grad)+",11)\n"
        diag += u"\\psaxes[Dx=1,dx=1,Dy=10,dy=1]{->}(0,0)("+str(grad)+",11)\n"
        
        for f in range(len(val[1])):
            diag += u"\\psline[linewidth=0.1,linecolor=green]("+val[0][f+1]+",0)("+val[0][f+1]+","+str(val[1][f]/10.0)+")\n"
            
        diag += u"\\rput(0,11.2){\\small Fréquences (\\%)}\n"
        diag += u"\\rput("+str(grad+0.5)+",0){\\small "+val[0][0]+"}\n"
        diag += u"\\end{pspicture}\n"
        
    elif typed == 2: # Diagramme circulaire
        grad = len(val[1])
        diag += u"\\begin{pspicture}(-3,-3)(3,3)\n"
        diag_texte = ""
        
        debut = 0
        fin = round(val[1][0]*3.6,0)
        liste_fin = [fin] # Pour éviter d'avoir les pointillés superposés sur des lignes
        

        for v in range(len(val[1])-1):
            diag += u"\\pswedge[fillstyle=solid,fillcolor="+couleur[v%12]+"](0,0){3}{"+str(debut)+"}{"+str(fin)+"}\n"
            diag_texte += u"\\rput[r]{"+str((debut+fin)/2.0)+"}("+str(3*round(cos(radians((debut+fin)/2.0)),2))+","+str(3*round(sin(radians((debut+fin)/2.0)),2))+"){\\small \\bfseries{"+val[0][v+1]+"}}\n"
            debut = fin
            fin += round(val[1][v+1]*3.6,0)
            liste_fin.append(fin)
        diag += u"\\pswedge[fillstyle=solid,fillcolor="+couleur[(len(val[1])-1)%12]+"](0,0){3}{"+str(debut)+"}{360}\n"
        diag_texte += u"\\rput[r]{"+str((debut+fin)/2.0)+"}("+str(3*round(cos(radians((debut+fin)/2.0)),2))+","+str(3*round(sin(radians((debut+fin)/2.0)),2))+"){\\small \\bfseries{"+val[0][-1]+"}}\n"
                
        if aide != 0:        
            temp = [int(3.6*v) for v in val[1]]
            temp2 = [pgcd(temp[i],temp[i+1]) for i in range(len(val[1])-1)]
            temp2.sort()
            ecart = temp2[0]
            angle = ecart
                  
            while angle < 360:
                if angle not in liste_fin:
                    diag += u"\\psline[linestyle=dashed,linecolor=gray](0,0)("+str(3*round(cos(radians(angle)),2))+","+str(3*round(sin(radians(angle)),2))+")\n"
                angle += ecart   
        
        diag += diag_texte
        diag += u"\\end{pspicture}\n"
        
    elif typed == 3: # Diagramme semi-circulaire
        grad = len(val[1])
        diag += u"\\begin{pspicture}(0,0)(3,3)\n"
        diag_texte = ""
        
        debut = 0
        fin = round(val[1][0]*1.8,0)
        liste_fin = [fin] # Pour éviter d'avoir les pointillés superposés sur des lignes
        
        for v in range(len(val[1])-1):
            diag += u"\\pswedge[fillstyle=solid,fillcolor="+couleur[v%12]+"](0,0){3}{"+str(debut)+"}{"+str(fin)+"}\n"
            diag_texte += u"\\rput[r]{"+str((debut+fin)/2.0)+"}("+str(3*round(cos(radians((debut+fin)/2.0)),2))+","+str(3*round(sin(radians((debut+fin)/2.0)),2))+"){\\small \\bfseries{"+val[0][v+1]+"}}\n" # FIX problème hauteur textes superposés
            debut = fin
            fin += round(val[1][v+1]*1.8,0)
            liste_fin.append(fin)
        diag += u"\\pswedge[fillstyle=solid,fillcolor="+couleur[(len(val[1])-1)%12]+"](0,0){3}{"+str(debut)+"}{180}\n"
        diag_texte += u"\\rput[r]{"+str((debut+fin)/2.0)+"}("+str(3*round(cos(radians((debut+fin)/2.0)),2))+","+str(3*round(sin(radians((debut+fin)/2.0)),2))+"){\\small \\bfseries{"+val[0][-1]+"}}\n"
        
        if aide != 0:        
            temp = [int(1.8*v) for v in val[1]]
            temp2 = [pgcd(temp[i],temp[i+1]) for i in range(len(val[1])-1)]
            temp2.sort()
            ecart = temp2[0]
            angle = ecart

            while angle < 180:
                if angle not in liste_fin:
                    diag += u"\\psline[linestyle=dashed,linecolor=gray](0,0)("+str(3*round(cos(radians(angle)),2))+","+str(3*round(sin(radians(angle)),2))+")\n"
                angle += ecart   
        
        diag += diag_texte
        diag += u"\\end{pspicture}\n"
        
    
    return diag
def exo_ages():
    """Exercice sur la répartition des âges dans une population."""
    global exo, cor
    
    # Partitions de 20
    partitions = [[4, 4, 4, 4, 4], [3, 4, 4, 4, 5], [3, 3, 4, 5, 5], [2, 4, 4, 5, 5], [2, 3, 5, 5, 5], [1, 4, 5, 5, 5], 
                  [3, 3, 4, 4, 6], [2, 4, 4, 4, 6], [3, 3, 3, 5, 6], [2, 3, 4, 5, 6], [1, 4, 4, 5, 6], [2, 2, 5, 5, 6], 
                  [1, 3, 5, 5, 6], [2, 3, 3, 6, 6], [2, 2, 4, 6, 6], [1, 3, 4, 6, 6], [1, 2, 5, 6, 6], [1, 1, 6, 6, 6], 
                  [3, 3, 3, 4, 7], [2, 3, 4, 4, 7], [1, 4, 4, 4, 7], [2, 3, 3, 5, 7], [2, 2, 4, 5, 7], [1, 3, 4, 5, 7], 
                  [1, 2, 5, 5, 7], [2, 2, 3, 6, 7], [1, 3, 3, 6, 7], [1, 2, 4, 6, 7], [1, 1, 5, 6, 7], [2, 2, 2, 7, 7], 
                  [1, 2, 3, 7, 7], [1, 1, 4, 7, 7], [3, 3, 3, 3, 8], [2, 3, 3, 4, 8], [2, 2, 4, 4, 8], [1, 3, 4, 4, 8], 
                  [2, 2, 3, 5, 8], [1, 3, 3, 5, 8], [1, 2, 4, 5, 8], [1, 1, 5, 5, 8], [2, 2, 2, 6, 8], [1, 2, 3, 6, 8], 
                  [1, 1, 4, 6, 8], [1, 2, 2, 7, 8], [1, 1, 3, 7, 8], [1, 1, 2, 8, 8], [2, 3, 3, 3, 9], [2, 2, 3, 4, 9], 
                  [1, 3, 3, 4, 9], [1, 2, 4, 4, 9], [2, 2, 2, 5, 9], [1, 2, 3, 5, 9], [1, 1, 4, 5, 9], [1, 2, 2, 6, 9], 
                  [1, 1, 3, 6, 9], [1, 1, 2, 7, 9], [1, 1, 1, 8, 9], [2, 2, 3, 3, 10], [1, 3, 3, 3, 10], [2, 2, 2, 4, 10], 
                  [1, 2, 3, 4, 10], [1, 1, 4, 4, 10], [1, 2, 2, 5, 10], [1, 1, 3, 5, 10], [1, 1, 2, 6, 10], [1, 1, 1, 7, 10], 
                  [2, 2, 2, 3, 11], [1, 2, 3, 3, 11], [1, 2, 2, 4, 11], [1, 1, 3, 4, 11], [1, 1, 2, 5, 11], [1, 1, 1, 6, 11], 
                  [2, 2, 2, 2, 12], [1, 2, 2, 3, 12], [1, 1, 3, 3, 12], [1, 1, 2, 4, 12], [1, 1, 1, 5, 12], [1, 2, 2, 2, 13], 
                  [1, 1, 2, 3, 13], [1, 1, 1, 4, 13], [1, 1, 2, 2, 14], [1, 1, 1, 3, 14], [1, 1, 1, 2, 15], [1, 1, 1, 1, 16]]
    
    choix_diagramme = random.randint(0,1)
    if choix_diagramme == 0:
        diagramme_texte = "circulaire"
    else:
        diagramme_texte = "semi-circulaire"
    hasard = partitions[random.randint(0,len(partitions)-1)]
    frequences = [5*v for v in hasard] 
    random.shuffle(frequences)
    
    population = 20*random.randint(100,2000)
    
    titres = [u"Moins de 20 ans", u"Entre 20 et 40 ans", u"Entre 40 et 60 ans", u"Entre 60 et 80 ans", u"Plus de 80 ans"]
    diagramme = diagramme_tex(choix_diagramme+2,[[u"Ages", u"<20 ans","20 - 40 ans","40 - 60 ans","60 - 80 ans",u">80 ans"],frequences],1) 
    exo.append(u"\\begin{center}")
    cor.append(u"\\begin{center}")
    exo.append(diagramme)
    cor.append(diagramme)
    exo.append(u"\\end{center}")
    cor.append(u"\\end{center}")
    exo.append(u"Le diagramme "+diagramme_texte+u" ci-dessus représente les différentes fréquences des classes d'âges dans une certaine région.\\par")
    cor.append(u"Le diagramme "+diagramme_texte+u" ci-dessus représente les différentes fréquences des classes d'âges dans une certaine région.\\par")
    exo.append("\\begin{enumerate}")
    cor.append("\\begin{enumerate}")
    exo.append(u"\\item Calculer les fréquences de chaque classe d'âges.")
    cor.append(u"\\item Calculer les fréquences de chaque classe d'âges.\\par")
    
    titres = [u"Classes d'âges", u"$0 \\leq n \\leq 20$", u"$20 \\leq n \\leq 40$", u"$40 \\leq n \\leq 60$", u"$60 \\leq n \\leq 80$", u"$80 \\geq n$"]
    
    liste_pgcd = [pgcd(frequences[i],frequences[i+1]) for i in range(len(frequences)-2)]
    liste_pgcd.sort()
    pourcent = liste_pgcd[0]    
    parts = 100 / pourcent
    effectifs = [f*population/100 for f in frequences]
    
    cor.append(u"Le diagramme "+diagramme_texte+u" est partagé en "+str(parts)+u" parts symbolisées par des lignes grises en pointillés.\\par")
    cor.append(u"On en déduit que chacune de ces parts représente $\\dfrac{100}{"+str(parts)+"}="+str(pourcent)+u"\\%$, puis en comptant le nombre de parts dans chaque classe, on obtient le tableau suivant :\\par" )
    cor.append("\\end{enumerate}")
    cor.append(tableau_tex(titres,">{\\centering}p{2.2cm}",0,1,[[],frequences]))
    cor.append("\\begin{enumerate}")
    exo.append(u"\\item Sachant que la population étudiée est composée de "+str(population)+u" personnes, calculer les effectifs de chaque classe d'âges.")
    cor.append(u"\\item[$\\blacktriangleright$\\textbf{2.}] Sachant que la population étudiée est composée de "+str(population)+u" personnes, calculer les effectifs de chaque classe d'âges.\\par")
    
    cor.append(u"Sachant que la classe des moins de vingt ans est composée de "+str(frequences[0])+u" \\% de "+str(population)+u" personnes, on peut calculer l'effectif concerné :\\par")
    cor.append(u"$\\dfrac{"+str(frequences[0])+u" \\times "+str(population)+u"}{100}="+str(effectifs[0])+u"$.\\par")
    cor.append(u"Avec le même type de calcul, on obtient les effectifs des autres classes, résumés dans le tableau ci-dessous :")
    cor.append("\\end{enumerate}")
    cor.append(tableau_tex(titres,">{\\centering}p{2.2cm}",1,1,[effectifs,frequences]))
    
    
    exo.append("\n\\end{enumerate}")

    return False
def factorise_identites_remarquables(pol1,sgns,var='',racines=True):
    '''Factorise un polynomes grâce aux identités remarquables'''
    if var=='':
        var=pol1.var
    X=Polynome({1:1},var)
    a1=pgcd(int(pol1[0]),pgcd(int(pol1[1]),int(pol1[2])))#du signe de a=pol1[2]
    if a1!=1 or a1!=-1:
        pol2=pol1/a1
    else:
        pol2=pol1
    #coeff=coeff/int(math.sqrt(a1))
    #pol2=(cx)^2 ±2× cx × b + b^2
    #pol2[2]=c^2
    #pol2[1]=2× cx × b
    #pol2[0] = b^2
    c=int(sqrt(pol2[2]))#problème d'arrondi ?

    factorisation=[]
    if a1!=1:
        pol_temp = (pol1/a1).simplifie()
        pol_temp.var = var
        factorisation.append("%s \\times\\big[ %s \\big]"%(TeX(a1),pol_temp))
        facteur2 ="%s\\times \\big["%(TeX(a1))
    else:
        facteur2 =""
    if c!=1:
        facteur2 +=u"(%s %s)^2"%(TeX(c),var)
    else:
        facteur2 +=u"%s^2"% var
    if sgns:
        if sgns==-2: #-2 => (a-b)²
            facteur2 +="-2 \\times "
        else:        #+2 => (a+b)²
            facteur2 +="+2 \\times "
        if c==1:
            facteur2 +=var
        else:
            facteur2 +=TeX(c)+var
        b=int(sqrt(pol2[0]))
        facteur2 +=" \\times %s +"%(TeX(b))
    else:
        #a²-b²
        facteur2 +="-"
        b=int(sqrt(-(pol2[0])))
    facteur2 +=u"%s^2"%(TeX(b))
    if a1!=1:
        facteur2 +="\\big]"
    factorisation.append(facteur2)
    facteur3=""
    if a1!=1:
        facteur3 +=TeX(a1)
    sgns=sgns/2
    if sgns:#(cx-b)² ou (cx+b)²
        liste_racines=[Fractions(-(sgns))*b/c]
        facteur3 +="{(%s)}^2"%(c*X+sgns*b)
    else:#(cx-b)(cx+b)
        liste_racines=[Fractions(-1)*b/c,Fractions(1)*b/c]
        facteur3 +="(%s)(%s)"%(c*X+b,c*X-b)
    factorisation.append(facteur3)
    if racines:
        return factorisation,liste_racines
    return factorisation