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()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.