La note ne valide pas seulement le résultat de votre programme, mais également son style :
y = x * 2 # y est le double de x
n'apporte rien),
Vérifiez ces points avant de demander à votre intervenant de valider votre code.
Vous aurez également besoin du fichier boulet.py.
Le but de ce TP est de revoir certains concepts vu au premier semestre (boucles, conditionnelles, fonctions) en insistant sur la qualité du code écrit. Pour ceci, il faudra suivre les règles vues en cours concernant :
#
de Python),
Après quelques exercices préliminaires, nous allons modéliser (et dessiner) la trajectoire d'un boulet de canon en fonction de l'angle de tir, de la vitesse initiale du boulet et de sa masse. Nous chercherons ensuite à ajuster automatiquement l'angle de tir pour essayer d'atteindre une cible précise.
Le principe de la recherche dichotomique (Wikipedia) est de chercher une solution d'un problème en coupant l'ensemble des solutions possible en deux parties égales à chaque étape. Au bout d'un moment, soit la solution est trouvée, soit l'ensemble devient vide et il n'y a pas de solution.
Par exemple, pour trouver un nombre entre 0 et 100 par questions oui/non successives, les stratégies suivantes ne sont pas très efficaces :
La strategie optimale est de séparer l'ensemble des nombre en 2 parties égales (ou presque) à chaque question. On peut poser par exemple :
Si on représente les questions sur un dessin, on a :
Avec cette stratégie, il ne faudra jamais plus de 7 questions pour arriver à trouver le nombre !
Le principe est le suivant : pour chercher un nombre entre a et b, on demande s'il est entre a et m, où m est la moyenne de a et b. Si la réponse est oui, on recommence à chercher entre a et m, et si la réponse est non, on recommence à chercher entre m+1 et b.
La procédure suivante implante la stratégie qui pioche des nombres au hasard jusqu'à tomber sur le nombre choisi par l'utilisateur :
from random import randint def strategie_naive(): """implémentation de la stratégie naïve qui cherche un nombre entre 0 et 100 choisi par l'utilisateur.""" print("Pensez à un nombre entre 0 et 100 puis appuyez sur 'Enter'...") input() nombre = -1 # nombre cherché. Il passera à une valeur positive # quand on l'aura trouvé nb_questions = 0 while nombre < 0: nb = randint(0,100) # on demande si le nombre est égal à nb : question = "Est-ce que le nombre est égal à " + str(nb) + " ? [o/n] " reponse = "" while reponse not in ["o", "n"]: reponse = input(question) if reponse == "o": print("oui !") nombre = nb elif reponse == "n": print("non...") nb_questions = nb_questions+1 print("Le nombre choisi est égal à", nombre, "et il a fallu", nb_questions, "questions pour le trouver")
Lisez ce programme pour comprendre comment il fonctionne, puis écrivez une procédure sur le même modèle qui implémente la recherche dichotomique...
Combien de questions sont nécessaires pour trouver un nombre entre 1 et 100 ? Entre 1 et 1000 ? Entre 1 et 10000 ?
La trajectoire d'un objet inerte est régie par les lois de la mécanique. Nous allons utiliser une approximation de ces lois pour modéliser de manière discrète la trajectoire d'un boulet de canon.
À un instant t donné, le boulet a
x
et y
,
vx
et vy
et il est soumis à la force d'attraction terrestre. Au temps t + dt
, la position et la vitesse du boulet sont modifiées en utilisant les valeurs précédentes :
x = x + vx * dt
,
y = y + vy * dt
,
vx = vx
, autrement dit, la valeur vx
ne change pas (car on néglige les frottements),
vy = vy - m * G * dt
, où m
est la masse du boulet et G
est la constante gravitationnelle de la terre (9.81
).
Attention : dans ces formules, la différence de temps dt
est exprimé en secondes.
Pour que la modélisation ressemble à la réalité physique, il faut que dt
soit assez petit.
Écrivez une fonction "trajectoire_boulet
" qui prend en argument les valeurs suivantes :
angle
: l'angle du canon, en degrés, par rapport à l'horizontal
masse
: la masse, en kilogramme, du boulet de canon (5kg est une valeur pertinente)
vitesse
: la vitesse, en mètre/s, du boulet à la sortie du canon (125 m/s est une valeur pertinente).
dt
: l'intervalle de temps pour les calculs successifs, en centièmes de secondes. Si cette valeur n'est pas fournie, votre fonction utilisera la valeur 1
par défaut.
freq
: la fréquence des affichages. En effet, si l'on dessine le boulet trop souvent, on ne pourra pas voir les positions successives du boulet. Une valeur de ce paramètre de 50 n'affichera donc qu'une position sur 50. Si cette valeur n'est pas donnée, votre fonction utilisera la valeur 10
par défaut.
La valeur de retour de la fonction est la distance parcourue par le boulet avant qu'il touche le sol. (Il s'agit donc de la dernière valeur de x
.)
Votre fonction devra afficher (en utilisant la procédure dessine_boulet(x,y)
) le boulet aux positions intermédiaires appropriées (argument freq
).
Vous devez écrire votre fonction dans le fichier à trous suivant : boulet.py.
from math import sin,cos,pi
"Run" -> "Run Module F5"
) et d'utiliser la petite interface.
Nous cherchons maintenant à atteindre une cible, avec une précision de 1 mètre. Pour ceci, il faudra tirer des boulets (avec la fonction trajectoire_boulet
) et modifier l'angle en fonction de la distance parcourue par le boulet : on commence par tirer un boulet à 45° pour obtenir la distance maximale que l'on peut atteindre.
Écrivez la fonction dichotomie
, qui prend en argument :
cible
: la distance entre le canon et la cible, en mètres,
masse
, vitesse
, dt
et freq
avec la même interprétation que dans la question précédente.
Votre fonction appellera la fonction précédente trajectoire
pour calculer et afficher les trajectoires du boulet.
boulet.py
. Ça ne change rien, mais les tests sont plus interessants...