Un cancre doit simplifier la fraction $\frac{16}{64}$. Il "raisonne" ainsi: $\frac{1{\not{6}}}{{\not{6}}4} = \frac{1}{4}$.
Un prof de maths écrit un exercice de contrôle sur le thème des fractions. Pour cela, il choisit un entier à deux chiffres au hasard (cet entier sera le numérateur) puis il choisit le dénominateur au hasard parmi les entiers à deux chiffres distincts du numérateur.
La consigne est de donner la forme irréductible de la fraction ainsi constituée. L'enseignant donne la consigne de ne pas écrire les détails.
La note sera 1 pour une réponse correcte, 0 pour une réponse incorrecte.
Quelle est la probabilité que le cancre gagne un point?
On résoudra la question à l'aide d'un script python.
Les entiers $a$ et $b$ à manipuler n'ayant que deux chiffres et étant distincts, ils ont au plus un chiffre commun.
Si l'on cherche à prolonger la question à des entiers de plus de deux chiffres, le problème se complique. Le cancre pourra en effet chercher à simplifier une fraction telle que $\frac{919}{69}$ de deux façons différentes (obtenant soit $\frac{19}{6}$, soit $\frac{91}{6}$).
Le cancre verra sa réponse comptée comme juste dans les cas suivants:
Ecrire une fonction python cancreSimplifiable(a,b)
prenant en paramètres les entiers naturels $a$ et $b$ ($b\neq 0$) et renvoyant True
si une simplification-cancre peut être opérée et False
sinon. On se limite ici à une fonction traitant les entiers a et b à deux chiffres.
def cancreSimplifiable(a,b):
"""
a et b sont deux entiers naturels (b non nul).
a et b sont compris entre 10 et 99 et distincts.
La fonction renvoie True si a et b ont un chiffre commun
(dans leur écriture en base 10).
"""
assert(10 <= a <= 99)
assert(10 <= b <= 99)
a = (a%10, a//10)
b = (b%10, b//10)
return a[0]==b[0] or a[1]==b[1] or a[0]==b[1] or a[1]==b[0]
cancreSimplifiable(22, 32)
cancreSimplifiable(21,34)
from math import gcd
def nbIrreductibleNonCancreSimplifiable():
"""
La fonction renvoie le nombre de fractions a/b telles que:
- a est différent de b
- a et b sont compris entre 10 et 99
- aucune simplication du cancre n'est applicable à la fraction a/b
- la fraction a/b est irréductible
"""
compteur = 0
for a in range(10,100):
for b in range(10,100):
if gcd(a,b)==1 and not(cancreSimplifiable(a,b)):
compteur += 1
return compteur
nbIrreductibleNonCancreSimplifiable()
def cancreSimplifiableCorrectIrreductible(a,b):
"""
a et b sont deux entiers naturels distincts, compris entre 10 et 99.
La fonction renvoie True si:
- la fraction a/b peut subir une simplification du cancre.
- le résultat de cette simplification est correct et irréductible
La fonction renvoie False sinon.
"""
assert(10 <= a <= 99)
assert(10<= b <= 99)
assert(a != b)
A = (a%10, a//10)
B = (b%10, b//10)
if A[0]==B[0] and a*B[1]==b*A[1] and gcd(A[1], B[1])==1: return True
if A[1]==B[1] and a*B[0]==b*A[0] and gcd(A[0], B[0])==1: return True
if A[0]==B[1] and a*B[0]==b*A[1] and gcd(A[1], B[0])==1: return True
if A[1]==B[0] and a*B[1]==b*A[0] and gcd(A[0], B[1])==1: return True
return False
cancreSimplifiableCorrectIrreductible(16,64)
cancreSimplifiableCorrectIrreductible(64,16)
49/98 == 4/8
from math import gcd
gcd(49,98)
cancreSimplifiableCorrectIrreductible(49,98)
def nbCancreSimplifiableCorrectIrreductible():
"""
La fonction renvoie le nombre de fractions a/b telles que:
- a est différent de b
- a et b sont compris entre 10 et 99.
- la fraction a/b peut subir une simpliciation du cancre
- cette simplification-cancre mène à un résultat correct et irréductible
"""
compteur = 0
for a in range(10,100):
for b in [k for k in range(10,100) if k!=a]:
if cancreSimplifiableCorrectIrreductible(a,b):
compteur += 1
return compteur
nbCancreSimplifiableCorrectIrreductible()
Le nombre de couples $(a;b)$ avec $10 \leqslant a \leqslant 99$, $10 \leqslant b \leqslant 99$, $a\neq b$ est égal à $(99-10+1)\times(99-10+1) - 90 = 8010$.
def nbCouples():
"""
La fonction renvoie le nombre de couples (a,b) tels que
- a est différent de b
- a et b sont compris entre 10 et 99
"""
compteur = 0
for a in range(10,100):
for b in [k for k in range(10,100) if k!=a]:
compteur += 1
return compteur
nbCouples()
La probabilité que l'enseignant choisisse une fraction permettant au cancre de gagner un point est donc égale à $\frac{60+3284}{8010}$.
(60+3284)/8010
Ecrire une fonction python calculant la liste des couples $(a;b)$ tels que $a\neq b$, $10 \leqslant a \leqslant 99$, $10\leqslant b \leqslant 99$ et la fraction $\frac{a}{b}$ peut subir une simplification du cancre donnant un résultat correct (non nécessairement irréductible).
On éliminera d'office tous les cas $\frac{20}{60}$, $\frac{80}{30}$, ... (rapport de deux multiples de 10) pour ne pas surcharger l'affichage.
def cancreSimplifiableCorrect(a,b):
"""
a et b sont deux entiers naturels distincts, compris entre 10 et 99.
La fonction renvoie True si:
- la fraction a/b peut subir une simplification du cancre.
- le résultat de cette simplification est correct.
La fonction renvoie False sinon.
"""
assert(10 <= a <= 99)
assert(10<= b <= 99)
assert(a != b)
A = (a%10, a//10)
B = (b%10, b//10)
if A[0]==B[0] and a*B[1]==b*A[1]: return True
if A[1]==B[1] and a*B[0]==b*A[0]: return True
if A[0]==B[1] and a*B[0]==b*A[1]: return True
if A[1]==B[0] and a*B[1]==b*A[0]: return True
return False
def listeCancreSimplifiableCorrect():
"""
Renvoie la liste des couples (a,b) avec:
- a distinct de b
- a et b entre 0 et 99
- une simplification cancre est possible et donne un résultat correct
- a et b ne sont pas tous deux multiples de 10
"""
liste = []
for a in range(10,100):
for b in [k for k in range(10,100) if k!=a]:
if not(a%10==0) or not(b%10==0):
if cancreSimplifiableCorrect(a,b):
liste.append((a,b))
return liste
listeCancreSimplifiableCorrect()
Objectif: réécrire la fonction cancreSimplifiable(a,b)
mais pour des entiers naturels a et b non limités à deux chiffres.
Le chiffre des unités est le chiffre de poids 0, le chiffre des dizaines est le chiffre de poids 1, le chiffre des centaines est le chiffre de poids 2, le chiffre des milliers est le chiffre de poids 3, etc...
Ecrire une fonction python chiffre(entier, poids)
prenant en paramètres deux entiers naturels et renvoyant le chiffre de poids "poids" de l'entier "entier".
def chiffre(entier, poids):
"""
entier est un entier naturel.
poids est un entier naturel.
La fonction renvoie le chiffre de poids "poids" de l'entier "entier".
Exemples:
chiffre(125, 0) = 5
chiffre(125, 1) = 2
chiffre(125, 2) = 1
chiffre(125, n) = 0 où n > 2
"""
A = entier // (10**poids)
return A % 10
chiffre(125, 0)
chiffre(125, 2)
Ecrire une fonction python nbChiffres(n)
prenant un entier naturel en entrée et renvoyant le nombre de chiffres de cet entier (dans son écriture en base 10).
def nbChiffres(n):
"""
n est un entier naturel.
La fonction renvoie le nombre de chiffres de l'écriture décimale de n.
"""
if n < 10: return 1 # cas particulier pour n = 0 notamment
nb = 0
while n != 0:
nb += 1
n = n//10
return nb
nbChiffres(124)
nbChiffres(0)
Ecrire une fonction python cancreSimplifiableG(a,b)
qui renvoie True si on peut appliquer une simplification du cancre à la fraction $\frac{a}{b}$ (c'est à dire si les écritures décimales de a et b présentent au moins un chiffre commun).
def cancreSimplifiableG(a,b):
"""
a et b sont deux entiers naturels.
La fonction renvoie True si les écritures décimales de a et b
présentent au moins un chiffre commun.
"""
# nombre de chiffres des deux entiers:
la, lb = nbChiffres(a), nbChiffres(b)
# pour chaque poids possible pour a
# pour chaque poids possible pour b
for pa in range(la):
for pb in range(lb):
if chiffre(a,pa)==chiffre(b,pb): return True
return False
cancreSimplifiableG(16,64)
cancreSimplifiableG(919,92)
cancreSimplifiableG(987,6543)
On voudrait "barrer un chiffre" de l'écriture d'un entier pour obtenir l'entier écrit sans ce chiffre.
Exemples:
Définir une fonction python barrerChiffre(entier, poids)
qui renverra l'entier obtenu en barrant le chiffre de poids "poids" de l'entier "entier".
def barrerChiffre(entier, poids):
"""
entier est un entier naturel.
poids est un entier naturel.
La fonction renvoie l'entier dont l'écriture est
celle de "entier" sans son chiffre de poids "poids".
Exemples:
chiffre(125, 0) = 12
chiffre(125, 1) = 15
chiffre(125, 2) = 25
chiffre(125, n) = 125 où n > 2
"""
queue = entier % (10**poids)
tete = entier // (10**(poids+1))
return tete * 10**poids + queue
barrerChiffre(125, 0)
barrerChiffre(125, 2)
Ecrire une fonction python cancreSimplifiableCorrectG(a,b)
prenant en paramètres deux entiers naturels a et b et renvoyant True lorsqu'une simplification du cancre menant à un résultat correct est possible (et renvoyant False sinon).
def cancreSimplifiableCorrectG(a,b):
la = nbChiffres(a)
lb = nbChiffres(b)
for pa in range(la):
for pb in range(lb):
if chiffre(a,pa)==chiffre(b,pb) and a*barrerChiffre(b,pb)==b*barrerChiffre(a,pa):
return True
return False
cancreSimplifiableCorrectG(64,16)
La fonction précédente a le défaut de ne pas donner le rang des chiffres simplifiables menant à un résultat correct. Lorsque plusieurs chiffres sont communs, cela est gênant. Ecrire une fonction corrigeant ce problème.
def cancreSimplifiableCorrectAvecPoids(a,b):
"""
Renvoie le premier couple de poids trouvé correspondant
à une simplification du cancre "valide" sur la fraction a/b.
"""
la = nbChiffres(a)
lb = nbChiffres(b)
for pa in range(la):
for pb in range(lb):
if chiffre(a,pa)==chiffre(b,pb) and a*barrerChiffre(b,pb)==b*barrerChiffre(a,pa):
return (pa,pb)
return False
cancreSimplifiableCorrectAvecPoids(16,64)
def listeCancreSimplifiableCorrectAvecPoids(a,b):
"""
Renvoie la liste des couples de poids correspondant
à une simplification du cancre "valide" sur la fraction a/b.
"""
liste = []
la = nbChiffres(a)
lb = nbChiffres(b)
for pa in range(la):
for pb in range(lb):
if chiffre(a,pa)==chiffre(b,pb) and a*barrerChiffre(b,pb)==b*barrerChiffre(a,pa):
liste.append((a,b, pa, pb))
return liste
listeCancreSimplifiableCorrectAvecPoids(16,64)
listeCancreSimplifiableCorrectAvecPoids(177,9735)
Le cas de $\frac{177}{9735}$ qui se simplifie de deux façons est un peu "décevant": la suppression de l'un ou l'autre des 7 du numérateur est en fait la même.
Ecrire un script python cherchant des exemples où plusieurs simplications cancres valides sont présentes mais sans le cas de chiffres consécutifs égaux.
def consecutifsId(n):
"""
n est un entier naturel.
La fonction renvoie True si l'écriture décimale de n
présente au moins deux chiffres consécutifs identiques.
"""
if n < 10: return False
chiffre1 = n%10
while n != 0:
n = n//10
chiffre2 = n%10
if chiffre2 == chiffre1: return True
chiffre1 = chiffre2
return False
consecutifsId(11)
consecutifsId(212)
def cspfsrcc(ma, Ma, mb, Mb):
"""
Renvoie une liste de fractions a/b telles que:
- a et b sont différents,
- a est compris entre ma et Ma, b est compris entre mb et Mb,
- plusieurs simplifications du cancre sont possibles,
- les écritures décimales de a et de b ne présentent pas de chiffres consécutifs égaux.
- on évite également des relations trop simples entre a et b (a = 10b, a = 100b...)
ainsi que les cas où a et b sont tous deux multiples de 10.
"""
liste = []
for a in range(ma, Ma+1):
for b in range(mb, Mb+1):
if not(consecutifsId(a)) and not(consecutifsId(b)) and a!=b and (max(a,b)//min(a,b))%10 != 0:
if not(a%10==0 and b%10==0):
listeab = listeCancreSimplifiableCorrectAvecPoids(a,b)
if len(listeab) > 1: liste.append(listeab)
return liste
cspfsrcc(10, 10000, 10, 10000)
Exemple tiré de cette liste:
from fractions import *
Fraction(9765,3906), Fraction(765,306), Fraction(975,390), Fraction(75,30)