; next identical popcount, revisited
(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 (next-perm lt? zs)
(if (null? zs) zs
(let next ((xlist (list (car zs))) (ys (cdr zs)))
(cond ((null? ys) (reverse zs))
((not (lt? (car ys) (car xlist)))
(next (cons (car ys) xlist) (cdr ys)))
(else
(letrec ((swap
(lambda (xs)
(cond ((null? (cdr xs))
(cons (car ys) (cons (car xs) (cdr ys))))
((lt? (car ys) (cadr xs))
(cons (car xs) (swap (cdr xs))))
(else (append (cons (car ys) (cons (cadr xs) (cddr xs)))
(cons (car xs) (cdr ys))))))))
(swap xlist)))))))
(define (next n)
(undigits (reverse (next-perm < (reverse (cons 0 (digits n 2))))) 2))
(display (next 15)) (newline)
(display (next 23)) (newline)
(display (next (expt 2 30))) (newline)