fork download
  1. ; next to last item in a list
  2.  
  3. (define-syntax assert
  4. (syntax-rules ()
  5. ((assert expr result)
  6. (if (not (equal? expr result))
  7. (for-each display `(
  8. #\newline "failed assertion:" #\newline
  9. expr #\newline "expected: " ,result
  10. #\newline "returned: " ,expr #\newline))))))
  11.  
  12. (define (range . args)
  13. (case (length args)
  14. ((1) (range 0 (car args) (if (negative? (car args)) -1 1)))
  15. ((2) (range (car args) (cadr args) (if (< (car args) (cadr args)) 1 -1)))
  16. ((3) (let ((le? (if (negative? (caddr args)) >= <=)))
  17. (let loop ((x(car args)) (xs '()))
  18. (if (le? (cadr args) x)
  19. (reverse xs)
  20. (loop (+ x (caddr args)) (cons x xs))))))
  21. (else (error 'range "unrecognized arguments"))))
  22.  
  23. (define (next-to-last xs)
  24. (cond ((or (null? xs) (null? (cdr xs))) #f)
  25. ((null? (cddr xs)) (car xs))
  26. (else (next-to-last (cdr xs)))))
  27.  
  28. (define (test-next-to-last)
  29. (assert (next-to-last '()) #f)
  30. (assert (next-to-last '(1)) #f)
  31. (assert (next-to-last '(1 2)) 1)
  32. (assert (next-to-last '(1 2 3)) 2)
  33. (assert (next-to-last '(1 2 3 4)) 3)
  34. (assert (next-to-last '(1 2 3 4 5)) 4))
  35.  
  36. (test-next-to-last)
  37.  
  38. (define (nth-to-last n xs)
  39. (if (not (positive? n)) #f
  40. (let loop ((n n) (leading xs))
  41. (if (null? leading) #f
  42. (if (< 1 n) (loop (- n 1) (cdr leading))
  43. (let loop ((trailing xs) (leading (cdr leading)))
  44. (if (null? leading) (car trailing)
  45. (loop (cdr trailing) (cdr leading)))))))))
  46.  
  47. (define (test-nth-to-last)
  48. (assert (nth-to-last 0 '()) #f)
  49. (assert (nth-to-last 0 '(1)) #f)
  50. (do ((n 1 (+ n 1))) ((= n 7))
  51. (do ((x 1 (+ x 1))) ((= x 7))
  52. (let ((r (if (< x n) #f (- x n -1))))
  53. (assert (nth-to-last n (range 1 (+ x 1))) r)))))
  54.  
  55. (test-nth-to-last)
Success #stdin #stdout 0.01s 7272KB
stdin
Standard input is empty
stdout