; string re-ordering
(define (make-list n x)
(let loop ((n n) (xs '()))
(if (zero? n) xs
(loop (- n 1) (cons x xs)))))
(define (string-index c str)
(let loop ((ss (string->list str)) (k 0))
(cond ((null? ss) #f)
((char=? (car ss) c) k)
(else (loop (cdr ss) (+ k 1))))))
(define sort #f)
(define merge #f)
(let ()
(define dosort
(lambda (pred? ls n)
(if (= n 1)
(list (car ls))
(let ((i (quotient n 2)))
(domerge pred?
(dosort pred? ls i)
(dosort pred? (list-tail ls i) (- n i)))))))
(define domerge
(lambda (pred? l1 l2)
(cond
((null? l1) l2)
((null? l2) l1)
((pred? (car l2) (car l1))
(cons (car l2) (domerge pred? l1 (cdr l2))))
(else (cons (car l1) (domerge pred? (cdr l1) l2))))))
(set! sort
(lambda (pred? l)
(if (null? l) l (dosort pred? l (length l)))))
(set! merge
(lambda (pred? l1 l2)
(domerge pred? l1 l2))))
(define (index c str)
(let ((x (string-index c str)))
(if x x -1)))
(define (order1 t o)
(let loop ((ts (string->list t)) (ps (list)))
(if (pair? ts)
(loop (cdr ts) (cons (cons (index (car ts) o) (car ts)) ps))
(list->string
(map cdr (sort (lambda (a b) (< (car a) (car b))) ps))))))
(display (order1 "hello" "eloh")) (newline)
(display (order1 "help" "eloh")) (newline)
(define (build o buckets out)
(list->string (apply append (reverse out)
(map (lambda (c)
(make-list (vector-ref buckets (char->integer c)) c))
(string->list o)))))
(define (order2 t o)
(define c->i char->integer)
(let ((buckets (make-vector 256 #f)))
(do ((os (string->list o) (cdr os))) ((null? os))
(vector-set! buckets (c->i (car os)) 0))
(let loop ((ts (string->list t)) (out (list)))
(cond ((null? ts) (build o buckets out))
((vector-ref buckets (c->i (car ts)))
(vector-set! buckets (c->i (car ts))
(+ (vector-ref buckets (c->i (car ts))) 1))
(loop (cdr ts) out))
(else (loop (cdr ts) (cons (car ts) out)))))))
(display (order2 "hello" "eloh")) (newline)
(display (order2 "help" "eloh")) (newline)