# PREUD'HOMME BONTOUX Geoffrey - PeiP 12 - 2014/2015 # TP n°8 donné le 14/11/2014 - Dessiner avec la tortue ep02 # http://www.fil.univ-lille1.fr/~allegraud/info_l1s1/tp_chaines_et_listes.html from turtle import * import doctest # Réalisez une procédure nommée dessine def dessine(ordres, l, α): """ Trace sur turtle la séquence d'ordre donnée, avec la longueur l et l'angle α donné. CU : ordres str, l numérique, α numérique → ∅ """ assert(type(ordres) is str), "ordres doit être du type str" assert(type(l) is float or type(l) is int), "l doit être numérique" assert(type(α) is float or type(α) is int), "α doit être numérique" for i in ordres: if i == 'F' or i == 'G': forward(l) elif i == '+': left(α) elif i == '-': right(α) else: assert (False), "ordres doit être composé des caractères 'F', 'G', '+' \ ou '-'" # Testez votre procédure sur l’exemple précédent. # dessine('F--F--F', 100, 60) # Tracez chacune des figures ci-dessous : # un carré # dessine('F-F-F-F', 100, 90) # un hexagone régulier # dessine('F-F-F-F-F-F', 100, 360/6) # (facultatif) une maison # Version compressée # reset() # dessine('FFF+++FF+++F+++FF+++FFF+++FFFFF+FFFFF++++FFFFF++++FFFFF++++++FFFFF+++FFFFF', 10, 30) # Version expliquée # L = 10 # On choisi une longueur sufisament petite pour les détails # ANGLE_DEG = 30 # On a besoin d'angles de 90° (pour les murs) et de 60° (pour # # le triangle équilatéral qui sert de toit), on prend donc le PGCD des deux # MUR = 5 # ANGLE_DROIT = 90 // ANGLE_DEG # ANGLE_TRIANGLE_DEG = 180 // 3 # ROTATION_TRIANGLE_DEG = 180 - ANGLE_TRIANGLE_DEG # ROTATION_TRIANGLE = ROTATION_TRIANGLE_DEG // ANGLE_DEG # DEMITOUR = 180 // ANGLE_DEG # DECALAGE_PORTE_GAUCHE = MUR // 2 # HAUTEUR_PORTE = 2 # LARGEUR_PORTE = 1 # DECALAGE_PORTE_DROITE = MUR - DECALAGE_PORTE_GAUCHE # reset() # dessine(# Mur du bas et porte # 'F' * (DECALAGE_PORTE_GAUCHE + LARGEUR_PORTE) # + '+' * ANGLE_DROIT # + 'F' * HAUTEUR_PORTE # + '+' * ANGLE_DROIT # + 'F' * LARGEUR_PORTE # + '+' * ANGLE_DROIT # + 'F' * HAUTEUR_PORTE # + '+' * ANGLE_DROIT # + 'F' * DECALAGE_PORTE_DROITE # # Mur de droite # + '+' * ANGLE_DROIT # + 'F' * MUR # # Toit # + '-' * ANGLE_DROIT # + '+' * ROTATION_TRIANGLE # + 'F' * MUR # + '+' * ROTATION_TRIANGLE # + 'F' * MUR # + '+' * ROTATION_TRIANGLE # + 'F' * MUR # + '+' * DEMITOUR # + 'F' * MUR # + '+' * ANGLE_DROIT # + 'F' * MUR, L, ANGLE_DEG) # (facultatif) un mouton # Version compressée # reset() # dessine('FFFFFFF+++FFF+++FFFFFFF+++FFF+++FFFFFFF+FFF++FFF++++FFF++++++FFF+++++FFFFFFF+FFF', 20, 30) # Version expliquée # L = 20 # ANGLE_DEG = 30 # LARGEUR = 7 # LONGUEUR = 3 # PROFONDEUR = 3 # ANGLE_DROIT = 90 // ANGLE_DEG # ANGLE_PERSPECTIVE = 1 # DEMITOUR = 180 // ANGLE_DEG # # print(# Face avant # 'F' * LARGEUR # + '+' * ANGLE_DROIT # + 'F' * LONGUEUR # + '+' * ANGLE_DROIT # + 'F' * LARGEUR # + '+' * ANGLE_DROIT # + 'F' * LONGUEUR # + '+' * ANGLE_DROIT # # Arète oblique en bas # + 'F' * LARGEUR # + '+' * ANGLE_PERSPECTIVE # + 'F' * PROFONDEUR # # Arète verticale à droite # + '+' * (ANGLE_DROIT - ANGLE_PERSPECTIVE) # + 'F' * LONGUEUR # # Arète oblique au milieu # + '+' * (ANGLE_DROIT + ANGLE_PERSPECTIVE) # + 'F' * PROFONDEUR # + '+' * DEMITOUR # + 'F' * PROFONDEUR # # Arète horizontale en haut # + '+' * (DEMITOUR - ANGLE_PERSPECTIVE) # + 'F' * LARGEUR # # Arète oblique à gauche # + '+' * ANGLE_PERSPECTIVE # + 'F' * PROFONDEUR # , L, ANGLE_DEG) # « Ça c'est la caisse. Le mouton que tu veux est dedans. » # - Antoine de Saint Exupery # Dériver un ordre par rapport à une variable # Soit une chaîne so et une autre chaîne r. On appelle la dérivation de so # par r par rapport à 'F' la chaîne obtenue en remplaçant chacune des # occurrences du caractère 'F' de so par tous les caractères de r. # Par exemple, la dérivation de 'F+F' par 'F-F' est 'F-F+F-F'. # Réalisez une fonction derive qui revoie la dérivation de la première chaîne passée en paramètre par la seconde par rapport à 'F'. # On définit la dérivée n-ième de so par r par rapport à 'F' comme le # terme un de la suite (un)n∈N définie par récurrence : def derive(so, r): """ Revoie la dérivation de la première chaîne passée en paramètre par la seconde par rapport à 'F'. Remplace dans une chaîne donnée toutes les occurences d’un caracère donné par une autre chaîne de caractères. CU : so str et r str → str >>> derive('', '++') '' >>> derive('F+F', 'F-F') 'F-F+F-F' """ assert(type(so) is str), "so doit être du type str" assert(type(r) is str), "r doit être du type str" retour = '' for i in so: if i == 'F': retour += r else: retour += i return retour # Programmez une fonction derive_n def derive_n(so, r, n): """ Renvoie la dérivation n-ième de la première chaîne par la seconde par rapport à 'F' CU : CU : so str et r str et n int → str >>> derive_n('F+F', 'F-F', 3) 'F-F-F-F-F-F-F-F+F-F-F-F-F-F-F-F' >>> derive_n('FFF', 'F+F+F', 0) 'FFF' """ assert(type(n) is int), "n doit être du type int" # derive() s'occupe des autres assertions, inutile de vérifier so deux fois retour = so for i in range(0, n): retour = derive(retour, r) return retour # Fractales # N’hésitez pas à accélerer la tortue en utilisant la fonction speed du # module turtle. speed(0) # Merci. # Tracez pour n compris entre 0 et 5, l=35−n et α=60 le résultat de la séquence # d’ordres obtenu en dérivant n fois 'F--F--F' par 'F+F--F+F' # n = 3 # l = 3 ** (5 - n) # α = 60 # ordres = derive_n('F--F--F', 'F+F--F+F', n) # dessine(ordres, l, α) # Essayez maintenant de dériver plusieurs fois 'F' par 'F+F-F-F+F' avec un angle # de 90°. # dessine(derive_n('F', 'F+F-F-F+F', 3), 5, 90) # Dérivation à plusieurs variables # Écrivez une fonction cherche_regle def cherche_regle(ordre, liste_vars, liste_regles): """ Renvoie ordre si ordre n’appartient pas à liste_vars ou liste_regles[i] si il existe un indice i vérifiant ordre == liste_vars[i]. CU : ordre str de taille 1, liste_vars une liste contenant exclusivement des types str, liste_regles une liste contenant exclusivement des types str de même taille que liste_vars → str >>> cherche_regle('F', ['F', 'G'], ['F-F', 'G+G']) 'F-F' >>> cherche_regle('A', ['F', 'G'], ['F-F', 'G+G']) 'A' """ assert(type(ordre) is str and len(ordre) == 1), "ordre doit être du type \ str et être de taille 1" assert(type(liste_vars) is list), "liste_vars doit être du type list" for i in liste_vars: assert(type(i) is str), "liste_vars doit contenir exclusivement des \ types str" assert(type(liste_regles) is list), "liste_regles doit être du type list" for i in liste_regles: assert(type(i) is str), "liste_regles doit contenir exclusivement des \ types str" assert(len(liste_vars) == len(liste_regles)), "liste_regles doit être de \ même taille que liste_vars" if (ordre in liste_vars): return liste_regles[liste_vars.index(ordre)] else: return ordre # Écrivez une fonction derive_mult def derive_mult(so, liste_regles, liste_vars): """ Renvoie la dérivation de so par liste_regles par rapport à liste_vars. CU : so str, liste_vars une liste contenant exclusivement des types str, liste_regles une liste contenant exclusivement des types str de même taille que liste_vars → str >>> derive_mult('FGF', ['F', 'G'], ['GG', 'FFF']) 'GGFFFGG' """ assert(type(so) is str), "so doit être de type str" # cherche_regle s'occupe des autres assertions retour = '' for i in so: retour += cherche_regle(i, liste_regles, liste_vars) return retour # Écrivez une fonction derive_mult_n def derive_mult_n(so, liste_regles, liste_vars, n): """ Renvoie la dérivée de la séquence d’ordres par la liste de règles par rapport à la liste des variables. CU : so str, liste_vars une liste contenant exclusivement des types str, liste_regles une liste contenant exclusivement des types str de même taille que liste_vars, n int → str >>> derive_mult_n('FGF', ['F', 'G'], ['GG', 'FFF'], 3) 'GGGGGGGGGGGGFFFFFFFFFFFFFFFFFFGGGGGGGGGGGG' """ assert(type(n) is int), "n doit être du type int" # deriv_mult() s'occupe des autres assertions retour = so for i in range(0, n): retour = derive_mult(retour, liste_regles, liste_vars) return retour # Tracez pour n compris entre 0 et 6, l=27−n et α=90 le résultat de la séquence # d’ordres obtenu en dérivant 2n fois 'FX' par ['X+YF+', '-FX-Y'] par rapport # à ['X','Y']. # n = 4 # l = 2 ** (7 - n) # α = 90 # ordres = derive_mult_n('FX', ['X', 'Y'], ['X+YF+', '-FX-Y'], 2 * n) # ordres = derive_mult(ordres, ['X', 'Y'], ['', '']) # Pour éviter les erreurs # # d'assertion # dessine(ordres, l, α) # Sauvegarde d’une position # Écrivez une commande sauvegardant l’état de la tortue # dans une liste de 3 éléments. etat = [0, 0, 0] def sauvegarder_etat(): """ Sauvegarde l’état de la tortue dans la variable globale etat CU : ∅ → ∅ """ global etat etat[0] = xcor() etat[1] = ycor() etat[2] = heading() # Écrivez une commande permettant de restaurer un état contenu # dans une liste à 3 éléments. def restaurer_etat(): """ Restaure l’état de la tortue depuis la variable globale etat CU : ∅ → ∅ """ global etat penup() goto(etat[0], etat[1]) setheading(etat[2]) pendown() # Modifiez votre procédure dessine pour prendre en compte les deux # nouveaux ordres. def dessine2(ordres, l, α): """ Trace sur turtle la séquence d'ordre donnée, avec la longueur l et l'angle α donné. CU : ordres str, l numérique, α numérique → ∅ """ assert(type(ordres) is str), "ordres doit être du type str" assert(type(l) is float or type(l) is int), "l doit être numérique" assert(type(α) is float or type(α) is int), "α doit être numérique" for i in ordres: if i == 'F' or i == 'G': forward(l) elif i == '+': left(α) elif i == '-': right(α) elif i == '(': sauvegarder_etat() elif i == ')': restaurer_etat() else: assert (False), "ordres doit être composé des caractères 'F', 'G', '+' \ '-', '(' ou ')'" # Tracez pour n compris entre 0 et 6, l=4 et α=60 le résultat de la # séquence d’ordres obtenu en dérivant n fois 'G' par ['FF', 'F+(G)--G'] # par rapport à ['F','G']. # n = 6 # l = 4 # α = 60 # ordres = derive_mult_n('G', ['F', 'G'], ['FF', 'F+(G)--G'], n) # dessine2(ordres, l, α) def tester(): doctest.testmod(verbose=True)