Proposition de correction

from turtle import *
from math import *
from matplotlib . pyplot import *
import numpy as np
from random import *

X = [0, 3, 3, 1.5,0,0]
Y = [0, 0, 3, 5.5,3,0]
#plot (X, Y, "k-")
#Pour avoir la meme echelle sur les axes
axis('equal')
#show()


def tracerMaison():
    forward(100)
    left(90)
    forward(100)
    left(30)
    forward(100)
    left(120)
    forward(100)
    left(30)
    forward(100)

def dessiner(unite,angle,motif):
    # test de validité du mot 
    valide=['F','+','-']
    for char in motif:
        if char not in valide:
            return 1
    # Dessin
    for char in motif:
        if char=='F':
            fd(unite)
        if char=='+':
            left(angle)
        if char=='-':
            right(angle)
    # Le dessin est fini
    return 0
    
def suivant(motif,regle):
    sortie=''
    for char in motif:
        if char=='F':
            sortie+=regle
        else:sortie+=char
    return sortie
        
def evolution(axiome,regle,etape):
    #init
    sortie=axiome
    #on tourne sur le nb d'étapes:
    for i in range(etape):
        sortie=suivant(sortie,regle)
    return sortie

def dessinerMPL(longueur,pasRotation,motif):
    # on supose le mot valide 
    
    # Dessin
    #init
    x=[0]
    y=[0]
    d=90 #azimut
    for char in motif:
        if char=='F':
            #on calcule les variations selon x et y
            varx=longueur*np.cos(d*pi/180)
            vary=longueur*np.sin(d*pi/180)
            #on ajoute ces variations au dernier élément de la liste obtenu avec liste[-1]
            x.append(x[-1]+varx)
            y.append(y[-1]+vary)
        if char=='+':
            d+=pasRotation
        if char=='-':
            d-=pasRotation
         
    plot (x, y, "k-")
    #Pour avoir la meme echelle sur les axes
    axis('equal')
    show()
    
def dessinerRamif(unite,angle, motif,azimut):
    #on Suppose le motif valide
    x=[0]
    y=[0]
    d=azimut #azimut
    pile=[]
    
    for char in motif:
        if char=='F':
            #on calcule les variations selon x et y
            varx=unite*np.cos(d*pi/180)
            vary=unite*np.sin(d*pi/180)
            #on ajoute ces variations au dernier élément de la liste obtenu avec liste[-1]
            x.append(x[-1]+varx)
            y.append(y[-1]+vary)
        if char=='+':
            d+=angle
        if char=='-':
            d-=angle
        if char=='[':
            # on sauvegarde la position courante dans la pile
            pile.append([x[-1],y[-1],d])
        if char==']':
            # on dépile pour revenir à la posision sauvegardée
            xpos,ypos,d=pile.pop()
            x.append(xpos)
            y.append(ypos)
            
    plot (x, y, "k-")
    #Pour avoir la meme echelle sur les axes
    axis('equal')
    show()
    
 #PartieB
def genereRegle ():
    alphabet = ['F', '-', '+', '[', ']']
    regle = ""
    for i in range (randint(15,20)):
        regle=regle+choice(alphabet)
    return regle
 
def verifie(motif):
    pile=[]
    for char in motif:
        # on empile les [
        if char=='[':
            pile.append('[')
        if char==']' : 
            if len(pile)==0:
                return False
            else :
                pile.pop()
    return len(pile)==0
    
#Q2b

def simplifie(regle):
    i,reponse = 0,''
    while i<len(regle)-1:
        double=regle[i]+regle[i+1]
        if double=='+-' or double=='-+':
            i=i+2 # on saute le double qui a été traité
        elif double == '-]' or double == '+]':
            #on empile le crochet
            reponse=reponse+regle[i+1]
            i=i+2 # on saute le double qui a été traité
        else:# si FF ou F[ ou ...
            reponse=reponse+regle[i]
            i=i+1
        #on ajoute le dernier element du mot
    if i==len(regle)-1: #erreur moi : ne pas ajouter syst. le dernier caractère (saut de 2 possible).
        reponse = reponse + regle [-1]
    if len(reponse)!= len(regle):
        reponse=simplifie(reponse)
    return reponse

def population(n):
    resultat=[]
    i=0
    def comptage(char,chaine):
        return chaine.count(char)
        
    while i<n:
        nouvelleRegle=simplifie(genereRegle())
        if verifie(nouvelleRegle) and comptage('[',nouvelleRegle)>2 and (comptage('+',nouvelleRegle)+comptage('-',nouvelleRegle))>1 and nouvelleRegle not in resultat:
            resultat.append(nouvelleRegle)
            i+=1
    return resultat

#Mutation


            
def mutation(chaine):
    #reperage des symboles + ou - 
    listePositions=[]
    for i in range(len(chaine)):
        if chaine[i]=='+' or chaine[i]=='-':
            listePositions.append(i)
    
    #choix d'une position de symbole de rotation au hasard
    j=randint(0,len(listePositions)-1)
    
    alea=listePositions[j] # bornes incluses
    
    #fonction d'echange des symboles
    def echange(symbole):
        if symbole=='+':
            return '-'
        if symbole=='-':
            return '+'
    #echange
    #chaine de caractère non mutable !!!!
    #liste mutable OK
    print('tst')
    print(chaine[0:alea])
    print(echange(chaine[alea]))
    print(chaine[alea+1:])
    print('tst')
    
    chaine1=chaine[0:alea]+echange(chaine[alea])+chaine[alea+1:]
    return chaine1

def extraitBranche(chaine):
    #1 on recherche les index de position des '['
    #2 on choisit un des index au hasard : on note stop 1 son index.
    #3 on cherche la position du caractère ']' qui suit : on note son index stop2
    #4 on découpe la chaine en 3 brins que l'on retourne
    
    #etape1
    listePositions=[]
    for i in range(len(chaine)):
        if chaine[i]=='[':
            listePositions.append(i)
    
    #etape 2 : choix d'une position de '[' au hasard
    j=randint(0,len(listePositions)-1)
    stop1=listePositions[j] # bornes incluses
    print(stop1)
    
    #etape3
    k=0
    branche=chaine[stop1] # A ce stade elle n'est pas valide car = à '['
    
    
    while not verifie(branche) :
        branche=chaine[stop1:stop1+k+1]
        print(branche)
        k+=1
    
    return chaine[0:stop1],branche,chaine[stop1+k:]
        
def croise(r1,r2):
    br1,br2,br3=extraitBranche(r1)
    br4,br5,br6=extraitBranche(r2)
    enfant=br1+br5+br3
    return enfant
    
    
##Programme principal
#tracerMaison()
#dessiner(5,60,evolution('F--F--F','F+F--F+F',2))
dessinerRamif(10,30,evolution('F','F[+FF]F[-FF]F',4),90) 
#plante sympa
#dessinerRamif(10,40,evolution('F','F[+F]F[-F[+FF]]F',4),90)
# maison avec mpl
motif='+F+++++++++F++++++++'
#dessinerMPL(10,20,'F'+motif+'F'+motif)
dessinerRamif(10,20,'F[+F]F[-F]F',90)
#motif='[[][]'
#print(verifie(motif))

#regle='F+-+-[F-F]+F+[F+-FF]-F'
#print(simplifie(regle))
#print(mutation(regle))

print(extraitBranche('F[-FF]+[FF[-F]]-FF[-F-F]'))

print(croise('F[-FF]+[FFF]-FF[-F-F]','F[+F]+[-F-F]-FF[+F][-F][F]'))