#lang racket
(require (planet "main.rkt" ("samsergey" "rewrite.plt" 1 0))
rackunit)
(check-equal? ((/. 'a --> 'b
'b --> 'c
'c --> 'd) '(a b c d))
'(b c d d))
(check-equal? ((/. 'a --> 'b
'b --> 'c
'c --> 'a) '(a b c d))
'(b c a d))
(check-equal? ((/. 'a --> 'b
'b 1 --> 'c
'c 1 2 --> 'a) 'a)
'b)
(check-equal? ((/. 'a --> 'b
'b 1 --> 'c
'c 1 2 --> 'a) 'b 1)
'c)
(check-equal? ((/. 'a --> 'b
'b 1 --> 'c
'c 1 2 --> 'a) 'x 'y 'z 't)
'(x y z t))
(check-equal? ((//. 'a --> 'b
'b --> 'c
'c --> 'd) '(a b c d))
'(d d d d))
(check-equal? ((//. 'a -->. 'b 'b --> 'a
'c --> 'a) '(a b c d))
'(b b b d))
(define/. length
(cons _ t) --> (+ 1 (length t))
'() --> 0)
(define/. depth
(? list? x) --> (+ 1 (apply max (map depth x)))
_ --> 0)
(define fib
(replace
1 --> 0
2 --> 1
n --> (fib 0 1 n)
a b 3 --> (+ a b)
a b i --> (fib b (+ a b) (- i 1))))
(define/. palindrom?
(or '() (list _)) --> #t
(list x y ___ x) --> (palindrom? y))
(check-true (palindrom? '()))
(check-true (palindrom? '(a a)))
(check-true (palindrom? '(a b a)))
(check-equal? (palindrom? '(r e v o l v e r)) '(o l))
(define ln-expand
(replace-all-repeated
`(ln (,x __1 * ,y __1)) --> `((ln ,x) + (ln ,y))
`(ln (,x __1 / ,y __1)) --> `((ln ,x) - (ln ,y))
`(ln (,x ^ ,n)) --> `(,n * (ln ,x))
`(ln (,x)) --> `(ln ,x)))
(check-equal? (ln-expand '(ln(x * y))) '((ln x) + (ln y)))
(check-equal? (ln-expand '(ln(x / y))) '((ln x) - (ln y)))
(check-equal? (ln-expand '(ln(x * y / z))) '((ln x) + ((ln y) - (ln z))))
(check-equal? (ln-expand '(ln(x / (y * z)))) '((ln x) - ((ln y) + (ln z))))
(check-equal? (ln-expand '(ln(x ^ 2 / (y * z)))) '((2 * (ln x)) - ((ln y) + (ln z))))
(check-equal? (ln-expand '(ln(x + y))) '(ln (x + y)))
(check-equal? (ln-expand '(ln(8 * (x + y)))) '((ln 8) + (ln (x + y))))
(check-equal? (ln-expand '(ln(ln(x ^ n)))) '((ln n) + (ln(ln x))))
(define (split x l)
(foldl (/. y `(,l ,r) --> (? (< y x)) `(,(cons y l) ,r)
y `(,l ,r) --> `(,l ,(cons y r)))
'(() ()) l))
(define qsort
(replace-repeated
(cons x y) --> (values x (split x y))
x `(,l ,r) -->. (append (qsort l) `(,x) (qsort r))))
(check-equal? (qsort '()) '())
(check-equal? (qsort '(1 1)) '(1 1))
(check-equal? (qsort '(2 4 1 3 2 6 9 2)) '(1 2 2 2 3 4 6 9))
(define (bisection f)
(replace-repeated
a b --> (values a b (f a) (f b))
_ _ fa fb -->. (? (> (* fa fb) 0)) #f
a b _ _ -->. (? (almost-equal? a b)) a
a b fa fb -->. (let* ([c (/ (+ a b) 2.)]
[fc (f c)])
(or ((bisection f) a c fa fc)
((bisection f) c b fc fb)))))
(check almost-equal? ((bisection (λ(x)(- x 2))) 1 3) 2)
(check almost-equal? ((bisection (λ(x)(- (sin x) .4))) 0 2) (asin 0.4))