Загрузка данных
;; Задание 1. Макрос trace
(define-syntax trace
(syntax-rules ()
((_ expr)
(let ((v expr))
(display 'expr)
(display " => ")
(write v)
(newline)
v))))
(define (zip . xss)
(if (or (null? xss)
(null? (car xss)))
'()
(cons (map car xss)
(apply zip (map cdr xss)))))
(zip '(1 2 3) '(one two three))
(newline)
(define counter
(let ((n 0))
(lambda ()
(set! n (+ n 1))
n)))
(+ (trace (counter))
(trace (counter)))
(newline)
(newline)
;; Задание 2. Каркас модульного тестирования
(define-syntax test
(syntax-rules ()
((_ expr expected)
(list 'test
'expr
(lambda () expr)
(lambda () expected)))))
(define (run-test t)
(if (not (and (pair? t) (eq? (car t) 'test)))
(begin (display "<некорректный тест>") (newline) #f)
(let ((src (cadr t))
(get-act (caddr t))
(get-exp (cadddr t)))
(write src)
(and (procedure? get-act)
(let ((actual (get-act))
(expected (get-exp)))
(if (equal? actual expected)
(begin (display " ok") (newline) #t)
(begin
(display " FAIL") (newline)
(display " Expected: ") (write expected) (newline)
(display " Returned: ") (write actual) (newline)
#f)))))))
(define (run-tests tests)
(let loop ((ts tests) (ok? #t))
(if (null? ts)
ok?
(loop (cdr ts)
(and ok? (run-test (car ts)))))))
;; Задание 3. Деструктивное обращение
(define (reverse! seq . maybe-dest)
(let ((dest (if (null? maybe-dest) seq (car maybe-dest))))
(cond
((null? seq) '())
((pair? seq) (rev-list! seq dest))
((vector? seq) (rev-vector! seq dest))
((string? seq) (rev-string! seq dest))
(else (error "неизвестный тип последовательности")))))
(define (rev-list! src dst)
(if (eq? src dst)
(rev-list-in-place! src)
(rev-list-copy! src dst)))
(define (rev-list-in-place! lst)
(define (len l) (if (null? l) 0 (+ 1 (len (cdr l)))))
(let ((n (len lst)) (front lst) (k 0))
(define (walk cur)
(if (null? cur)
'done
(begin
(walk (cdr cur))
(if (< k (quotient n 2))
(begin
(let ((tmp (car front)))
(set-car! front (car cur))
(set-car! cur tmp))
(set! front (cdr front))
(set! k (+ k 1))))
'done)))
(walk lst)))
(define (rev-list-copy! src dst)
(let ((k 0))
(define (walk cur)
(if (null? cur)
'done
(begin
(walk (cdr cur))
(put-elem! dst k (car cur))
(set! k (+ k 1)))))
(walk src)))
(define (rev-vector! src dst)
(let ((n (vector-length src)))
(if (eq? src dst)
(do ((i 0 (+ i 1)) (j (- n 1) (- j 1))) ((>= i j))
(let ((tmp (vector-ref src i)))
(vector-set! src i (vector-ref src j))
(vector-set! src j tmp)))
(do ((i 0 (+ i 1))) ((= i n))
(put-elem! dst i (vector-ref src (- n 1 i)))))))
(define (rev-string! src dst)
(let ((n (string-length src)))
(if (eq? src dst)
(do ((i 0 (+ i 1)) (j (- n 1) (- j 1))) ((>= i j))
(let ((c (string-ref src i)))
(string-set! src i (string-ref src j))
(string-set! src j c)))
(do ((i 0 (+ i 1))) ((= i n))
(put-elem! dst i (string-ref src (- n 1 i)))))))
(define (put-elem! container i val)
(cond
((vector? container) (vector-set! container i val))
((string? container)
(if (char? val)
(string-set! container i val)
(error "в строку можно писать только символы")))
((pair? container)
(let loop ((c container) (k i))
(if (= k 0)
(set-car! c val)
(loop (cdr c) (- k 1)))))
(else (error "неподходящий приемник"))))
;; Задание 4. Разложение на множители
(define (exppt b e) (expt b e))
(define (length= l n)
(let loop ((x l) (k n))
(cond ((zero? k) (null? x))
((null? x) #f)
(else (loop (cdr x) (- k 1))))))
(define (binop? e op)
(and (pair? e) (eq? (car e) op) (length= e 3)))
(define (exppt? e)
(and (pair? e) (eq? (car e) 'exppt) (length= e 3)))
(define (ebase e) (cadr e))
(define (eexp e) (caddr e))
(define (part-exppt-k? part k)
(and (exppt? part) (= (eexp part) k)))
(define (mk op a b) (list op a b))
(define (fac-sq-diff a b)
(list '* (mk '- a b) (mk '+ a b)))
(define (fac-cube-diff a b)
(list '* (mk '- a b)
(list '+ (list 'exppt a 2) (mk '* a b) (list 'exppt b 2))))
(define (fac-cube-sum a b)
(list '* (mk '+ a b)
(list '+ (list 'exppt a 2)
(mk '- (list 'exppt b 2) (mk '* a b)))))
(define (factorize e)
(cond
((and (binop? e '-)
(part-exppt-k? (cadr e) 2)
(part-exppt-k? (caddr e) 2))
(fac-sq-diff (ebase (cadr e)) (ebase (caddr e))))
((and (binop? e '-)
(part-exppt-k? (cadr e) 3)
(part-exppt-k? (caddr e) 3))
(fac-cube-diff (ebase (cadr e)) (ebase (caddr e))))
((and (binop? e '+)
(part-exppt-k? (cadr e) 3)
(part-exppt-k? (caddr e) 3))
(fac-cube-sum (ebase (cadr e)) (ebase (caddr e))))
(else e)))
;;Тесты reverse!
(define rev-tests
(list
(test (let ((xs '(a b c d e))) (reverse! xs) xs) '(e d c b a))
(test (let ((ys (vector 1 2 3 4 5))) (reverse! ys) ys) #(5 4 3 2 1))
(test (let ((zs (string #\h #\e #\l #\l #\o))) (reverse! zs) zs) "olleh")
(test (let ((xs '())) (reverse! xs) xs) '())
(test (let ((xs '(9))) (reverse! xs) xs) '(9))
(test (let ((xs '(1 2 3 4))) (reverse! xs) xs) '(4 3 2 1))
(test (let ((xs '(a b c d e)) (ys '(0 0 0 0 0)))
(reverse! xs ys) ys)
'(e d c b a))
(test (let ((xs '(1 2 3)) (yv (vector 0 0 0)))
(reverse! xs yv) yv)
#(3 2 1))
(test (let ((zs (string #\a #\b #\c)) (ls (list #\z #\z #\z)))
(reverse! zs ls) ls)
'(#\c #\b #\a))
(test (let* ((as '(a b c)) (bs (append '(x y z) as)))
(set-car! as 1) (reverse! bs) (list bs as))
'((c b 1 z y x) (z y x)))
(test (let* ((as '(a b c)) (bs (append '(x y z) as)))
(set-car! as 1) (reverse! bs) (reverse! (cdr bs)) (list bs as))
'((c x y z 1 b) (z 1 b)))))
(display (run-tests rev-tests))
(newline)
;;Тесты factorize
(define fact-tests
(list
(test (factorize '(- (exppt x 2) (exppt y 2)))
'(* (- x y) (+ x y)))
(test (factorize '(- (exppt (+ first 1) 2) (exppt (- second 1) 2)))
'(* (- (+ first 1) (- second 1))
(+ (+ first 1) (- second 1))))
(test (factorize '(- (exppt a 3) (exppt b 3)))
'(* (- a b) (+ (exppt a 2) (* a b) (exppt b 2))))
(test (factorize '(+ (exppt a 3) (exppt b 3)))
'(* (+ a b) (+ (exppt a 2) (- (exppt b 2) (* a b)))))
(test (factorize '(- (exppt x 4) (exppt y 2)))
'(- (exppt x 4) (exppt y 2)))
(test (factorize '(+ x y)) '(+ x y))
(test (eval (list (list 'lambda '(x y)
(factorize '(- (exppt x 2) (exppt y 2))))
3 5)
(interaction-environment))
-16)
(test (eval (list (list 'lambda '(a b)
(factorize '(+ (exppt a 3) (exppt b 3))))
2 3)
(interaction-environment))
35)
(test (eval (list (list 'lambda '(a b)
(factorize '(- (exppt a 3) (exppt b 3))))
4 1)
(interaction-environment))
63)))
(display (run-tests fact-tests))
(newline)