derivateur2000.py
Created by
maelg0000
Created on
April 07, 2026
13.7 KB
from kandinsky import draw_string as ds
from kandinsky import fill_rect as fr
from ion import keydown
W = ( 255 , 255 , 255 )
B = ( 0 , 0 , 0 )
V = ( 0 , 120 , 0 )
R = ( 200 , 0 , 0 )
O = ( 200 , 150 , 0 )
BL = ( 0 , 100 , 200 )
# Touches
K_OK = 4
K_UP = 1
K_DOWN = 2
K_BACK = 5
T = []
P = 0
# === TUTORIELS ===
TUTOS = {
" facteur " :[
" FACTORISATION a^2-b^2 " ,
" ================== " ,
"" ,
" Identite remarquable: " ,
" a^2 - b^2 = (a+b)(a-b) " ,
"" ,
" Exemple: (x^2-1)/(x-1) " ,
"" ,
" Etape 1: Reconnaitre " ,
" x^2-1 = x^2 - 1^2 " ,
" Donc a=x et b=1 " ,
"" ,
" Etape 2: Factoriser " ,
" x^2-1 = (x+1)(x-1) " ,
"" ,
" Etape 3: Simplifier " ,
" (x+1)(x-1)/(x-1) " ,
" = x+1 " ,
"" ,
" Etape 4: Deriver " ,
" d/dx(x+1) = 1 " ,
"" ,
" Reponse finale: 1 " ,
],
" trigo " :[
" IDENTITE TRIGONOMETRIQUE " ,
" ======================== " ,
"" ,
" Formule fondamentale: " ,
" sin^2(x) + cos^2(x) = 1 " ,
"" ,
" Donc la derivee de 1 = 0 " ,
"" ,
" Exemple: " ,
" f(x) = sin(x)^2+cos(x)^2 " ,
"" ,
" Etape 1: Reconnaitre " ,
" C ' est sin^2 + cos^2 " ,
"" ,
" Etape 2: Simplifier AVANT " ,
" f(x) = 1 " ,
"" ,
" Etape 3: Deriver " ,
" f ' (x) = 0 " ,
"" ,
" Autres identites utiles: " ,
" 1+tan^2 = 1/cos^2 " ,
" 1+cot^2 = 1/sin^2 " ,
],
" expln " :[
" SIMPLIFICATION exp(ln) " ,
" ====================== " ,
"" ,
" Regles fondamentales: " ,
" exp(ln(x)) = x " ,
" ln(exp(x)) = x " ,
"" ,
" Ce sont des fonctions " ,
" inverses l ' une de l ' autre! " ,
"" ,
" Exemple: exp(ln(x^2)) " ,
"" ,
" Etape 1: Appliquer la regle " ,
" exp(ln(x^2)) = x^2 " ,
"" ,
" Etape 2: Deriver " ,
" d/dx(x^2) = 2x " ,
"" ,
" Reponse: 2x " ,
"" ,
" Autre exemple: ln(exp(3x)) " ,
" = 3x " ,
" Derivee = 3 " ,
],
" denom " :[
" REDUCTION DENOMINATEURS " ,
" ======================= " ,
"" ,
" Quand vous avez: " ,
" a/b + c/d " ,
"" ,
" Etape 1: Trouver denom commun " ,
" = (a*d + c*b) / (b*d) " ,
"" ,
" Exemple: 1/x + 1/x^2 " ,
"" ,
" Etape 1: Denom commun = x^2 " ,
" 1/x = x/x^2 " ,
"" ,
" Etape 2: Additionner " ,
" x/x^2 + 1/x^2 " ,
" = (x+1)/x^2 " ,
"" ,
" Astuce: Chercher le PPCM " ,
" des denominateurs. " ,
],
" long " :[
" EXPRESSION COMPLEXE " ,
" =================== " ,
"" ,
" Strategies possibles: " ,
"" ,
" 1. FACTORISER " ,
" Chercher facteur commun " ,
" Ex: 2x+2 = 2(x+1) " ,
"" ,
" 2. DEVELOPPER " ,
" Parfois plus simple " ,
" Ex: (x+1)^2 = x^2+2x+1 " ,
"" ,
" 3. REGROUPER " ,
" Termes similaires " ,
" Ex: 2x+3x = 5x " ,
"" ,
" 4. IDENTITES " ,
" sin^2+cos^2 = 1 " ,
" exp(ln(x)) = x " ,
"" ,
" Conseil: Simplifier AVANT " ,
" de deriver si possible! " ,
],
}
def tok ( s ):
r = []
i = 0
while i < len ( s ):
c = s [ i ]
if c == ' ' :
i += 1
elif c == ' * ' and i + 1 < len ( s ) and s [ i + 1 ] == ' * ' :
r . append ( ' ^ ' ) # ** devient ^
i += 2
elif c in ' +-*/^() ' :
r . append ( c )
i += 1
elif c . isdigit () or c == ' . ' :
j = i
while j < len ( s ) and ( s [ j ]. isdigit () or s [ j ] == ' . ' ):
j += 1
v = s [ i : j ]
r . append (( ' n ' , float ( v ) if ' . ' in v else int ( v )))
i = j
elif c . isalpha ():
j = i
while j < len ( s ) and s [ j ]. isalpha ():
j += 1
w = s [ i : j ]
if w == ' x ' :
r . append ( ' x ' )
elif w in ( ' sin ' , ' cos ' , ' exp ' , ' ln ' , ' tan ' , ' sqrt ' ):
r . append (( ' f ' , w ))
i = j
else :
i += 1
o = []
for i , t in enumerate ( r ):
if i > 0 :
p = r [ i - 1 ]
if ( type ( p ) == tuple and p [ 0 ] == ' n ' ) or p == ' x ' or p == ' ) ' :
if t == ' x ' or t == ' ( ' or ( type ( t ) == tuple and t [ 0 ] == ' f ' ):
o . append ( ' * ' )
o . append ( t )
return o
def pk ():
return T [ P ] if P < len ( T ) else None
def eat ():
global P
t = T [ P ]
P += 1
return t
def parse ( s ):
global T , P
T = tok ( s )
P = 0
return expr ()
def expr ():
l = term ()
while pk () in ( ' + ' , ' - ' ):
o = eat ()
l = ( o , l , term ())
return l
def term ():
l = fact ()
while pk () in ( ' * ' , ' / ' ):
o = eat ()
l = ( o , l , fact ())
return l
def fact ():
b = una ()
if pk () == ' ^ ' :
eat ()
return ( ' ^ ' , b , fact ())
return b
def una ():
if pk () == ' - ' :
eat ()
return ( ' ~ ' , una ())
if pk () == ' + ' :
eat ()
return una ()
return atm ()
def atm ():
t = pk ()
if t == ' ( ' :
eat ()
n = expr ()
if pk () == ' ) ' : eat ()
return n
if t == ' x ' :
eat ()
return ' x '
if type ( t ) == tuple :
if t [ 0 ] == ' n ' :
eat ()
return t
if t [ 0 ] == ' f ' :
eat ()
fn = t [ 1 ]
if pk () == ' ( ' :
eat ()
a = expr ()
if pk () == ' ) ' : eat ()
if fn == ' sqrt ' :
return ( ' ^ ' , a ,( ' n ' , 0.5 ))
return ( fn , a )
return ( ' n ' , 0 )
def cst ( n ):
if n == ' x ' : return False
if type ( n ) == tuple :
if n [ 0 ] == ' n ' : return True
if len ( n ) == 3 : return cst ( n [ 1 ]) and cst ( n [ 2 ])
if len ( n ) == 2 : return cst ( n [ 1 ])
return True
def inum ( n ):
return type ( n ) == tuple and n [ 0 ] == ' n '
def nval ( n ):
return n [ 1 ] if inum ( n ) else None
def skey ( n ):
if n == ' x ' : return ' x '
if inum ( n ): return ' 0 ' + str ( n [ 1 ])
if type ( n ) == tuple :
o = n [ 0 ]
if o in ( ' sin ' , ' cos ' , ' tan ' , ' exp ' , ' ln ' ):
return o + skey ( n [ 1 ])
if o == ' ~ ' :
return ' ~ ' + skey ( n [ 1 ])
if len ( n ) == 3 :
return o + skey ( n [ 1 ]) + skey ( n [ 2 ])
return str ( n )
def csort ( a , b ):
if skey ( a ) > skey ( b ):
return ( b , a , True )
return ( a , b , False )
def sadd ( a , b ):
if inum ( a ) and nval ( a ) == 0 : return b
if inum ( b ) and nval ( b ) == 0 : return a
if inum ( a ) and inum ( b ): return ( ' n ' , nval ( a ) + nval ( b ))
sa , sb = skey ( a ), skey ( b )
if sa == sb : return smul (( ' n ' , 2 ), a )
if type ( b ) == tuple and b [ 0 ] == ' ~ ' :
return ssub ( a , b [ 1 ])
if type ( a ) == tuple and a [ 0 ] == ' ~ ' :
return ssub ( b , a [ 1 ])
return ( ' + ' , a , b )
def ssub ( a , b ):
if inum ( b ) and nval ( b ) == 0 : return a
if inum ( a ) and nval ( a ) == 0 : return sneg ( b )
if inum ( a ) and inum ( b ): return ( ' n ' , nval ( a ) - nval ( b ))
if skey ( a ) == skey ( b ): return ( ' n ' , 0 )
if type ( b ) == tuple and b [ 0 ] == ' ~ ' :
return sadd ( a , b [ 1 ])
return ( ' - ' , a , b )
def smul ( a , b ):
if inum ( a ) and nval ( a ) == 0 : return ( ' n ' , 0 )
if inum ( b ) and nval ( b ) == 0 : return ( ' n ' , 0 )
if inum ( a ) and nval ( a ) == 1 : return b
if inum ( b ) and nval ( b ) == 1 : return a
if inum ( a ) and nval ( a ) ==- 1 : return sneg ( b )
if inum ( b ) and nval ( b ) ==- 1 : return sneg ( a )
if inum ( a ) and inum ( b ): return ( ' n ' , nval ( a ) * nval ( b ))
a , b , sw = csort ( a , b )
sa , sb = skey ( a ), skey ( b )
if sa == sb : return ( ' ^ ' , a ,( ' n ' , 2 ))
if type ( a ) == tuple and a [ 0 ] == ' ~ ' :
if type ( b ) == tuple and b [ 0 ] == ' ~ ' :
return smul ( a [ 1 ], b [ 1 ])
return sneg ( smul ( a [ 1 ], b ))
if type ( b ) == tuple and b [ 0 ] == ' ~ ' :
return sneg ( smul ( a , b [ 1 ]))
if inum ( a ) and type ( b ) == tuple and b [ 0 ] == ' * ' :
if inum ( b [ 1 ]):
return smul (( ' n ' , nval ( a ) * nval ( b [ 1 ])), b [ 2 ])
if type ( b ) == tuple and b [ 0 ] == ' ^ ' and sa == skey ( b [ 1 ]):
if inum ( b [ 2 ]):
return ( ' ^ ' , a ,( ' n ' , nval ( b [ 2 ]) + 1 ))
return ( ' * ' , a , b )
def sdiv ( a , b ):
if inum ( a ) and nval ( a ) == 0 : return ( ' n ' , 0 )
if inum ( b ) and nval ( b ) == 1 : return a
if inum ( a ) and inum ( b ) and nval ( b ) != 0 :
v = nval ( a ) / nval ( b )
if v == int ( v ): return ( ' n ' , int ( v ))
return ( ' n ' , v )
if skey ( a ) == skey ( b ): return ( ' n ' , 1 )
if type ( b ) == tuple and b [ 0 ] == ' ^ ' and skey ( a ) == skey ( b [ 1 ]):
if inum ( b [ 2 ]):
ne = 1 - nval ( b [ 2 ])
if ne == 0 : return ( ' n ' , 1 )
if ne == 1 : return a
return ( ' ^ ' , a ,( ' n ' , ne ))
return ( ' / ' , a , b )
def spow ( a , b ):
if inum ( b ) and nval ( b ) == 0 : return ( ' n ' , 1 )
if inum ( b ) and nval ( b ) == 1 : return a
if type ( a ) == tuple and a [ 0 ] == ' ^ ' and inum ( a [ 2 ]) and inum ( b ):
return ( ' ^ ' , a [ 1 ],( ' n ' , nval ( a [ 2 ]) * nval ( b )))
return ( ' ^ ' , a , b )
def sneg ( a ):
if inum ( a ): return ( ' n ' , - nval ( a ))
if type ( a ) == tuple and a [ 0 ] == ' ~ ' : return a [ 1 ]
if type ( a ) == tuple and a [ 0 ] == ' * ' and inum ( a [ 1 ]):
return ( ' * ' ,( ' n ' , - nval ( a [ 1 ])), a [ 2 ])
return ( ' ~ ' , a )
def D ( n ):
if n == ' x ' : return ( ' n ' , 1 )
if type ( n ) != tuple : return ( ' n ' , 0 )
o = n [ 0 ]
if o == ' n ' : return ( ' n ' , 0 )
if o == ' ~ ' : return sneg ( D ( n [ 1 ]))
if o == ' + ' : return sadd ( D ( n [ 1 ]), D ( n [ 2 ]))
if o == ' - ' : return ssub ( D ( n [ 1 ]), D ( n [ 2 ]))
if o == ' * ' :
u , v = n [ 1 ], n [ 2 ]
return sadd ( smul ( D ( u ), v ), smul ( u , D ( v )))
if o == ' / ' :
u , v = n [ 1 ], n [ 2 ]
return sdiv ( ssub ( smul ( D ( u ), v ), smul ( u , D ( v ))), spow ( v ,( ' n ' , 2 )))
if o == ' ^ ' :
u , e = n [ 1 ], n [ 2 ]
if cst ( e ):
return smul ( smul ( e , spow ( u , ssub ( e ,( ' n ' , 1 )))), D ( u ))
else :
return smul ( n , sadd ( smul ( D ( e ),( ' ln ' , u )), smul ( e , sdiv ( D ( u ), u ))))
if o == ' sin ' : return smul ( D ( n [ 1 ]),( ' cos ' , n [ 1 ]))
if o == ' cos ' : return sneg ( smul ( D ( n [ 1 ]),( ' sin ' , n [ 1 ])))
if o == ' exp ' : return smul ( D ( n [ 1 ]),( ' exp ' , n [ 1 ]))
if o == ' ln ' : return sdiv ( D ( n [ 1 ]), n [ 1 ])
if o == ' tan ' : return sdiv ( D ( n [ 1 ]), spow (( ' cos ' , n [ 1 ]),( ' n ' , 2 )))
return ( ' n ' , 0 )
def S ( n ):
if type ( n ) != tuple : return n
if n [ 0 ] == ' n ' : return n
o = n [ 0 ]
if o == ' ~ ' :
return sneg ( S ( n [ 1 ]))
if o == ' exp ' :
a = S ( n [ 1 ])
if type ( a ) == tuple and a [ 0 ] == ' ln ' :
return a [ 1 ]
return ( ' exp ' , a )
if o == ' ln ' :
a = S ( n [ 1 ])
if type ( a ) == tuple and a [ 0 ] == ' exp ' :
return a [ 1 ]
return ( ' ln ' , a )
if o in ( ' sin ' , ' cos ' , ' tan ' ):
return ( o , S ( n [ 1 ]))
if len ( n ) < 3 : return n
a , b = S ( n [ 1 ]), S ( n [ 2 ])
if o == ' + ' : return sadd ( a , b )
if o == ' - ' : return ssub ( a , b )
if o == ' * ' : return smul ( a , b )
if o == ' / ' : return sdiv ( a , b )
if o == ' ^ ' : return spow ( a , b )
return ( o , a , b )
def ts ( n ):
if n == ' x ' : return ' x '
if type ( n ) != tuple : return str ( n )
o = n [ 0 ]
if o == ' n ' :
v = n [ 1 ]
if type ( v ) == float and v == int ( v ): v = int ( v )
return str ( v )
if o == ' ~ ' :
s = ts ( n [ 1 ])
if type ( n [ 1 ]) == tuple and n [ 1 ][ 0 ] in ( ' + ' , ' - ' ):
return ' -( ' + s + ' ) '
return ' - ' + s
if o in ( ' sin ' , ' cos ' , ' exp ' , ' ln ' , ' tan ' ):
return o + ' ( ' + ts ( n [ 1 ]) + ' ) '
l , r = ts ( n [ 1 ]), ts ( n [ 2 ])
if o in ( ' + ' , ' - ' ): return l + o + r
if o == ' * ' :
if type ( n [ 1 ]) == tuple and n [ 1 ][ 0 ] in ( ' + ' , ' - ' ): l = ' ( ' + l + ' ) '
if type ( n [ 2 ]) == tuple and n [ 2 ][ 0 ] in ( ' + ' , ' - ' ): r = ' ( ' + r + ' ) '
return l + ' * ' + r
if o == ' / ' :
if type ( n [ 1 ]) == tuple and n [ 1 ][ 0 ] in ( ' + ' , ' - ' ): l = ' ( ' + l + ' ) '
if type ( n [ 2 ]) == tuple and n [ 2 ][ 0 ] in ( ' + ' , ' - ' , ' * ' , ' / ' ): r = ' ( ' + r + ' ) '
return l + ' / ' + r
if o == ' ^ ' :
if type ( n [ 1 ]) == tuple and n [ 1 ][ 0 ] in ( ' + ' , ' - ' , ' * ' , ' / ' ): l = ' ( ' + l + ' ) '
return l + ' ^ ' + r
return ' ? '
def detect ( f , res ):
r = ts ( res )
if ' / ' in f :
if ' ^2- ' in f or ' -1)/ ' in f :
return ( " facteur " , " Factorisation requise " )
if ' sin ' in f and ' cos ' in f and ' + ' in f :
return ( " trigo " , " Identite trigo " )
if ' exp(ln ' in f or ' ln(exp ' in f :
return ( " expln " , " Simplifier exp/ln " )
if r . count ( ' / ' ) > 1 :
return ( " denom " , " Reduire fractions " )
if len ( r ) > 40 :
return ( " long " , " Expression complexe " )
return None
# === AFFICHAGE SCROLLABLE ===
def show_tuto ( key ):
if key not in TUTOS :
return
lines = TUTOS [ key ]
total = len ( lines )
scroll = 0
maxl = 11 # lignes visibles (222/18 ~ 12, -1 pour instruction)
while True :
fr ( 0 , 0 , 320 , 222 , W )
# Afficher les lignes visibles
y = 5
for i in range ( scroll , min ( scroll + maxl , total )):
line = lines [ i ]
if i == 0 :
ds ( line , 5 , y ,( 100 , 0 , 150 ), W )
elif line . startswith ( " Etape " ):
ds ( line , 5 , y , BL , W )
elif line . startswith ( " " ):
ds ( line , 5 , y ,( 80 , 80 , 80 ), W )
elif " = " in line and len ( line ) < 25 :
ds ( line , 5 , y , V , W )
else :
ds ( line , 5 , y , B , W )
y += 18
# Indicateur de scroll
if scroll > 0 :
ds ( " ^ " , 155 , y ,( 150 , 150 , 150 ), W )
if scroll + maxl < total :
ds ( " v " , 155 , y + 10 ,( 150 , 150 , 150 ), W )
# Instructions
ds ( " [UP/DOWN] [BACK=quit] " , 50 , 205 ,( 100 , 100 , 100 ), W )
# Attendre input
while True :
if keydown ( K_UP ):
if scroll > 0 :
scroll -= 1
while keydown ( K_UP ): pass
break
if keydown ( K_DOWN ):
if scroll + maxl < total :
scroll += 1
while keydown ( K_DOWN ): pass
break
if keydown ( K_BACK ):
return
if keydown ( K_OK ):
return
def aff ( t , y , c ):
while len ( t ) > 30 :
ds ( t [: 30 ], 5 , y , c , W )
t = t [ 30 :]
y += 18
ds ( t , 5 , y , c , W )
return y + 18
def main ():
fr ( 0 , 0 , 320 , 222 , W )
ds ( " DERIVATEUR v3 " , 90 , 5 ,( 50 , 50 , 150 ), W )
f = input ( " f(x) = " )
fr ( 0 , 40 , 320 , 182 , W )
ds ( " f(x)= " , 5 , 42 , B , W )
y = aff ( f , 58 ,( 80 , 80 , 80 ))
try :
tree = parse ( f )
d = D ( tree )
for _ in range ( 10 ):
d = S ( d )
ds ( " f ' (x)= " , 5 , y + 5 , B , W )
y = aff ( ts ( d ), y + 22 , V )
# Detection
hint = detect ( f , d )
if hint :
y += 10
ds ( " ! " + hint [ 1 ], 5 , y , O , W )
ds ( " [OK] pour aide " , 5 , y + 18 , BL , W )
# Attendre OK ou BACK
while True :
if keydown ( K_OK ):
while keydown ( K_OK ): pass
show_tuto ( hint [ 0 ])
# Re-afficher resultat
fr ( 0 , 0 , 320 , 222 , W )
ds ( " f(x)= " + f [: 20 ], 5 , 5 , B , W )
ds ( " f ' (x)= " , 5 , 30 , B , W )
aff ( ts ( d ), 48 , V )
ds ( " ! " + hint [ 1 ], 5 , 100 , O , W )
ds ( " [BACK] quitter " , 5 , 120 , BL , W )
if keydown ( K_BACK ):
break
except :
ds ( " Erreur syntaxe! " , 5 , y + 10 , R , W )
main ()