; reverse vowels

(define (vowel? c) (member (char-downcase c) '(#\a #\e #\i #\o #\u)))

(define (reverse-vowels str)
  (let* ((cs (string->list str)) (vs (reverse (filter vowel? cs))))
    (let loop ((cs cs) (vs vs) (zs (list)))
      (cond ((null? cs) (list->string (reverse zs)))
            ((vowel? (car cs))
              (let ((f (if (char-upper-case? (car cs)) char-upcase char-downcase)))
                (loop (cdr cs) (cdr vs) (cons (f (car vs)) zs))))
            (else (loop (cdr cs) vs (cons (car cs) zs)))))))

(display (reverse-vowels "HELLO world")) (newline)
(display (reverse-vowels "Programming PRAXIS")) (newline)

(define (reverse-vowels str)
  (define (fix-case x y)
    (if (char-upper-case? x)
        (char-upcase y)
        (char-downcase y)))
  (let loop ((lo 0) (hi (- (string-length str) 1)))
    (cond ((< hi lo) str)
          ((and (vowel? (string-ref str lo))
                (vowel? (string-ref str hi)))
            (let ((temp (string-ref str lo)))
               (string-set! str lo
                 (fix-case temp (string-ref str hi)))
               (string-set! str hi
                 (fix-case (string-ref str hi) temp)))
            (loop (+ lo 1) (- hi 1)))
          ((not (vowel? (string-ref str lo))) (loop (+ lo 1) hi))
          ((not (vowel? (string-ref str hi))) (loop lo (- hi 1)))
          (else (loop (+ lo 1) (- hi 1))))))

(display (reverse-vowels "HELLO world")) (newline)
(display (reverse-vowels "Programming PRAXIS")) (newline)