Reverse Vowels

June 4, 2019

Now that school is finished for the year, I’m catching up on the homework questions that people have sent me over the last several months. This one is fun:

Given a string, write it with the vowels reversed, maintaining the original capitalization of the vowels. For instance, “HELLO world” becomes “HOLLO werld” and “Programming PRAXIS” becomes “Prigramming PRAXOS” (I kinda like that one).

Your task is to write a program that returns an input string with vowels in reverse order, respecting the original capitalization. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

10 Responses to “Reverse Vowels”

  1. chaw said

    I decided to use a functional style instead of the perhaps more
    obvious in-place replacement of characters in an array. My program
    (written without peeking at the solution) ended up being almost the
    same as the first one by programmingpraxis, except for the slight
    optimization of avoiding a couple of reverses. Here it is for
    completeness sake.

    (import (scheme base)
            (scheme write)
            (scheme char))
    
    ;; Equivalent to (reverse (filter pred lst)) but avoids extra reversing.
    (define (reverse-filter pred lst)
      (let loop ((lst lst)
                 (r '()))
        (if (null? lst)
            r
            (loop (cdr lst)
                  (if (pred (car lst))
                      (cons (car lst)
                            r)
                      r)))))
    
    (define vowel?
      (let ((vs (string->list "AaEeIiOoUu")))
        (lambda (c)
          (memq c vs))))
    
    ;; Replace the i'th vowel in str (counting from the left) with the
    ;; i'th vowel counting from the right (for all valid i), preserving
    ;; the case of the original vowel.
    (define (reverse-vowels str)
      (let ((cs (string->list str)))
        (let loop ((cs cs)
                   (rv (reverse-filter vowel? cs))
                   (r '()))
          (if (null? cs)
              (list->string (reverse r))
              (if (vowel? (car cs))
                  (loop (cdr cs)
                        (cdr rv)
                        (cons ((if (char-upper-case? (car cs))
                                   char-upcase
                                   char-downcase)
                               (car rv))
                              r))
                  (loop (cdr cs)
                        rv
                        (cons (car cs)
                              r)))))))
    
    (write (map reverse-vowels '("Hello, World!" "Programming PRAXIS")))
    (newline)
    
    ("Hollo, Werld!" "Prigramming PRAXOS")
    

  2. Steve said

    Mumps version

    
    Code:  This is written in the form of variables which contain code and are executed.
                Z is the driver variable, which executes the other variables
                Z2 gets the string and defines the vowels
                Z3 scans the string for vowels and places them in a stack
                Z4 scans the string for vowels and replaces them with the vowels from the stack
                Z5 prints the new string
    
    Z="X Z2 X:STR]"" Z3,Z4,Z5"
    
    Z2="R !,"STRING: ",STR S VWLS="AEIOUY""
    
    Z3="K V F I=1:1:$L(STR) S LTR=$E(STR,I) I VWLS[LTR S V($I(V,-1))=LTR"
    
    Z4="S V="" F I=1:1:$L(STR) S LTR=$E(STR,I) I VWLS[LTR S V=$O(V(V)),VOW=V(V) K V(V) S $E(STR,I)=VOW"
    
    Z5="W !,STR"
    
    ---
    
    Run: 
    
    DEVESS>X Z
    
    STRING: HELLO, WORLD!
    
    HOLLO, WERLD!
    
    DEVESS>X Z
    
    STRING: PROGRAMMING PRAXIS
    
    PRIGRAMMING PRAXOS
    
    
  3. Smith said
    s = "HELLO world"
    ns = list(s)
    vowels = 'aeiouAEIOU'
    
    first, last = 0, len(s)-1
    while first <= last:
        while (s[first] not in vowels):
            first += 1
            if first == last: break
        while (s[last] not in vowels):
            last -= 1
            if first == last: break
    
        ns[last] = s[first].upper() if ns[last].isupper() else s[first].lower()
        ns[first] = s[last].upper() if ns[first].isupper() else s[last].lower()
    
        first += 1
        last -= 1
    
    print(''.join(ns))
    # HOLLO werld
    
  4. Globules said

    A Haskell version.

    import Data.Bool (bool)
    import Data.Char (isLower, toLower, toUpper)
    
    -- Reverse the order of vowels in a string, maintaining the case of the original
    -- letter.
    slewov :: String -> String
    slewov = revsub isVowel updCase
      where isVowel c = c `elem` "aeiouAEIOU"
            updCase x = bool toUpper toLower (isLower x)
    
    revsub :: (a -> Bool) -> (a -> a -> a) -> [a] -> [a]
    revsub prd upd xs = subst prd upd xs (reverse $ filter prd xs)
    
    subst :: (a -> Bool) -> (a -> a -> a) -> [a] -> [a] -> [a]
    subst prd upd = go
      where go (x:xs) (y:ys) | prd x     = upd x y : go xs ys
                             | otherwise =       x : go xs (y:ys)
            go xs [] = xs
            go [] ys = ys
    
    main :: IO ()
    main = do
      putStrLn $ slewov "HELLO world"
      putStrLn $ slewov "Programming PRAXIS"
    
    $ ./vowels
    HOLLO werld
    Prigramming PRAXOS
    
  5. Steve said

    Klong version

    Code:
            Klong 20190209
            :" Reverse vowels"
            l::[]
            f1::{[len r s v]; len::#s::x; r::""; v::"AEIOUYaeiouy"; {x<len}{f2(s@x; v); x+1}:~0; {x<len}{r::r,f3(s@x; v); x+1}:~0; r}
            f2::{:[#y?x; l::($x),l; ""]}
            f3::{[r2]; :[#y?x; {r2::*l; l::1_l; r2}(); x]}
    
    Run:
            f1'["HELLO, WORLD!" "PROGRAMMING PRAXIS"]
    ["HOLLO, WERLD!" "PRIGRAMMING PRAXOS"]
    
    
  6. Bill Wood said

    Rust version:

    struct RevVowelIter<'a> {
        it: std::iter::Rev<std::str::Chars<'a>>,
    }
    impl<'a> Iterator for RevVowelIter<'a> {
        type Item = char;
    
        fn next(&mut self) -> Option<Self::Item> {
            while let Some(c) = self.it.next() {
                match c {
                    'a' | 'e' | 'i' | 'o' | 'u' |
                        'A' | 'E' | 'I' | 'O' | 'U' => return Some(c),
                    _ => (),
                }
            }
            None
        }
    }
    impl<'a> RevVowelIter<'a> {
        fn new(s: &'a str) -> Self {
            RevVowelIter { it: s.chars().rev() }
        }
    }
    
    fn rev_vowels(st: &str) -> String {
        let mut s = "".to_string();
        let mut v = RevVowelIter::new(st);
        for c in st.chars() {
            match c {
                'a' | 'e' | 'i' | 'o' | 'u' => s.push(v.next().unwrap().to_ascii_lowercase()),
                'A' | 'E' | 'I' | 'O' | 'U' => s.push(v.next().unwrap().to_ascii_uppercase()),
                _ => s.push(c),
            }
        }
        s
    }
    
    fn main() {
        assert_eq!("HOLLO werld", rev_vowels("HELLO world"));
        assert_eq!("Prigramming PRAXOS", rev_vowels("Programming PRAXIS"));
    }
    

    Playground link https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=60f83463ee1eca11e929173b886da670

  7. Bill Wood said

    Rust version:

    struct RevVowelIter<'a> {
        it: std::iter::Rev<std::str::Chars<'a>>,
    }
    impl<'a> Iterator for RevVowelIter<'a> {
        type Item = char;
    
        fn next(&mut self) -> Option<Self::Item> {
            while let Some(c) = self.it.next() {
                match c {
                    'a' | 'e' | 'i' | 'o' | 'u' |
                        'A' | 'E' | 'I' | 'O' | 'U' => return Some(c),
                    _ => (),
                }
            }
            None
        }
    }
    impl<'a> RevVowelIter<'a> {
        fn new(s: &'a str) -> Self {
            RevVowelIter { it: s.chars().rev() }
        }
    }
    
    fn rev_vowels(st: &str) -> String {
        let mut s = "".to_string();
        let mut v = RevVowelIter::new(st);
        for c in st.chars() {
            match c {
                'a' | 'e' | 'i' | 'o' | 'u' => s.push(v.next().unwrap().to_lowercase().next().unwrap()),
                'A' | 'E' | 'I' | 'O' | 'U' => s.push(v.next().unwrap().to_uppercase().next().unwrap()),
                _ => s.push(c),
            }
        }
        s
    }
    
    fn main() {
        assert_eq!("HOLLO werld", rev_vowels("HELLO world"));
        assert_eq!("Prigramming PRAXOS", rev_vowels("Programming PRAXIS"));
    }
    

    Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=60f83463ee1eca11e929173b886da670

  8. Bill Wood said

    Rust version without custom iterator

    fn rev_vowels(st: &str) -> String {
        let mut s = "".to_string();
        let mut v = st.chars().rev().filter(|c| "aeiouAEIOU".find(*c).is_some());
        for c in st.chars() {
            match c {
                'a' | 'e' | 'i' | 'o' | 'u' => s.push(v.next().unwrap().to_ascii_lowercase()),
                'A' | 'E' | 'I' | 'O' | 'U' => s.push(v.next().unwrap().to_ascii_uppercase()),
                _ => s.push(c),
            }
        }
        s
    }
     
    fn main() {
        assert_eq!("HOLLO werld", rev_vowels("HELLO world"));
        assert_eq!("Prigramming PRAXOS", rev_vowels("Programming PRAXIS"));
    }
    

    Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=54bac1b236904a178f7eb8ba8e5714e8

  9. Daniel said

    Here’s a solution in Python.

    def reverse_vowels(string):
        VOWELS = 'AaEeIiOoUu'
        subs = [x for x in string if x in VOWELS]
        chars = [subs.pop().lower() if x in VOWELS else x for x in string]
        chars = [c if s.islower() else c.upper() for s, c in zip(string, chars)]
        return ''.join(chars)
    
    print(reverse_vowels('HELLO world'))
    print(reverse_vowels('Programming PRAXIS'))
    

    Output:

    HOLLO werld
    Prigramming PRAXOS
    
  10. SRS said

    LOCOMOTIVE BASIC

    10 REM Reverse Vowels by SRS 05.03.2020
    20 MODE 2
    30 PRINT “Please enter a string; this program will then reverse the vowels in that string,”:PRINT “maintaining the original capitalisation of the vowels.”
    40 PRINT
    50 INPUT”Your String:”,s$
    60 FOR i=LEN(s$) TO 1 STEP -1:c$=MID$(s$,i,1):IF INSTR(“aeiouAEIOU”,c$) THEN rv$=rv$+c$
    70 NEXT
    80 FOR i=1 TO LEN(s$):c$=MID$(s$,i,1):IF INSTR(“aeiou”,c$) THEN rs$=rs$+LOWER$(LEFT$(rv$,1)):rv$=RIGHT$(rv$,LEN(rv$)-1):GOTO 110
    90 IF INSTR(“AEIOU”,c$) THEN rs$=rs$+UPPER$((LEFT$(rv$,1))):rv$=RIGHT$(rv$,LEN(rv$)-1):GOTO 110
    100 rs$=rs$+c$
    110 NEXT
    120 PRINT “My Output: “;rs$

Leave a comment