; tri-partitions
(define (f xs)
(let loop ((xs xs) (zeroes (list)) (ones (list)) (twos (list)))
; (display "loop1 ") (display xs) (display " ") (display zeroes)
; (display " ") (display ones) (display " ") (display twos) (newline)
(if (pair? xs)
(cond ((= (modulo (car xs) 3) 0)
(loop (cdr xs) (cons (car xs) zeroes) ones twos))
((= (modulo (car xs) 3) 1)
(loop (cdr xs) zeroes (cons (car xs) ones) twos))
(else (loop (cdr xs) zeroes ones (cons (car xs) twos))))
(if (and (null? zeroes) (pair? ones) (pair? twos)) #f ; no zero separator
(if (null? zeroes) (append ones twos)
(let loop ((saved (car zeroes)) (zeroes (cdr zeroes))
(ones ones) (twos twos) (zs (list)))
; (display "loop2 ") (display saved) (display " ")
; (display zeroes) (display " ") (display ones) (display " ")
; (display twos) (display " ") (display zs) (newline)
(cond ((and (null? zeroes) (null? ones) (null? twos))
(if saved (cons saved zs) zs))
((and (pair? zeroes) (pair? ones))
(loop saved (cdr zeroes) (cdr ones) twos
(cons (car ones) (cons (car zeroes) zs))))
((pair? ones)
(loop saved zeroes (cdr ones) twos (cons (car ones) zs)))
(saved (loop #f zeroes ones twos (cons saved zs)))
((and (pair? twos) (pair? zeroes))
(loop saved (cdr zeroes) ones (cdr twos)
(cons (car zeroes) (cons (car twos) zs))))
((pair? twos)
(loop saved zeroes ones (cdr twos) (cons (car twos) zs)))
(else #f)))))))) ; leftover zeroes
(display (f '(0 0 0))) (newline)
(display (f '(0 0 1))) (newline)
(display (f '(0 0 2))) (newline)
(display (f '(0 1 1))) (newline)
(display (f '(0 2 2))) (newline)
(display (f '(1 1 1))) (newline)
(display (f '(2 2 2))) (newline)
(display (f '(1 1 2))) (newline)
(display (f '(0 1 2))) (newline)
(define xs '(2 67 65 71 86 83 12 17 9 30 42 61 33 68 57 30 74 42 41 51))
(display (f xs)) (newline)
(display (map (lambda (x) (modulo x 3)) (f xs))) (newline)