; phone numbers
(define (range . args)
(case (length args)
((1) (range 0 (car args) (if (negative? (car args)) -1 1)))
((2) (range (car args) (cadr args) (if (< (car args) (cadr args)) 1 -1)))
((3) (let ((le? (if (negative? (caddr args)) >= <=)))
(let loop ((x(car args)) (xs '()))
(if (le? (cadr args) x)
(reverse xs)
(loop (+ x (caddr args)) (cons x xs))))))
(else (error 'range "unrecognized arguments"))))
(define (mappend f . xss) (apply append (apply map f xss)))
(define (list-minus xs ys)
(filter (lambda (y) (not (member y ys))) xs))
(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 (phone-numbers len skips)
(let loop ((len (- len 1))
(nums (map list (list-minus (range 1 10) skips))))
(if (zero? len)
(map undigits (map reverse nums))
(loop (- len 1)
(mappend (lambda (xs)
(filter (lambda (xs)
(not (= (car xs) (cadr xs))))
(map (lambda (x)
(cons x xs))
(list-minus (range 10) (cons 4 skips)))))
nums)))))
(display (phone-numbers 3 '(1 3 5 7 9))) (newline)