#lang racket (define stream-take->list (compose stream->list stream-take)) (define ones (stream-cons 1 ones)) ; =============================================== LAZY BFS ;(displayln "----- Căutare leneşă în spaţiul stărilor -----") (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 (expand-max n) ; apelează expand dar doar pentru șiruri de lungime maxim n (λ (s) (if (<= (length s) n) (expand-string s) '() ))) (define palindrome? (λ (s) (equal? s (reverse s)))) (define (n-palindrome? n) (λ (s) (and (equal? n (length s)) (palindrome? s)))) ; curry ;; găsește prima soluție și o întoarce (define (bfs-one siruri solutie?) (let* ((first (car siruri)) (sol? (solutie? first)) ) (if sol? first ;; am găsit o soluție (bfs-one (append (cdr siruri) (expand-string first)) solutie?) )) ) ;; primul palindrom de lungime 3: (bfs-one '(()) (n-palindrome? 3)) ;; găsește toate soluțiile (spațiul de căutare trebuie să fie finit) (define (bfs siruri expand solutie?) (if (null? siruri) '() ;; am terminat de explorat? (let* ((first (car siruri)) ; șir curent (sol? (solutie? first)) ) (if sol? (cons first ;; am găsit o soluție (bfs (append ;; șirurile nou construite se adaugă la sfârșit (cdr siruri) (expand first)) expand solutie?)) (bfs (append (cdr siruri) (expand first)) expand solutie?) )) )) (bfs '(()) (expand-max 4) (n-palindrome? 3)) ;; produce un flux de soluții, pe baza unui spațiu de căutare potențial infinit (define (bfs-lazy siruri expand solutie?) (if (null? siruri) '() (let* ((first (car siruri)) (sol? (solutie? first)) ) (if sol? (stream-cons first ;; singura modificare ;; la găsirea unei soluții, 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 bfs-lazy) (bfs-lazy (append (cdr siruri) (expand first)) expand solutie?)) ;; dacă first nu este soluție, continuăm căutarea pentru a putea livra o soluție (bfs-lazy (append (cdr siruri) (expand first)) expand solutie?) )) )) (stream-take->list (bfs-lazy '(()) expand-string (n-palindrome? 3)) 9) (stream-take->list (bfs-lazy '(()) expand-string palindrome?) 20) (displayln "==== primes: ") (define naturals (stream-cons 0 (stream-map add1 naturals))) (stream-take->list naturals 10) (define nat-2 (stream-tail naturals 2)) (stream-take->list nat-2 10) ; numere care nu sunt divizibile cu 2 (stream-take->list (stream-filter (λ (x) (not (zero? (remainder x 2)))) nat-2) 20) (define primes (let build ((xs nat-2)) (let ((p (stream-first xs))) (stream-cons p (build (stream-filter (λ (x) (not (zero? (remainder x p)))) xs))))) ) (stream-take->list primes 20) (displayln "==== observați diferența: ") (define (stream-zip-with-v f s1 s2) (stream-cons (begin (printf "~v+~v\n" (stream-first s1) (stream-first s2)) (f (stream-first s1) (stream-first s2))) (stream-zip-with-v f (stream-rest s1) (stream-rest s2)))) (define (partial-sums s) (stream-cons 0 (stream-zip-with-v + s ; apelul recursiv face să se construiască *un nou flux* (partial-sums s)))) (stream-take->list (partial-sums naturals) 5) (define (partial-sums-2 s) (letrec ((flux ; construcția se face chiar pe baza fluxului (stream-cons 0 (stream-zip-with-v + s flux) ))) flux)) (stream-take->list (partial-sums-2 naturals) 5)