(define list-ref
  (lambda (ls n)
    (if (= n 0)
	(car ls)
	(list-ref (cdr ls) (sub1 n)))))

;; inefficient
(define sublist
  (lambda (ls m n)
    (if (>= m n)
	()
	(cons (list-ref ls m)
	      (sublist ls (add1 m) n)))))

;; better
(define sublist
  (lambda (ls m n)
    (letrec 
      ((tail
	(lambda (ls m)
	  (if (= m 0)
	      ls
	      (tail (cdr ls) (sub1 m)))))
       (head
	(lambda (ls n)
	  (if (= n 0)
	      ()
	      (cons (car ls) (head (cdr ls) (sub1 n)))))))
      (head (tail ls m) (- n m)))))

(define merge
  (lambda (ls1 ls2)
    (cond ((null? ls1) ls2)
	  ((null? ls2) ls1)
	  ((< (car ls1) (car ls2))
	   (cons (car ls1)
		 (merge (cdr ls1) ls2)))
	  (else
	   (cons (car ls2)
		 (merge ls1 (cdr ls2)))))))

(define mergesort
  (lambda (ls)
    (let ((len (length ls)))
      (if (<= len 1)
        ls
        (let ((mid (floor (/ len 2))))
	  (merge (mergesort (sublist ls 0 mid))
		 (mergesort (sublist ls mid len)))))))))

(define list?
  (lambda (s)
    (cond ((null? s) #t)
	  ((pair? s) 
	   (list? (cdr s)))
	  (else #f))))

(define append
  (lambda (ls1 ls2)
    (if (null? ls1)
	ls2
	(cons (car ls1)
	      (append (cdr ls1) ls2)))))

(define reverse
  (lambda (ls)
    (if (null? ls)
	()
	(append (reverse (cdr ls))
		(list (car ls))))))

;; tail-recursive reverse
(define reverse
  (lambda (ls)
    (letrec 
      ((loop
	(lambda (ls acc)
	  (if (null? ls)
	      acc
	      (loop (cdr ls) (cons (car ls) acc))))))
      (loop ls ()))))


(define append
  (lambda (ls1 ls2)
    (letrec 
      ((loop
	(lambda (ls acc)
	  (if (null? ls)
	      acc
	      (loop (cdr ls) (cons (car ls) acc))))))
      (loop (reverse ls1) ls2)))) ;; hmmmm.

;; tail-recursive append
(define append
  (lambda (ls1 ls2)
    (letrec 
      ((loop
	(lambda (ls acc)
	  (if (null? ls)
	      acc
	      (loop (cdr ls) (cons (car ls) acc))))))
      (loop (loop ls1 ()) ls2))))