#lang racket ;; -------------------------------------------------- ;; Cursul al II-lea: ;; ;; Recursivitate pe stivă vs. recursivitate pe coadă ;; Exemple: ;; ;; - lungimea unei liste ;; * este nevoie de un parametru suplimentar ;; ;; - ridicarea la pătrat element cu element ;; * se produce o listă în ordine inversă ;; ;; - fibonacci ;; * recursivitatea pe coadă poate fi mai eficientă ;; și din punct de vedere temporal ;; -------------------------------------------------- ;; I. Lungimea unei liste (define length-stack ;; recursivitate pe stivă (λ (lst) (if (null? lst) 0 (add1 (length-stack (cdr lst)))) )) (define length-tail-helper ;; recursivitate pe coadă (λ (lst acc) ;; acumulatorul va conține suma elementelor parcurse deja (if (null? lst) acc ;; "în final" acumulatorul va reprezenta soluția (length-tail-helper (cdr lst) (add1 acc)) ))) (define length-tail (λ (lst) (length-tail-helper lst 0))) ;; -------------------------------------------------- ;; II. Ridicarea la pătrat element cu element (define squares-stack (λ (lst) (if (null? lst) '() (cons (* (car lst) (car lst)) (squares-stack (cdr lst))) ))) (define squares-tail-helper (λ (lst acc) (if (null? lst) acc ;; lista întoarsă va fi în ordine inversă (squares-tail-helper (cdr lst) (cons (* (car lst) (car lst)) acc)) ))) (define squares-tail (λ (lst) (squares-tail-helper lst '()))) (define squares-tail-rev-helper (λ (lst acc) (if (null? lst) (reverse acc) ;; Soluția 1: aplicarea reverse la final: O(n) (squares-tail-rev-helper (cdr lst) (cons (* (car lst) (car lst)) acc)) ))) (define squares-tail-rev (λ (lst) (squares-tail-rev-helper lst '()))) (define squares-tail-append-helper ;; Nu așa procedăm (bad practice) (λ (lst acc) (if (null? lst) acc ;; Soluția 2: aplicarea append la fiecare pas: O(n^2) (squares-tail-helper (cdr lst) (append `(,(* (car lst) (car lst))) acc)) ))) (define squares-tail-append (λ (lst) (squares-tail-append-helper lst '()))) ;; -------------------------------------------------- ;; III. Ridicarea la pătrat element cu element (define fibonacci-stack (λ (n) (if (< n 2) 1 (+ (fibonacci-stack (- n 1)) (fibonacci-stack (- n 2)))))) (define fibonacci-tail-helper (λ (n acc) (if (= n 0) (car acc) (fibonacci-tail-helper (- n 1) (cons (+ (car acc) (cdr acc)) (car acc))) ))) (define fibonacci-tail (λ (n) (fibonacci-tail-helper n '(1 . 0)))) ;; -- The end --