; reversing digits

(define (digits n . args)
  (let ((b (if (null? args) 10 (car args))))
    (let loop ((n n) (d '()))
      (if (zero? n) d
          (loop (quotient n b)
                (cons (modulo n b) d))))))

(define (undigits ds . args)
  (let ((b (if (null? args) 10 (car args))))
    (let loop ((ds ds) (n 0))
      (if (null? ds) n
          (loop (cdr ds) (+ (* n b) (car ds)))))))

(define (timing rev)
  (time
    (let ((count 0))
      (do ((n 1 (+ n 1)))
          ((< 50000 n) count)
        (when (= n (rev n))
          (set! count (+ count 1)))))))

(define (rev1 n) ; iterative 1731
  (let loop ((n n) (z 0))
    (if (zero? n) z
      (loop (quotient n 10)
            (+ (* z 10) (modulo n 10))))))

(define (rev2 n) ; recursive 1747
  (define (rev n r)
    (if (zero? n) r
      (rev (quotient n 10)
           (+ (* r 10) (modulo n 10)))))
  (rev n 0))

(define (rev3 n) ; numeric split 2918
  (undigits (reverse (digits n))))

(define (rev4 n) ; string split 2527
  (string->number
    (list->string
      (reverse
        (string->list
          (number->string n))))))

(display (timing rev1)) (newline)
(display (timing rev2)) (newline)
(display (timing rev3)) (newline)
(display (timing rev4)) (newline)