#lang scheme
(define-struct tree (val) #:prefab)
(define-struct (leaf tree) () #:prefab)
(define-struct (node tree) (left right) #:prefab)
(define (half n)
(arithmetic-shift n -1))
(define (tree-ref/set s t i v)
(cond [(zero? i)
(values (tree-val t)
(cond [(leaf? t) (make-leaf v)]
[else
(make-node v (node-left t) (node-right t))]))]
[else
(let ((s* (half s)))
(if (<= i s*)
(let-values ([(t* v*) (tree-ref/set s* (node-left t) (- i 1) v)])
(values v* (make-node (tree-val t) t* (node-right t))))
(let-values ([(t* v*) (tree-ref/set s* (node-right t) (- i 1 s*) v)])
(values v* (make-node (tree-val t) (node-left t) t*)))))]))
(define (ra:list-ref/set ls i v)
(match ls
[(list) (error (object-name ra:list-ref/set) "index out of bounds: ~a" i)]
[(cons (cons s t) r)
(cond [(< i s)
(let-values ([(v* t*) (tree-ref/set s t i v)])
(values v* (cons (cons s t*) r)))]
[else
(let-values ([(v* r*) (ra:list-ref/set r (- i s) v)])
(values v* (cons (first ls) r*)))])]))
(define (ra:list-ref ls i)
(let-values ([(v* _) (ra:list-ref/set ls i '_)]) v*))
(define (ra:list-set ls i v)
(let-values ([(_ l*) (ra:list-ref/set ls i v)]) l*))
(define (ra:cons x ls)
(match ls
[(list-rest (cons s t1) (cons s t2) r)
(cons (cons (+ 1 s s) (make-node x t1 t2)) r)]
[else
(cons (cons 1 (make-leaf x)) ls)]))
(define (ra:first ls)
(match ls
[(list) (error (object-name ra:first) "expected non-empty list")]
[(cons (cons s (struct tree (x))) r) x]))
(define (ra:rest ls)
(match ls
[(list) (error (object-name ra:rest) "expected non-empty list")]
[(cons (cons s (struct leaf (x))) r) r]
[(cons (cons s (struct node (x t1 t2))) r)
(let ((s* (half s)))
(list* (cons s* t1) (cons s* t2) r))]))
(define ra:empty empty)
(define ra:empty? empty?)
(define (ra:cons? x)
(match x
[(cons (cons (? integer?) (? tree?)) r) true]
[else false]))
(define (ra:list? x)
(or (ra:empty? x)
(ra:cons? x)))
(define (ra:list . xs)
(foldr ra:cons ra:empty xs))
(define (ra:build-list n f)
(let loop ((i n) (a ra:empty))
(cond [(zero? i) a]
[else (loop (sub1 i)
(ra:cons (f (sub1 i)) a))])))
(define (tree-map f t)
(cond [(leaf? t) (make-leaf (f (tree-val t)))]
[(node? t) (make-node (f (tree-val t))
(tree-map f (node-left t))
(tree-map f (node-right t)))]))
(define (ra:map f ls)
(map (lambda (p) (cons (car p) (tree-map f (cdr p))))
ls))
(define (ra:foldl f b ls)
(cond [(ra:empty? ls) b]
[else (ra:foldl f (f (ra:first ls) b) (ra:rest ls))]))
(define (ra:foldr f b ls)
(cond [(ra:empty? ls) b]
[else (f (ra:first ls) (ra:foldr f b (ra:rest ls)))]))
(provide/contract
(rename ra:cons cons (-> any/c ra:list? ra:cons?))
(rename ra:empty empty ra:empty?)
(rename ra:list-ref list-ref (-> ra:cons? natural-number/c any))
(rename ra:list-set list-set (-> ra:cons? natural-number/c any/c ra:cons?))
(rename ra:cons? cons? (-> any/c boolean?))
(rename ra:empty? empty? (-> any/c boolean?))
(rename ra:list? list? (-> any/c boolean?))
(rename ra:first first (-> ra:cons? any))
(rename ra:rest rest (-> ra:cons? ra:list?))
(rename ra:map map (-> (-> any/c any) ra:list? ra:list?))
(rename ra:foldr foldr (-> (-> any/c any/c any) any/c ra:list? any))
(rename ra:foldl foldl (-> (-> any/c any/c any) any/c ra:list? any))
(rename ra:list list (->* () () #:rest (listof any/c) ra:list?))
(rename ra:list-ref/set list-ref/set
(-> ra:cons? natural-number/c any/c (values any/c ra:cons?)))
(rename ra:build-list build-list
(-> natural-number/c (-> natural-number/c any) ra:list?)))