这次回顾HW1 Extra Practice Problems,主要是Racket基本语法的补充练习。

课程主页:

https://www.coursera.org/learn/programming-languages-part-b/home

B站搬运:

https://www.bilibili.com/video/BV1tZ4y1D7

习题内容:

https://www.coursera.org/learn/programming-languages-part-b/supplement/xf752/extra-practice-problems

参考资料:

https://www.coursera.org/learn/programming-languages-part-b/discussions/weeks/1/threads/TSM3qblPR9SjN6m5TzfUxg

代码

#lang racket

(provide (all-defined-out))

; 1
(define (palindromic arr)
    (letrec ([l (length arr)]
          [f (lambda (i)
                (if (= i l)
                    null
                    (cons (+ (list-ref arr i) (list-ref arr (- (- l 1) i))) (f (+ i 1)))))])
        (f 0)))

; 2
(define fibonacci
  (letrec ([f (lambda (a b) (cons a (lambda () (f b (+ a b)))))])
    (lambda () (f 0 1))))

; 3
(define (stream-until f s)
  (define (loop f s last)
    (let ([s1 (s)])
      (if (f (car s1))
        (loop f (cdr s1) (car s1))
        last)))
  (loop f s 0))

; 4
(define (stream-map f s)
  (letrec ([s1 (s)]
           [g (lambda () (cons (f (car s1)) (stream-map f (cdr s1))))])
    g))

; 5
(define (stream-zip s1 s2)
  (letrec ([s1a (s1)]
           [s2a (s2)]
           [g (lambda () (cons (cons (car s1a) (car s2a)) (stream-zip (cdr s1a) (cdr s2a))))])
    g))

; 7
(define (interleave streams)
  (letrec ([l (length streams)]
           [f (lambda (streams i) 
                (letrec ([stream (list-ref streams i)]
                         [x (stream)])
                  (begin
                    (cons (car x) (lambda () (f (list-set streams i (cdr x)) (remainder (+ i 1) l)))))))])
    (lambda () (f streams 0))))

; 8
(define (pack n s)
  (letrec ([f (lambda (i s)
                (if (= i n)
                  (cons null s)
                  (let ([p (f (+ i 1) (cdr (s)))]
                        [s1 (s)])
                    (cons (cons (car s1) (car p)) (cdr p)))))]
           [g (lambda (s)
                (let ([p (f 0 s)])
                  (cons (car p) (lambda () (g (cdr p))))))])
    (lambda () (g s))))

; 9
(define (sqrt-stream n)
  (letrec ([f (lambda (x) (/ (+ x (/ n x)) 2))]
           [g (lambda (x) 
                (let ([x1 (f x)])
                  (cons x1 (lambda () (g x1)))))])
    (lambda () (g n))))

; 10
(define (approx-sqrt n e)
  (letrec ([stream (sqrt-stream n)]
           [f (lambda (s)
                (letrec ([s1 (s)]
                         [x (car s1)]
                         [x2 (* x x)])
                  (if (and (< (- n e) x2) (< x2 (+ n e)))
                    x
                    (f (cdr s1)))))])
    (f stream)))

(define (judge10 x n e)
  (let ([x2 (* x x)])
    (and (< (- n e) x2) (< x2 (+ n e)))))

; 11
(define-syntax perform
  (syntax-rules (if unless)
    [(perform e1 if e2)
     (let ([a e2])
       (if a
         e1
         a))]
    [(perform e1 unless e2)
     (let ([a e2])
       (if (not a)
        e1
        a))]))

第6问,reverse需要最后一个元素,但是stream无法求出最后一个元素。

测试

; https://www.coursera.org/learn/programming-languages-part-b/discussions/weeks/1/threads/TSM3qblPR9SjN6m5TzfUxg
#lang racket

(require rackunit)
(require "hw4_extra.rkt")
(require "01_homework-4-auto-grader_hw4.rkt")

; predefined streams from lecture (also use #4 stream-for-n-steps from HW4 for tests and to see values of streams)
(define ones (lambda () (cons 1 ones)))
(define nats
  (letrec ([f (lambda (x) (cons x (lambda () (f (+ x 1)))))])
    (lambda () (f 1))))
(define powers-of-two
  (letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
    (lambda () (f 2))))
(define a 2)
(define evens
  (letrec ([f (lambda (x)  (cons x (lambda () (f (+ x 2)))))])
    (lambda() (f 2))))
(define ahh ; (a, aa, aaa, etc) 
  (letrec ([f (lambda (s)
                (cons (string-append s "a") (lambda () (f (string-append s "a")))))])
    (lambda() (f ""))))

; TESTS
(define tests
  (test-suite
   "Sample tests for Extra Problems 4"
   ; #1
   (check-equal? (palindromic (list 1 2 4 8)) (list 9 6 6 9) "Palindromic test 1")
   (check-equal? (palindromic (list 1 2 3 4 5)) (list 6 6 6 6 6) "Palindromic test 2")
   ; #2
   (check-equal? (car (fibonacci)) 0 "Fibonacci test 1")
   (check-equal? (car ((cdr (fibonacci)))) 1 "Fibonacci test 2")
   (check-equal? (car ((cdr ((cdr (fibonacci)))))) 1 "Fibonacci test 3")
   (check-equal? (car ((cdr ((cdr ((cdr (fibonacci)))))))) 2 "Fibonacci test 4")
   (check-equal? (car ((cdr ((cdr ((cdr ((cdr (fibonacci)))))))))) 3 "Fibonacci test 5")
   (check-equal? (car ((cdr((cdr ((cdr ((cdr ((cdr (fibonacci)))))))))))) 5 "Fibonacci test 6")

   ; #3 - counts number of items in stream until f return false
   (check-equal? (stream-until (lambda(x) (<= x 100)) nats) 100 "Stream until test 1")
   (check-equal? (stream-until (lambda(x) (not (equal? x 32))) nats) 31 "Stream until test 2")
   (check-equal? (stream-until (lambda(x) (< x 100)) evens) 98 "Stream until test 3")
   (check-equal? (stream-until (lambda(x) (not (equal? x 32))) powers-of-two) 16 "Stream until test 4")
   (check-equal?  (stream-until (lambda (x) (< x 10)) fibonacci) 8) 
  
   ; #4
   (check-equal? (car ((stream-map (lambda(x) (- x)) evens))) -2 "Stream map test 1") ; f makes numbers negative
   (check-equal? (car ((cdr ((stream-map (lambda(x) (- x)) evens))))) -4 "Stream map test 2")
   (check-equal? (car ((cdr ((stream-map (lambda(x) (* x x)) evens))))) 16 "Stream map test 3") ; f squares numbers
   (check-equal? (car ((cdr ((stream-map (lambda(s) (string-append s "b")) ahh))))) "aab" "Stream map test 4")
   ; #5
   (check-equal? (car ((cdr ((stream-zip nats powers-of-two))))) (cons 2 4) "Stream zip test 1")
   (check-equal? (car ((cdr((cdr ((cdr ((cdr ((cdr ((stream-zip ones nats))))))))))))) (cons 1 6) "Stream zip test 2")
   (check-equal? (car ((cdr((cdr ((cdr ((cdr ((cdr ((stream-zip ones powers-of-two))))))))))))) (cons 1 64) "Stream zip test 3")
   ; #6 No code required. HINT: What is the last element of a stream?
   ; NOTE: Remaining tests make use of hw4#4 so make sure that is in the same file
   ; #7
   (check-equal? (stream-for-n-steps (interleave (list ones nats ahh)) 6) '(1 1 "a" 1 2 "aa") "Interleave test 1")
   (check-equal? (stream-for-n-steps (interleave (list ones nats ahh powers-of-two)) 13) '(1 1 "a" 2 1 2 "aa" 4 1 3 "aaa" 8 1) "Interleave test 2")
   ; #8
   (check-equal? (car ((cdr ((pack 3 nats))))) '(4 5 6) "Pack test 1")
   (check-equal? (stream-for-n-steps (pack 3 nats) 5) '((1 2 3) (4 5 6) (7 8 9) (10 11 12) (13 14 15)) "Pack test 2")
   (check-equal? (stream-for-n-steps (pack 2 nats) 15) '((1 2) (3 4) (5 6) (7 8) (9 10) (11 12) (13 14) (15 16) (17 18) (19 20) (21 22) (23 24) (25 26) (27 28) (29 30)) "Pack test 3")
   (check-equal? (stream-for-n-steps (pack 5 ones) 5) '((1 1 1 1 1) (1 1 1 1 1) (1 1 1 1 1) (1 1 1 1 1) (1 1 1 1 1)) "Pack test 4")
  ;  ; SKIPPED 9,10
   ; #9
   (check-equal? (stream-for-n-steps (sqrt-stream 9) 3) '(5 17/5 257/85) "Sqrt-stream test 1")
   ; #10
   (check-equal? (judge10 (approx-sqrt 9 0.01) 9 0.01) #t "Approx-sqrt test 1")
   (check-equal? (judge10 (approx-sqrt 100 0.00001) 100 0.01) #t "Approx-sqrt test 2")
   ; #11
   (check-equal? (perform (+ 1 1) if (= 3 3)) 2 "Perform test 1")
   (check-equal? (perform (+ 1 1) if (= 3 4)) #f "Perform test 2")
   (check-equal? (perform (+ 1 1) unless (= 3 4)) 2 "Perform test 3")
   (check-equal? (perform (+ 1 1) unless (= 3 3)) #t "Perform test 4")
  ))

(require rackunit/text-ui)
;; runs the test
(run-tests tests)

测试结果:

33 success(es) 0 failure(s) 0 error(s) 33 test(s) run