Let's say I have this string:

s = "Code Golf! I love Code Golf. It is the best."

I want to replace all the vowels with repeated "aeiou".


  • Uppercase vowels should be replaced by an uppercase letter, and lowercase vowels should be replaced by a lowercase letter.

  • Consonants (all alphabet characters except for "aeiou") and non alphabetical characters should be kept the same.

Desired output:

Cade Gilf! O luva Cedi Golf. Ut as the bist.

As you can see, the vowels are replaced in repetitive order of "aeiou".

Another example:

s = "This is a test! This is example number two."


Thas es i tost! Thus as eximplo numbar twe.

This is , so shortest code in bytes wins.

  • 23
    \$\begingroup\$ Cade Gilf! O luva Cedi Golf. Ut as the bist. -- you've captured the New Zealand accent perfectly. (I am a Kiwi fyi) \$\endgroup\$
    – roblogic
    Commented Dec 20, 2022 at 13:45
  • 3
    \$\begingroup\$ @roblogic Lol! Maybe they do this on purposely :) \$\endgroup\$ Commented Dec 20, 2022 at 13:58
  • \$\begingroup\$ John Madden! John Madden! \$\endgroup\$
    – apollyon
    Commented Feb 20, 2023 at 0:23

30 Answers 30


C (clang), 65 bytes


Try it online!


Detecting vowels

We determine whether the current character at *s is a vowel with:

2130466 >> *s & *s > 64

The value \$2130466\$ is a bitmask describing the positions of vowels:

     ^     ^     ^   ^   ^

The shift amount is interpreted modulo 32 (to my knowledge, this is true for at least Intel and ARM processors). This means that we just have to make sure that the character is a letter (with *s > 64) and can use the same expression for lower and upper case.

Turning them into different vowels

An interesting thing about vowels is that all their ASCII codes are odd:

A |  65 | 1000001        a |  97 | 1100001
E |  69 | 1000101        e | 101 | 1100101
I |  73 | 1001001        i | 105 | 1101001
O |  79 | 1001111        o | 111 | 1101111
U |  85 | 1010101        u | 117 | 1110101
          ||    |
          ||    '--> always 1
          |'-------> 'case' bit
          '--------> always 1

To turn a vowel of a given case into another vowel with the same case, only bits #1 to #4 (0-indexed) need to be modified. This can be represented with the bitmask \$00011110_2=30_{10}\$.

Hence a possible formula:

new_vowel = old_vowel XOR (x XOR (old_vowel AND 30))

where \$x\in\{0,4,8,14,20\}\$ (for A,E,I,O,U respectively).

Given \$i\in[0\dots4]\$, we get \$x_i\$ with:

$$x_i=(i\times 5)\operatorname{xor}(5 \bmod (i+1))$$

i i * 5 5 mod (i+1) xor
0 0 0 0
1 5 1 4
2 10 2 8
3 15 1 14
4 20 0 20

As C code, this gives:

*s ^= i * 5 ^ 5 % ++i ^ *s & 30

which, conveniently, is incrementing \$i\$ at the same time.

Putting everything together

i;                  // i is a counter for vowel replacement
f(*s) {             // s is the input string
  for(              // main loop:
    i = 0;          //   start with i = 0
    *s++ ^=         //   update the character *s:
      2130466 >> *s //     if this looks like a vowel
      & *s > 64 ?   //     and really is a letter:
        i * 5 ^     //       turn it into a different vowel
        5 % ++i ^   //       and increment i afterwards
        *s & 30     //
      :             //     else:
        0;          //       leave it unchanged
                    //   (NB: we stop when the result is NUL)
    i %= 5          //   make sure to keep i in [0..4]
  );                // end of loop
}                   //
  • 2
    \$\begingroup\$ I really love to see bit masking solutions, nice one btw! \$\endgroup\$
    – Alex
    Commented Dec 21, 2022 at 16:23

R, 94 81 79 bytes

Edit: -2 bytes thanks to pajonk


Attempt This Online!

Input & output as character vectors.
(Splitting-up an input string and reassembling one for the output costs about +36 bytes, for comparison with any alternative approaches that directly use strings).

Previous 94-byte version (using grep and toupper)

  • \$\begingroup\$ Not using the scan trick leads to -2 bytes. \$\endgroup\$
    – pajonk
    Commented Dec 21, 2022 at 12:39
  • \$\begingroup\$ @pajonk - Ah, thanks! I think it saved something in the old version with only a e i o u, but I didn't notice that the extra letters now stopped it making sense any more... \$\endgroup\$ Commented Dec 21, 2022 at 12:56

Excel (ms365), 183, 164 bytes

-19 bytes thanks to @jdt

enter image description here

Formula in B1:

  • \$\begingroup\$ =LET(x,MID(A1,ROW(A:A),1),y,"uaeio",r,SEARCH(x,y),z,SCAN(0,r,LAMBDA(a,b,a+(-ISERR(b)=0))),w,MID(y,MOD(z,5)+1,1),CONCAT(IFERROR(IF(r*(CODE(x)<97),UPPER(w),w),x))) \$\endgroup\$
    – jdt
    Commented Dec 23, 2022 at 16:29

Vyxal, 11 bytes


Try it Online!

If I had a nickel for every time I'd answered a vowel-related challenge with an 11 byte Vyxal answer in the last 2 weeks, I'd have 2 nickels, which isn't a lot but it's weird that it's happened twice. Outputs as a list of characters (add the s flag if you want a string object).


⟑           # To each character:
 A[         #  if it is a vowel:
   kv¥i     #    get the (register)th item of the string "aeiou" - wraps around if the register > 5
       $•   #    and give it the same case of the current character
         &› #    increment the register to get the next vowel
  • \$\begingroup\$ If I had a nickel for every time lyxal used a "if I had a nickel for every time I did something" metaphor I'd have about 3-4 nickels right now \$\endgroup\$ Commented Jan 5, 2023 at 4:54

Python, 109 106 104 98 bytes

f=lambda s,i=0:s and((c:=s[0])in(v:='uaeioUAEIO')and[v[:5],v[5:]][c<'a'][i:=-~i%5]or c)+f(s[1:],i)

Attempt This Online!

  • -6 thanks to Steffan

Python, 117 116 112 111 bytes

(not valid - this is just for fun)

lambda s:re.sub('[aeiou]',g,s,0,2)
def g(c):global i;i=-~i%5;return['uaeio','UAEIO'][c[0]<'a'][i]
import re

Attempt This Online!

  • -4 thanks to Steffan
  • -1 thanks to pxeger

Just wanted to try with a Regex-based approach. The function isn't reusable so it's not a valid solution.

  • \$\begingroup\$ i:=-~i%5 doesn't need parens, ord(c)<96 => c<'a' (a could be any char higher than Z) \$\endgroup\$
    – naffetS
    Commented Dec 20, 2022 at 22:10
  • \$\begingroup\$ @Steffan thanks! \$\endgroup\$
    – The Thonnu
    Commented Dec 21, 2022 at 9:46
  • \$\begingroup\$ sub('[aeiouAEIOU]',g,s) can be sub('[aeiou]',g,s,0,2) (0 is the maximum number of replacements to perform (0 meaning unlimited), and 2 is the value of the re.IGNORECASE flag) \$\endgroup\$
    – pxeger
    Commented Dec 21, 2022 at 14:30
  • \$\begingroup\$ Your second submission is not valid though, because it's not reusable: you'd need to reset i to 0 every time the lambda is called. \$\endgroup\$
    – pxeger
    Commented Dec 21, 2022 at 14:31
  • \$\begingroup\$ @pxeger thanks. I've updated the answer. \$\endgroup\$
    – The Thonnu
    Commented Dec 21, 2022 at 14:35

JavaScript (ES6), 59 bytes


Try it online!

  • \$\begingroup\$ Does /gi not help? \$\endgroup\$
    – Neil
    Commented Dec 20, 2022 at 13:57
  • \$\begingroup\$ @Neil I was just testing the /gi solution. Turns out it's one byte shorter. \$\endgroup\$
    – Arnauld
    Commented Dec 20, 2022 at 13:58
  • \$\begingroup\$ Oh, I hadn't realised you were using the regex source for your vowels... \$\endgroup\$
    – Neil
    Commented Dec 20, 2022 at 13:59

Python, 80 74 bytes

  • -6 thanks to xnor!
for c in input():print(end=c[c in V:]or(v:=v[2:]+V)[c>V])

Attempt This Online! Full program.

Python, 85 81 78 bytes

  • -4 thanks to Steffan!
  • -3 thanks to xnor!
lambda s,v='uUaAeEiIoO':''.join(c[c in v:]or(v:=v[2:]+v[:2])[c<'a']for c in s)

Attempt This Online!

  • 1
    \$\begingroup\$ I'm pretty sure you can leave out the f= since it's not recursive \$\endgroup\$
    – The Thonnu
    Commented Dec 20, 2022 at 17:40
  • 1
    \$\begingroup\$ @TheThonnu Oh right, I forgot about that, thanks! \$\endgroup\$
    – u-ndefined
    Commented Dec 20, 2022 at 17:52
  • 2
    \$\begingroup\$ ord(c)<96 => c<'a' \$\endgroup\$
    – naffetS
    Commented Dec 20, 2022 at 22:09
  • 1
    \$\begingroup\$ 78 bytes \$\endgroup\$
    – xnor
    Commented Dec 21, 2022 at 13:05
  • 3
    \$\begingroup\$ 74 bytes \$\endgroup\$
    – xnor
    Commented Dec 21, 2022 at 13:10

Raku, 44 bytes

{$!=0;S:g:ii[<[aeiou]>]=<a e i o u>[$!++%*]}

Try it online!

Most of the magic here is in the samecase flag on the substitution, whose short form is ii. It makes the match case-insensitive, and furthermore carries the case information forward into the substituted text.

  • \$\begingroup\$ You can remove $!=0 and use $++ instead of $!++ \$\endgroup\$
    – naffetS
    Commented Dec 20, 2022 at 21:30
  • \$\begingroup\$ @Steffan Actually I can't, because the $ state variable would keep its value from one function call to the next. \$\endgroup\$
    – Sean
    Commented Dec 20, 2022 at 21:53
  • \$\begingroup\$ No, that's not how $ works. It is scoped to the substitution, not the function. \$\endgroup\$
    – naffetS
    Commented Dec 20, 2022 at 22:04
  • 1
    \$\begingroup\$ @jubilatious1 $! is a special variable that holds the last thrown exception. You can use it for anything you want, though. It's not uncommon to see it used as a helper variable in golfing, since it saves you two bytes over declaring a new variable with my. I would never use it for that purpose in real code, though. \$\endgroup\$
    – Sean
    Commented Dec 21, 2022 at 15:55
  • 1
    \$\begingroup\$ @jubilatious1 In Raku, you can pass a function as the subscript to an array. Raku will call the function with the size of the array as its argument, and use whatever the function returns as the actual index into the array. Most often this is used to index from the end of the array, eg. @array[*-1] to get the last element. Here *-1 is just an anonymous function that subtracts one from its argument. In my code here, $!++ % * is another anonymous function that increments $! and returns the remainder of its previous value when divided by the function's argument. \$\endgroup\$
    – Sean
    Commented Dec 23, 2022 at 17:10

Pip, 37 21 bytes

- 14 bytes of mostly DLosc, and jezza_99 getting ninja'd
- 2 bytes thanks to jezza_99


Try It Online!

I'm bad at golfing in pip lol.

aR-XV{                }      Replace (case-insensitive) vowels with ...
      YVW@Uv                 Set y to the (vth*1) vowel
            aNz?yUCy         Copy case to y                     
  • \$\begingroup\$ Hint: instead of running a For loop, this is a good occasion to use regex replacement (-XV, i.e. "vowels, case-insensitive," is the regex you'll want). By using a function as the replacement, you can make the logic for picking the replacement character as complex as needed. \$\endgroup\$
    – DLosc
    Commented Dec 20, 2022 at 20:09
  • \$\begingroup\$ 24 bytes using @DLosc tip \$\endgroup\$
    – jezza_99
    Commented Dec 20, 2022 at 20:40
  • \$\begingroup\$ @jezza_99 oh nvm yours is 23 too, there's a crlf in the end \$\endgroup\$
    – math scat
    Commented Dec 20, 2022 at 20:52
  • \$\begingroup\$ @mathcat haha whoops, yes 23 bytes \$\endgroup\$
    – jezza_99
    Commented Dec 20, 2022 at 21:21
  • 1
    \$\begingroup\$ 21 bytes by shifting the increment and checking if a is in the lowercase alphabet z \$\endgroup\$
    – jezza_99
    Commented Dec 21, 2022 at 0:37

Japt v2.0a0, 21 bytes


Try it

r\v@T°g`aei`c^H*XèXu     :Implicit input of string
r                         :Replace
 \v                       :RegEx /[aeiou]/gi
   @                      :Pass each match X through the following function
    T°                    :  Postfix increment T (initially 0)
      g                   :  Index into
       `aei`             :    Compressed string "aeiou"
             c            :    Map charcodes
              ^           :      Bitwise XOR with
               H*         :      32 multiplied by
                 Xè       :      Count the occurrences in X of
                   Xu     :        X uppercased

Haskell, 93 bytes

(x:r)%u@(v:t:w)|elem x u=c:r%(w++[v,t])|1>0=x:r%u where c|x>'Z'=v|1>0=t

Attempt This Online!


import Data.Char
g vowels@(vowel:vOWEL:rest) (char:chars)
  | char `elem` vowels
    = mappedChar : g rotatedVowels chars
  | otherwise
    = char : g vowels chars 
    rotatedVowels = rest ++ [vowel, vOWEL]
      | isUpper char = vOWEL
      | otherwise = vowel
g _ "" = ""
g "aAeEiIoOuU"

Python 3.8+, 183 156 127 117 111 bytes

-29 bytes thanks to ElPedro
-10 bytes thanks to Neil
-6 bytes thanks to help from the Discord (mainly by dzaima and me)

def x(n):m,j='aeiou',0;return''.join([((m,m.upper())[i<'a'][j%5],j:=j+1)[0]if i.lower()in m else i for i in n])
  • \$\begingroup\$ A few golfs to help you get it down to 127 \$\endgroup\$
    – ElPedro
    Commented Dec 20, 2022 at 15:12
  • 1
    \$\begingroup\$ @ElPedro t+=(m,m.upper())[i<'a'][j%5];j+=1 saves another 10 bytes. \$\endgroup\$
    – Neil
    Commented Dec 20, 2022 at 19:44
  • \$\begingroup\$ @Neil Very nice. Not sure how a missed i<'a'. I've maybe been away from Code Golf for too long :-) \$\endgroup\$
    – ElPedro
    Commented Dec 20, 2022 at 20:20
  • \$\begingroup\$ ElPedro and Neil note that I have now golfed this to 111 bytes by using a list comprehension \$\endgroup\$ Commented Jan 3, 2023 at 15:51
  • \$\begingroup\$ This doesn't seem to be syntactically correct - you seem to be missing at least 1 parenthesis, and the brackets/parentheses seem to be unbalanced \$\endgroup\$ Commented Jan 3, 2023 at 19:15

Python 3, 130 122 120 bytes

for i in input():
 if i.lower()in v:p(end=[v[n],v[n].upper()][i.isupper()]);n=-~n%5

Try it online!

-8 bytes thanks to myself

-2 bytes thanks to The Thonnu

  • \$\begingroup\$ Beat me by 1 byte! \$\endgroup\$
    – The Thonnu
    Commented Dec 20, 2022 at 13:15
  • \$\begingroup\$ @TheThonnu Haha! \$\endgroup\$ Commented Dec 20, 2022 at 13:16
  • \$\begingroup\$ Added a new 120 byte solution... \$\endgroup\$
    – The Thonnu
    Commented Dec 20, 2022 at 13:17
  • \$\begingroup\$ @TheThonnu Added a 122 byte! \$\endgroup\$ Commented Dec 20, 2022 at 13:19
  • 1
    \$\begingroup\$ You can equal my score by replacing n=(n+1)%5 with n=-~n%5 \$\endgroup\$
    – The Thonnu
    Commented Dec 20, 2022 at 13:19

Pyth, 25 bytes


Try it online!


sm?}r0dK"uaeio"r@K=hZrId1dQ    # implicitly add dQ to the end
                               # implicitly assign Q = eval(input())
       K"uaeio"                # assign K to "uaeio"
s                              # sum of
 m                        Q    # map lambda d over Q
  ?}r0dK                       # ternary, if lowercase(d) in K:
               r     rId1      #   map case to d of
                @K             #   (looping) index K at
                  =hZ          #   increment Z, and assign it to the increment
                         d     # else: d

Jelly, 23 bytes


Try it online!

Jelly isn't great at challenges. Full program, as we take advantage of Jelly's smash printing.

How it works

ØciⱮðḟ0ØėṁŒs>5$}¡"Ɗż@œp - Take a string S on the left
Øc                      - Yield "AEIOUaeiou"
   Ɱ                    - For each character C in S:
  i                     -   Get the index of C in "AEIOUaeiou", or 0 if not found
    ð                   - Begin new dyadic chain, with vowel indices V on the left and S on the right
     ḟ0                 - Remove zeros from V, call that V'
                  Ɗ     - Group the previous 3 links into a monad f(V'):
       Øė               -   Uppercase vowels; "AEIOU"
         ṁ              -   Repeat to the same length as V'
                 "      -   For each pair (v, i) with v a vowel and i an index in V':
                ¡       -     Repeat:
              $         -       Iteration count:
               }        -         Is i...
            >5          -         ...greater than 5?
          Œs            -       Action: Swapcase
                     œp - Partition S at the the indices in V
                   ż@   - Zip the partition and the vowels, with reversed @rguments

Factor, 87 86 bytes

[ EBNF[=[ r=([aeiouAEIOU]=>[[96 > 0 -32 ? 0 inc 0 get 1 - 5 mod "aeiou"nth +]]|.)*]=]]

Attempt This Online!

  • [ ... ] Define a quotation, or anonymous function, that takes a string as input from the data stack and leaves a string as output on the data stack.
  • EBNF[=[ ... ]=] Define an anonymous EBNF parser that automatically runs on an input and produces an output.
  • r= Name the topmost EBNF rule. There has to be at least one rule, so here it is.
  • (...|.)* Match any number (*) of ... or (|) anything (.). The . matches consonants which will remain the same.
  • [aeiouAEIOU] Match any vowel.
  • =>[[...]] An EBNF action. The code inside the double brackets will run on each token before being added to the parse tree.
  • 96 > 0 -32 ? Is the vowel we matched lowercase? Push 0 on the data stack if so; otherwise, push -32 on the data stack.
  • 0 inc Increment the value stored at 0. In Factor, any value (such as 0) can be used as a variable (key) to store a value in an implicit hierarchy of hash tables. If 0 contains f, which all uninitialized variables do by default, inc will cause the value to become 1.
  • 0 get Get the value stored at 0.
  • 1 - Subtract one. We do this because it's shorter than initializing 0 to 0.
  • 5 mod Modulo five.
  • "aeiou"nth Get the nth letter in "aeiou".
  • + Add this letter to the 0 or -32 from earlier. This is what capitalizes the letter or keeps it lowercase.
  • 2
    \$\begingroup\$ First time I've ever seen EBNF used in a competitive answer. And to think I thought it was only good for lexers and parsers! :p \$\endgroup\$
    – lyxal
    Commented Dec 21, 2022 at 12:38

Java (JDK), 125131 bytes

s->{String v="aeiouAEIOU",r="";int j=0,p;for(var c:s.toCharArray()){p=v.indexOf(c);r+=p>=0?v.charAt((p>4?5:0)+j++%5):c;}return r;};

Try it online!

(Edited to add some lambda boilerplate.)

  • \$\begingroup\$ Welcome to Code Golf! I think usually the method/function declaration boilerplate is included in the score \$\endgroup\$ Commented Dec 21, 2022 at 19:58
  • \$\begingroup\$ Thanks. Should it be (1) String f(String s){...} or is (2) (s)->{...}; allowed, with the declaration (e.g. Function<String,String>) of the lambda omitted? \$\endgroup\$ Commented Dec 21, 2022 at 20:20
  • \$\begingroup\$ I've changed it to a lambda but left the lambda declaration implicit as per this Java answer to another challenge. \$\endgroup\$ Commented Dec 21, 2022 at 20:38
  • \$\begingroup\$ 126 bytes \$\endgroup\$
    – ceilingcat
    Commented Dec 22, 2022 at 16:49

Retina, 82 54 bytes


Try it online! Link includes test cases. Explanation:


Prefix as to all of the vowels, both lower and upper case.


Cyclically transliterate only the new as to vowels.


Uppercase the new vowels that precede old uppercase vowels.


Delete alternate vowels i.e. the old vowels.

If the input had all been in (say) lowercase, then it could have been done in 11 bytes:


Try it online! Link includes test cases. Explanation: Simply cyclically transliterates all the lowercase vowels to as and back to vowels.


Charcoal, 28 bytes


Try it online! Link is to verbose version of code. Explanation:


Get the vowels into a string to reduce repetition, but start with u because they need to be 1-indexed.


Loop over the input characters, replacing letters whose lowercase can be found in the string of vowels with letters cyclically chosen from the string or its uppercase according to the number of matches so far.


Perl 5 -p, 33 bytes

s/[aeiou]/$&&a|(<A E I O>||U)/ige

Try it online!


Dart (2.18.4), 139 bytes

r(s,[j=0,v='aeiouAEIOU',t,i=0])=>[for(var c=(l)=>v[(l?0:5)+j++%5];i<s.length;i++)if(v.contains(t=s[i]))c(t.codeUnitAt(0)>96)else t].join();

APL (Dyalog Extended), 25 bytes

Anonymous tacit prefix function.


Try it online!

× the case of the letters…

× imposed as case onto…

()@() amend the characters at the following locations:

| where the casefolded characters…

∊()⍨ are members of the following constant:

  v←'aeiou' the vowels (which are assigned to v

… with…

 the count of such located vowels

 cyclically reshaping the following constant:

  v the previously created v


Ruby (2.5.5), 113 bytes


Try it online!


Zsh, 87 bytes

Try it Online!   123 bytes   133 bytes

w=UAEIOuaeio;for k (${(s::)1}){let j+=${k/[$w]/1}
printf ${k/[$w]/$w[j%5+(#k<91?1:6)]}}

05AB1E, 17 bytes


I/O as a list of characters.

Try it online or verify all test cases.


žM           # Push string "aeiou"
  I          # Push the input-list
   l         # Convert each letter to lowercase
    å        # Check for each letter if it's in the vowels-string
     ÅÏ      # Apply on the truthy indices of the (implicit) input-list:
       žM    #  Push string "aeiou" again
         ¾è  #  Get the (modular) 0-based `¾`'th vowel
           ¼ #  Then increase `¾` by 1
       s     #  Swap so the current character is at the top
        .ui  #  Pop, and if it's uppercase:
           u #   Uppercase the indexed vowel as well
             # (after which the list of characters is output implicitly as result)

Ly, 58 bytes

"uoiea">ir[s<l'ZLsf:l' *+fsp~[p' *sp:l-s>pl<psprlr00]pp>o]

Try it online!

I thought this would be a "minor" variation on another answer I coded earlier this week. I was wrong. :)

The code uses one stack to hold a list of vowels. They are rotated each time one of them is used. And it uses a second stack as a "burndown" list of the input characters (codepoints). It copies one input character at a time to the vowel stack, searches for it, and if found substitutes the "next" vowel for the top of the burndown stack. Then it switches back to the burndown stack and prints the top codepoint as a character.

The upper/lowercase logic adds a bunch of code to the program and chaos of temporary stack entries...

"uoiea">ir  - setup...
"uoiea"     - push vowels onto the stack
       >ir  - switch to a new stack, read STDIN into the stack and reverse

[s<l'ZLsf:l' *+fsp~[...if vowel...]pp>o] - process each char
[                                      ] - loop until empty
 s<l                                     - copy char to vowel stack
    'ZL                                  - upper case?
       s                                 - save result
        f:                               - pull char forward, duplicate
          l                              - retrieve upper case 1|0
           ' *+                          - map to lowercase if appropriate
               f                         - pull original char forward
                sp                       - save it and delete
                  ~                      - search for lower case char
                   [...if vowel...]      - if it's a vowel, do this block
                                   pp    - clean up the stack
                                     >o  - switch stack, print top entry

p' *sp:l-s>pl<psprlr00 - code block run if we find a vowel
p                      - delete "if" test var
 ' *                   - calculate "should uppercase" delta
    sp                 - save and delete from stack
      :                - duplicate current vowel
       l               - load "uppercase" delta
        -              - convert case if called for
         s>            - save vowel to print, switch stacks
           pl          - delete original vowel, load replacement
             <         - switch back to rotating vowel stack
              p        - clean-up stack
               sprlr   - move vowel on top of stack to the bottom
                    00 - push entries on stack to match non-vowel state

Jelly, 17 bytes


Try it online!

Was originally e€ØcÄịØėa@Ʋo⁸O|O&32ƊỌ, but that eventually turned into this with some inspiration from caird's answer.

 €                   For each character of the input,
f Øc                 filter it to AEIOUaeiou, producing a mix of empty and length-1 strings.
    Øėṁ              Mold AEIOU to the same shape as that.
       ȯ"            Replace empty strings with corresponding characters from the input.
                "    For each pair of such corresponding elements:
         Œl          lowercase the result
               ¡     if
           ⁺  }      the original lowercased (and wrapped in a string)
            i$       contains the original.

Zsh --extendedglob, 63 bytes


Try it online!

Thanks to @roblogic for the answer without --extendedglob which kicked this off. I've got basically the same logic, just using (#m)+$MATCH to keep track of the upper/lower case within a single PE.


Arturo, 79 bytes


Try it


Scala, 147 bytes

Golfed version. Try it online!

def f(x:String)={var (p,i)=("aeiou",0);x.map(t=>if(p.contains(t.toLower)){val r=p(i%5);val o=if(t.isUpper)r.toUpper else r;i+=1;o}else t).mkString}

Ungolfed version. Try it online!

object VowelShift {
  def main(args: Array[String]): Unit = {
    val f: String => String = (x: String) => {
      val p = "aeiou"
      var i = 0
      x.map { t =>
        if (p.contains(t.toLower)) {
          val r = p(i % 5)
          val o = if (t.isUpper) r.toUpper else r
          i += 1
        } else {

    println(f("Code Golf! I love Code Golf. It is the best.") == "Cade Gilf! O luva Cedi Golf. Ut as the bist.")
    println(f("This is a test! This is example number two.") == "Thas es i tost! Thus as eximplo numbar twe.")


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.