i;f(*s){for(i=0;*s++^=2130466>>*s&*s>64?i*5^5%++i^*s&30:0;i%=5);}
Try it online!
How?
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:
000001000001000001000100010
^ ^ ^ ^ ^
zyxwvutsrqponmlkjihgfedcba
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
} //
Cade Gilf! O luva Cedi Golf. Ut as the bist.
-- you've captured the New Zealand accent perfectly. (I am a Kiwi fyi) \$\endgroup\$