This shows you the differences between two versions of the page.
|
pp:24:laboratoare:tda [2026/02/12 14:40] mihaela.balint [Exemplu pe tipul Nat] |
pp:24:laboratoare:tda [2026/02/12 15:20] (current) mihaela.balint [Exerciții] |
||
|---|---|---|---|
| Line 26: | Line 26: | ||
| ==== Exemple (deocamdată fără axiome) ==== | ==== Exemple (deocamdată fără axiome) ==== | ||
| ^ Tip ^ Constructori de bază ^ Operatori ^ | ^ Tip ^ Constructori de bază ^ Operatori ^ | ||
| - | | **Nat (N)** | zero: -> N \\ succ: N -> N | add: N x N -> N \\ isZero: N -> B | | + | | **Nat (N)** | zero: -> N \\ succ: N -> N | add: N x N -> N \\ isZero: N -> Bool | |
| | **List (L)** | null: -> L \\ cons: E x L -> L | head: L -> E \\ tail: L -> L \\ len: L -> N \\ app: L x L -> L | | | **List (L)** | null: -> L \\ cons: E x L -> L | head: L -> E \\ tail: L -> L \\ len: L -> N \\ app: L x L -> L | | ||
| ==== Constructori de tip ==== | ==== Constructori de tip ==== | ||
| Line 49: | Line 49: | ||
| **Reguli pentru scrierea axiomelor:** | **Reguli pentru scrierea axiomelor:** | ||
| * **Acoperirea**: Axiomele trebuie să acopere toate valorile tipului. De aceea, definim comportamentul operatorilor în raport cu **constructorii de bază**. | * **Acoperirea**: Axiomele trebuie să acopere toate valorile tipului. De aceea, definim comportamentul operatorilor în raport cu **constructorii de bază**. | ||
| - | * **Neredundanța**: Axiomele trebuie să fie minimale. | + | * **Neredundanța**: Pentru facilitarea demonstrațiilor, scriem axiome minimale. |
| - | * **Exemplu**: La operația ''add(n, m)'', variem doar primul parametru între ''zero'' și ''succ(n)''. Nu este necesar să variem și al doilea parametru. În general, când există mai mulți parametri de același tip, scriem axiomele variind doar parametrul pe care vom face recursivitatea. | + | * **Exemplu**: La operația ''add(n, m)'', variem doar primul parametru între ''zero'' și ''succ(n)''. Nu este necesar să variem și al doilea parametru. În general, când există mai mulți parametri de același tip, scriem axiomele variind doar parametrii pe care vom face recursivitatea. |
| ==== Exemple (specificații complete) ==== | ==== Exemple (specificații complete) ==== | ||
| ^ Tip ^ Constructori de bază ^ Operatori ^ Axiome ^ | ^ Tip ^ Constructori de bază ^ Operatori ^ Axiome ^ | ||
| - | | **Nat (N)** | zero: -> N \\ succ: N -> N | add: N x N -> N \\ isZero: N -> B | (A1) add(zero, m) = m \\ (A2) add(succ(n), m) = succ(add(n, m)) \\ \\ (Z1) isZero(zero) = true \\ (Z2) isZero(succ(n)) = false | | + | | **Nat (N)** | zero: -> N \\ succ: N -> N | add: N x N -> N \\ isZero: N -> Bool | (A1) add(zero, m) = m \\ (A2) add(succ(n), m) = succ(add(n, m)) \\ \\ (Z1) isZero(zero) = true \\ (Z2) isZero(succ(n)) = false | |
| | **List (L)** | null: -> L \\ cons: E x L -> L | head: L -> E \\ tail: L -> L \\ len: L -> N \\ app: L x L -> L | (H1) head(null) = eroare \\ (H2) head(cons(x, L)) = x \\ \\ (T1) tail(null) = eroare \\ (T2) tail(cons(x, L)) = L \\ \\ (L1) len(null) = zero \\ (L2) len(cons(x, L)) = succ(len(L)) \\ \\ (P1) app(null, L2) = L2 \\ (P2) app(cons(x, L1), L2) = cons(x, app(L1, L2)) | | | **List (L)** | null: -> L \\ cons: E x L -> L | head: L -> E \\ tail: L -> L \\ len: L -> N \\ app: L x L -> L | (H1) head(null) = eroare \\ (H2) head(cons(x, L)) = x \\ \\ (T1) tail(null) = eroare \\ (T2) tail(cons(x, L)) = L \\ \\ (L1) len(null) = zero \\ (L2) len(cons(x, L)) = succ(len(L)) \\ \\ (P1) app(null, L2) = L2 \\ (P2) app(cons(x, L1), L2) = cons(x, app(L1, L2)) | | ||
| Line 65: | Line 65: | ||
| ==== Inducția Structurală ==== | ==== Inducția Structurală ==== | ||
| Inducția structurală este un caz particular al inducției bine formate, și se folosește pentru a demonstra că o proprietate $P(v)$ este adevărată pentru orice valoare $v$ a unui TDA: | Inducția structurală este un caz particular al inducției bine formate, și se folosește pentru a demonstra că o proprietate $P(v)$ este adevărată pentru orice valoare $v$ a unui TDA: | ||
| - | * **Cazul de bază**: Demonstrăm $P(v)$ pentru valori de dimensiune minimă (constructori nulari sau externi). | + | * **Cazul de bază**: \\ Demonstrăm $P(v)$ pentru valori de dimensiune minimă (constructori nulari sau externi). |
| - | * **Pasul inductiv**: Presupunem că $P$ este adevărată pentru toate valorile de dimensiune $< n$ (ipoteza inductivă) și demonstrăm pentru valori de dimensiune $n$ (obținute prin constructori interni). | + | * **Pasul inductiv**: \\ Presupunem că $P$ este adevărată pentru toate valorile de dimensiune $< n$ (ipoteza inductivă) și demonstrăm pentru valori de dimensiune $n$ (obținute prin constructori interni). |
| | | ||
| ==== Exemplu pe tipul Nat ==== | ==== Exemplu pe tipul Nat ==== | ||
| - | Demonstrăm că $add(n, zero) = n$, pentru orice număr natural $n$. | + | Demonstrăm că ''add(n, zero) = n'', pentru orice număr natural ''n''. |
| - | * **Cazul de bază**: $add(zero, zero) = zero$ (conform axiomei $A1$). | + | * **Cazul de bază**: add(zero, zero) = zero (conform axiomei ''A1''). |
| - | * **Pas inductiv**: Ipoteza inductivă: $add(n, zero) = n$. Demonstrăm proprietatea pentru $succ(n)$: | + | * **Pas inductiv**: Ipoteza inductivă: add(n, zero) = n. Demonstrăm proprietatea pentru ''succ(n)'': |
| - | * $add(succ(n), zero) = succ(n)$ <=> (conform $A2$) | + | * add(succ(n), zero) = succ(n) <=> (conform ''A2'') |
| - | * $succ(add(n, zero)) = succ(n)$ <=> (conform ipotezei inductive) | + | * succ(add(n, zero)) = succ(n) <=> (conform ''ipotezei inductive'') |
| - | * $succ(n) = succ(n)$ **q.e.d** | + | * succ(n) = succ(n) **q.e.d** |
| Line 82: | Line 82: | ||
| Chiar dacă problemele nu sunt formulate ca operatori ai unui TDA, procesul de "gândire funcțională" este următorul: | Chiar dacă problemele nu sunt formulate ca operatori ai unui TDA, procesul de "gândire funcțională" este următorul: | ||
| - | - **Pe ce variabile este util să fac recursivitate?** (Identificăm variabilele care se "micșorează" structural). | + | * **Pe ce variabile este util să fac recursivitate?** \\ Identificăm variabilele care se "micșorează" structural. |
| - | - **Cum mă ajută rezultatul subproblemei?** (ex: Dacă știu rezultatul pentru ''tail(L)'', cum obțin rezultatul pentru ''L''?). | + | * **Cum mă ajută rezultatul subproblemei?** \\ Ex: Dacă știu rezultatul pentru ''tail(L)'', cum obțin rezultatul pentru ''L''? |
| ==== Exemple de gândire ==== | ==== Exemple de gândire ==== | ||
| - | **nth (al n-lea element din listă)** | + | <code haskell> |
| - | * **Întrebare**: Pe ce variabile fac recursivitate? | + | nth (al n-lea element din listă) |
| - | * **Raționament**: A identifica al ''n''-lea element din ''L'' înseamnă a identifica al ''(n-1)''-lea element din ''tail(L)''. | + | </code> |
| - | * **Concluzie**: Pe numărul $n$ și pe lista $L$. | + | |
| - | * **Axiome (Cod):** | + | |
| - | * ''nth(null, n) = eroare'' (Lista nu are suficiente elemente). | + | |
| - | * ''nth(cons(x, L), zero) = x'' (Dacă am ajuns la indexul zero, rezultatul este primul element din listă). | + | |
| - | * ''nth(cons(x, L), succ(n)) = nth(L, n)'' (Al n+1-lea element din lista curentă este al n-lea element din restul listei). | + | |
| - | **duplicate (duplicarea fiecărui element al listei)** | + | **Întrebare**: Pe ce variabile fac recursivitate? \\ |
| - | * **Observație**: Există un singur parametru (''L''), deci o singură variabilă pe care pot face recursivitate. | + | **Raționament**: A identifica al ''n''-lea element din ''L'' înseamnă a identifica al ''(n-1)''-lea element din ''tail(L)''. \\ |
| - | * **Întrebare**: Cum transform rezultatul pentru ''tail(L)''? | + | **Concluzie**: Pe numărul ''n'' și pe lista ''L''. |
| - | * **Raționament**: Dacă am duplicat toate elementele din ''tail(L)'', trebuie doar să adaug de două ori ''head(L)'' la început. | + | |
| - | * **Axiome (Cod):** | + | |
| - | * ''duplicate(null) = null'' (Cazul de bază). | + | |
| - | * ''duplicate(cons(x, L)) = cons(x, cons(x, duplicate(L)))'' (Implementarea raționamentului anterior). | + | |
| + | <code haskell> | ||
| + | -- Axiome (cod) | ||
| + | nth(null, n) = eroare | ||
| + | nth(cons(x, L), zero) = x | ||
| + | nth(cons(x, L), succ(n)) = nth(L, n) | ||
| + | </code> | ||
| + | |||
| + | |||
| + | <code haskell> | ||
| + | duplicate (duplicarea fiecărui element al listei) | ||
| + | </code> | ||
| + | |||
| + | **Notă**: Există un singur parametru (''L''), deci o singură variabilă pe care pot face recursivitate. \\ | ||
| + | **Întrebare**: Cum transform rezultatul pentru ''tail(L)''? \\ | ||
| + | **Raționament**: Dacă am duplicat toate elementele din ''tail(L)'', trebuie doar să adaug de două ori ''head(L)'' la început. | ||
| + | |||
| + | <code haskell> | ||
| + | -- Axiome (cod) | ||
| + | duplicate(null) = null | ||
| + | duplicate(cons(x, L)) = cons(x, cons(x, duplicate(L))) | ||
| + | </code> | ||
| ===== Exerciții ===== | ===== Exerciții ===== | ||
| * Demonstrați prin inducție structurală proprietatea ''len(app(A, B)) = add(len(A), len(B))''. | * Demonstrați prin inducție structurală proprietatea ''len(app(A, B)) = add(len(A), len(B))''. | ||
| Line 112: | Line 124: | ||
| * **Ștergerea** elementului de la poziția ''n'' din listă (ex: ștergerea celui de-al treilea element din $[a, b, c, d, e, f, g]$ produce $[a, b, d, e, f, g]$). | * **Ștergerea** elementului de la poziția ''n'' din listă (ex: ștergerea celui de-al treilea element din $[a, b, c, d, e, f, g]$ produce $[a, b, d, e, f, g]$). | ||
| * **Simetria structurală**: Verificați dacă doi arbori binari sunt simetrici (ex: un arbore cu structura ''node(empty, x, node(empty, y, empty))'' este simetric cu unul de forma ''node(node(empty, z, empty), w, empty)''). | * **Simetria structurală**: Verificați dacă doi arbori binari sunt simetrici (ex: un arbore cu structura ''node(empty, x, node(empty, y, empty))'' este simetric cu unul de forma ''node(node(empty, z, empty), w, empty)''). | ||
| - | * [[https://ocw.cs.pub.ro/courses/_media/pp/24/laboratoare/tda/tda-sol.zip|Soluții]] | + | |
| ===== Referințe ===== | ===== Referințe ===== | ||
| * [[https://www.ic.unicamp.br/~meidanis/courses/mc336/problemas-lisp/L-99_Ninety-Nine_Lisp_Problems.html|Probleme de programare funcțională]] | * [[https://www.ic.unicamp.br/~meidanis/courses/mc336/problemas-lisp/L-99_Ninety-Nine_Lisp_Problems.html|Probleme de programare funcțională]] | ||