#lang racket ; Mihnea Muraru & Andrei Olaru ;(display "----- Operatori pe fluxuri -----\n") ;; ne construim o abstractizare pentru ce mecanism de întârzieri folosim (define-syntax-rule (pack expr) ;(lambda () expr)) ; închideri (delay expr)) ; promisiuni (define unpack ;(λ (package) (package))) ; închideri force) ; promisiuni ; ===================================== (define-syntax-rule (stream-cons h t) ;; define-syntax-rule definește o construcție nestrictă, ;; deci apelul stream-cons nu va evalua h și t (cons h (pack t))) (define stream-car car) (define (stream-cdr s) (unpack (cdr s))) (define stream-nil '()) (define stream-null? null?) ; =============================== (define (stream-take s n) (cond ((zero? n) '()) ((stream-null? s) '()) (else (cons (stream-car s) (stream-take (stream-cdr s) (- n 1)))))) (define (stream-drop s n) (cond ((zero? n) s) ((stream-null? s) s) (else (stream-drop (stream-cdr s) (- n 1))))) (define (stream-map f s) (if (stream-null? s) s (stream-cons (f (stream-car s)) (stream-map f (stream-cdr s))))) (define (stream-filter f? s) (cond ((stream-null? s) s) ((f? (stream-car s)) (stream-cons (stream-car s) (stream-filter f? (stream-cdr s)))) (else (stream-filter f? (stream-cdr s))))) (define (stream-zip-with f s1 s2) (stream-cons (f (stream-car s1) (stream-car s2)) (stream-zip-with f (stream-cdr s1) (stream-cdr s2)))) (define (stream-append s1 s2) (if (stream-null? s1) s2 (stream-cons (stream-car s1) (stream-append (stream-cdr s1) s2)))) (define (stream-assoc k s) (cond ((stream-null? s) #f) ((equal? (car (stream-car s)) k) (stream-car s)) (else (stream-assoc k (stream-cdr s))))) (define (list->stream L) (if (null? L) stream-nil (stream-cons (car L) (list->stream (cdr L))))) ; =============================================== (display "----- Definiri de fluxuri -----\n") (display "ones:\n") ;(define ones (letrec ((ones (cons 1 ones))) ones)) ; eroare ;(define (ones) (cons 1 (ones))) ;ciclu infinit ;(define ones (cons 1 (λ () ones))) ; inchideri ;(define ones (cons 1 (delay ones))) ; promisiuni (define ones (stream-cons 1 ones)) (car ones) (cdr ones) (equal? ones (stream-cdr ones)) ; folosiți această definiție pentru a observa cum se construiesc elementele fluxului ;(define (naturalsFrom start) ; observați evaluarea la utilizarea promisiunilor ; (stream-cons start (naturalsFrom ; ca mecanism de întârziere a evaluării ; (and (display `(build ,(+ start 1))) (+ start 1))))) (define (naturalsFrom start) (stream-cons start (naturalsFrom (+ start 1)))) (define naturals (naturalsFrom 0)) (define naturals2 (stream-cons 0 (stream-zip-with + ones naturals2))) (display "naturals:\n") (stream-take naturals 0) (stream-take naturals 1) (stream-take naturals 5) (stream-take naturals 7) (stream-take naturals2 5) (define even-naturals (stream-filter even? naturals)) (display "even naturals: ") (stream-take even-naturals 5) (define even-naturals2 (stream-zip-with + naturals naturals)) (stream-take even-naturals 5) (define powers-of-2 ;; definiție recursivă (letrec ((build (λ (start) (stream-cons start (build (* start 2)))))) (build 1))) (define p-o-2 ;; variantă de definire implicită (stream-cons 1 (stream-zip-with + p-o-2 p-o-2))) (define p-o-2B ;; altă variantă (stream-cons 1 (stream-map ((curry *) 2) p-o-2))) (display "Powers of 2: ") (stream-take p-o-2 12) (define primes ;; primes (letrec ((sieve (λ (numbers) (let ((prime (stream-car numbers))) (stream-cons prime (sieve (stream-filter (λ (n) (not (zero? (remainder n prime)))) (stream-cdr numbers))) ))))) (sieve (naturalsFrom 2)))) (display "primes: ") (stream-take primes 10) (display "1000th prime: ") (stream-car (stream-drop primes 999)) ; =============================================== LAZY BFS (display "----- Căutare leneşă în spaţiul stărilor -----\n") ;(display "Găsirea primei stări goal\n") (define symbols '(a b c)) ;; alfabetul pentru palindroame (define expand-string ;; pe baza lui s, mai construiește o serie de șiruri, de lungime + 1 (λ (s) (map (λ (symb) (cons symb s)) symbols))) (define palindrome? (λ (s) (equal? s (reverse s)))) (define BFS-one ;; găsește prima soluție (λ (init expand goal?) (let search ((frontiera (list init))) ;; stări de explorat ;(display frontiera) (if (null? frontiera) '() ;; am terminat de explorat? (let ((state (car frontiera))) ;; stare curentă (if (goal? state) state ;; am găsit o stare scop (o soluție) (search (append (cdr frontiera) (expand state)))) ;; stările nou descoperite se adaugă la sfârșit ))) )) ;; primul palindrom de lungime 3: (define 3-palindrome? (λ (s) (and (equal? 3 (length s)) (palindrome? s)))) (BFS-one '() expand-string 3-palindrome?) (define BFS ;; găsește toate soluțiile (spațiul de căutare trebuie să fie finit) (λ (init expand goal?) (let search ((frontiera (list init))) ;; stări de explorat ;(display frontiera) (if (null? frontiera) '() ;; am terminat de explorat? (let* ((state (car frontiera)) ; stare curentă (other-solutions ;; rezultatul căutării recursive (search (append (cdr frontiera) (expand state))))) ;; stările nou descoperite se adaugă la sfârșit (if (goal? state) (cons state other-solutions) ;; am găsit o stare scop (o soluție) other-solutions) ))) )) (define 3-palindromes (BFS '() (compose ((curry filter) (λ (s) (<= (length s) 3))) expand-string) 3-palindrome?)) (display "palindroame <= 3: ") (displayln 3-palindromes) (define lazy-BFS ;; produce un flux de soluții, pe baza unui spațiu de căutare potențial infinit (λ (init expand goal?) (let search ((frontiera (list init))) ;; stări de explorat ;(display frontiera) (if (null? frontiera) stream-nil ;; am terminat de explorat? (let ((state (car frontiera))) ;; stare curentă (if (goal? state) (stream-cons state (search (append (cdr frontiera) (expand state)))) ;; la găsirea unei stări scop, restul căutării va fi lăsat ;; până când este necesară o nouă soluție (ceea ce va forța evaluarea lui cdr din ;; fluxul de stări, și deci evaluarea lui search (search (append (cdr frontiera) (expand state))) ))) ))) (define all-palindromes (lazy-BFS '() expand-string palindrome? )) (displayln "palindroamele de la 50 la 60:") (stream-take (stream-drop all-palindromes 50) 10)