#lang racket ; ------------------Șabloane comune------------------ ; Ex: Rezolvarea Ex1->Ex3 ; și abstractizarea șablonului comun ; Șablon comun (define (sum i stop f next) (if (> i stop) 0 (+ (f i) (sum (next i) stop f next)))) ; Ex1: adunarea numerelor naturale de la a la b (define (sum-interval a b) (if (> a b) 0 (+ a (sum-interval (+ 1 a) b)))) ;(sum-interval 1 10) (define (ex1 a b) (sum a b identity add1)) ;(ex1 1 10) ; Ex2: e = 1/0! + 1/1! + 1/2! + 1/3! + ... ; de aproximat adunând până la 1/n! (define (factorial n) (define (fact-tail n acc) (if (zero? n) acc (fact-tail (sub1 n) (* n acc)))) (fact-tail n 1)) (define (sum-e n) (define (iter i) (if (> i n) 0 (+ (/ 1. (factorial i)) (iter (+ 1 i))))) (iter 0)) ;(sum-e 15) (define (ex2 n) (sum 0 n (compose (curry / 1.) factorial) add1)) ;(ex2 15) ; Ex3: π^2/8 = 1/1^2 + 1/3^2 + 1/5^2 + ... ; de aproximat adunând până la 1/(2n-1)^2 (define (sum-pi2/8 n) (define (iter i) (if (> i n) 0 (+ (/ 1. (sqr i)) (iter (+ 2 i))))) (iter 1)) ;(sqrt (* 8 (sum-pi2/8 711111))) (define (ex3 n) (sum 1 n (compose (curry / 1.) sqr) (curry + 2))) ;(sqrt (* 8 (ex3 711111))) ; ------------------Funcționale------------------ ; Ex: definiții echivalente folosind funcționale ;; Maximul elementelor dintr-o listă de numere (define (max-list L) (if (null? L) -inf.0 (max (car L) (max-list (cdr L))))) ;(max-list '(5 2 1 4 11 5 7 5 7 3)) (define (max-list-f L) (foldl max -inf.0 L)) ;(max-list-f '(5 2 1 4 11 5 7 5 7 3)) ;; Extragerea inițialelor dintr-o listă de nume (define (initials names) (if (null? names) '() (cons (substring (car names) 0 1) (initials (cdr names))))) ;(initials '("Winston" "Leonard" "Spencer" "Churchill")) (define (initials-f names) (map (λ (n) (substring n 0 1)) names)) ;(initials-f '("Winston" "Leonard" "Spencer" "Churchill")) ;; Extragerea pronumelor dintr-o listă de cuvinte (define (pronouns words) (cond ((null? words) '()) ((member (car words) '(I you he she we they)) (cons (car words) (pronouns (cdr words)))) (else (pronouns (cdr words))))) (define YS '(In the town where I was born Lived a man who sailed to sea And he told us of his life In the land of submarines So we sailed up to the sun 'Til we found a sea of green And we lived beneath the waves In our yellow submarine)) ;(pronouns YS) (define (pronouns-f words) (filter (λ (w) (member w '(I you he she we they))) words)) ;(pronouns-f YS) ;; Pătratele elementelor dintr-o listă de numere (define (squares L) (if (null? L) L (cons (sqr (car L)) (squares (cdr L))))) ;(squares '(1 2 3)) (define (squares-f L) (map sqr L)) ;(squares-f '(1 2 3)) ;; Numărul de elemente impare dintr-o listă (define (count-odds L) (if (null? L) 0 (+ (if (odd? (car L)) 1 0) (count-odds (cdr L))))) ;(count-odds '(1 2 3)) (define (count-odds-f L) (foldr (λ (x acc) (if (odd? x) (add1 acc) acc)) 0 L)) ;(count-odds-f '(1 2 3 5 5 6 7 9 11 13)) ;; Extragerea numerelor unei liste care sunt mai mici decât o valoare dată (define (smaller-than x L) (cond ((null? L) L) ((< (car L) x) (cons (car L) (smaller-than x (cdr L)))) (else (smaller-than x (cdr L))))) ;(smaller-than 3 '(1 2 3)) (define (smaller-than-f x L) (filter (curry > x) L)) ;(smaller-than-f 3 '(1 2 3 4 1 3 2)) ;; Concatenarea unei liste de liste (define (concat Ls) (if (null? Ls) '() (append (car Ls) (concat (cdr Ls))))) ;(concat '((1 2 3) (a b) (c 4 d 5 e) (6))) (define (concat-f Ls) (apply append Ls)) ;(concat-f '((1 2 3) (a b) (c 4 d 5 e) (6))) ; Ex: concat cu foldl / foldr ; + compararea eficienței (define (concat-l Ls) (foldl (λ (x acc) (append acc x)) '() Ls)) ;(concat-l '((1 2 3) (a b) (c 4 d 5 e) (6))) ;O(n^2) (define (concat-r Ls) (foldr append '() Ls)) ;(concat-r '((1 2 3) (a b) (c 4 d 5 e) (6))) ;O(n) ; --------- Implementare map/filter/foldl folosind foldr --------- (define (map* f L) (foldr (λ (x acc) (cons (f x) acc)) '() L)) ;(map* add1 '(1 2 3 4 5)) (define (filter* p L) (foldr (λ (x acc) (if (p x) (cons x acc) acc)) '() L)) ;(filter* odd? '(1 2 3 4 5)) ; "A thing of beauty" (define (foldl* f acc L) ((foldr (λ (x f-acc) (compose f-acc (curry f x))) identity L) acc)) ;(foldl* cons '() '(2 3 5 8 11)) ; Explicație foldl* ; - foldr parcurge lista dreapta->stânga și ; produce o compunere de funcții: ; (compose identity ; (curry f (last L)) ; .. ; (curry f (first L))) ; - calculul pentru foldl se declanșează ; la aplicarea rezultatului foldr ; (compunerea de funcții) ; pe acc inițial ; - (curry f x) este echivalent cu ; (λ (prev_acc) (f x prev_acc)) și ; este mecanismul de a obține noul ; acumulator din cel vechi ; ---------------------- TDA-uri --------------------- ; Ex: Numere complexe ; intern: coordonate carteziene: ; - parte reală ; - parte imaginară ;(define make-complex cons) ;(define get-real car) ;(define get-imag cdr) ;(define (get-magnitude C) ; (sqrt (+ (sqr (car C)) (sqr (cdr C))))) ; intern: coordonate polare: ; - modul ; - unghi față de origine (define (make-complex r i) (cons (sqrt (+ (sqr r) (sqr i))) (atan i r))) (define (get-real C) (* (car C) (cos (cdr C)))) (define (get-imag C) (* (car C) (sin (cdr C)))) (define get-magnitude car) (define (add-c C1 C2) (make-complex (+ (get-real C1) (get-real C2)) (+ (get-imag C1) (get-imag C2)))) (define res (add-c (make-complex 3 4) (make-complex 4 5))) ;(get-real res) ;7.000000000000001 în varianta polară ;(get-imag res) ;8.999999999999998 în varianta polară ; Obs: abstractizarea nu elimină limitările de reprezentare ; (ex: precizia numerelor reale) ; coordonate carteziene folosind stucturi (define-struct complex-number (real imag) #:transparent) (define (add-c-n C1 C2) (make-complex-number (+ (complex-number-real C1) (complex-number-real C2)) (+ (complex-number-imag C1) (complex-number-imag C2)))) ;(add-c-n (make-complex-number 3 4) (make-complex-number 4 5)) ; Ex: Arbori binari de căutare ;Constructori ; empty-bst : -> BST ; make-bst : BST x Elem x BST -> BST ;(define empty-bst ;(define make-bst ;Operatori ; left : BST -> BST ; right : BST -> BST ; key : BST -> Elem ; bst-empty? : BST -> Bool ; insert-bst : Elem x BST -> BST ; list->bst : List -> BST ;(define left ;(define right ;(define key ;(define bst-empty? ;(define (insert-bst x bst) ;(define (list->bst L) ;(list->bst '(3 6 1 2 4 8)) ; bst folosind structuri ; - constructorii, selectorii, predicatele de tip ; se creează automat ; make-bst-empty creează arborele vid (define-struct bst-empty () #:transparent) ; make-bst-node este constructorul intern (define-struct bst-node (left key right) #:transparent) (define (insert-bst x bst) (cond ((bst-empty? bst) (make-bst-node (make-bst-empty) x (make-bst-empty))) ((< x (bst-node-key bst)) (make-bst-node (insert-bst x (bst-node-left bst)) (bst-node-key bst) (bst-node-right bst))) (else (make-bst-node (bst-node-left bst) (bst-node-key bst) (insert-bst x (bst-node-right bst)))))) (define (list->bst L) (foldl insert-bst (make-bst-empty) L)) ;(list->bst '(3 6 1 2 4 8))