# Challenge

You will be given a string that can contain lowercase letters, uppercase letters, or spaces. You have to turn the vowels (a, e, i, o, u) in the string to upper case and consonants to lower case. This applies whether or not the letter was originally upper case or lower case. Spaces remain as is. Note that "y" is a consonant.

# Examples

Hello World -> hEllO wOrld
abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVXWYZ -> AbcdEfghIjklmnOpqrstUvwxyz AbcdEfghIjklmnOpqrstUvxwyz


# Info

• The input string can contain letters A to Z, lowercase or uppercase, and spaces.

The string

# Output

The formatted string (Vowels uppercase and consonants lowercase).

# JavaScript (Node.js),  55 ... 46  45 bytes

Saved 1 byte thanks to @KevinCruijssen

s=>Buffer(s).map(c=>c^(c^~68174912>>c)&32)+''


Try it online!

### How?

The constant $$\68174912\$$ is a bitmask describing the positions of the vowels:

00000100000100000100010001000000
v     v     v   v   v
zyxwvutsrqponmlkjihgfedcba_^]\[


As per the ECMAScript specification, the following expression:

~68174912 >> c & 32


is equivalent to:

~68174912 >> (c % 32) & 32


and therefore evaluates to $$\32\$$ for a consonant or $$\0\$$ for a vowel, no matter the case of $$\c\$$.

### Commented

s =>                   // s = input string
Buffer(s)            // turn s into a buffer
.map(c =>            // for each ASCII code c:
c ^                //   change the case if:
( c              //     c is not in lower case
^              //     XOR
~68174912 >> c //     c is a consonant
) & 32           //
) + ''               // end of map(); coerce back to a string

• Thank you for the answer, it is so beautiful! – Chau Giang Mar 26 at 8:05

# C (gcc), 49 bytes

f(char*s){for(;*s;s++)*s^=(*s^~68174912>>*s)&32;}


Try it online!

# C (clang), 48 bytes

A version suggested by @Neil

This is abusing the way clang is dealing with the pointer post-increment.

f(char*s){for(;*s;)*s++^=(*s^~68174912>>*s)&32;}


Try it online!

• Ah, this is a binary lookup table of ASCII characters mod 32. Smart. – S.S. Anne Mar 22 '20 at 20:22
• @S.S.Anne Yes, exactly. (I've just added an explanation to my JS answer.) – Arnauld Mar 22 '20 at 20:34
• GCC is too clever, but if you switch to clang then you can (currently) get away with incrementing the pointer in the assignment statement thus saving a byte. – Neil Mar 23 '20 at 11:13
• @Neil Nice find! – Arnauld Mar 23 '20 at 11:27
• @S.S.Anne Yes, you are absolutely right: for n==1|n==5|n==7|n==13, it will test the bitmask 0x20a2 (C to machine code) provided that the code is compiled with at least -O1. – Arnauld Mar 23 '20 at 17:37

# Perl 5-p, 20 19 bytes

-1 due to @NahuelFouilleul

$_=lc;y;aeiou;AEIOU  Try it online! Convert everything to lower case, then change vowels to upper case. • can save one byte using ; as transliterator delimiter and ommiting the last Try it online! – Nahuel Fouilleul Mar 23 '20 at 17:16 • Thanks for the reminder – Xcali Mar 23 '20 at 18:59 # Python 3, 55 bytes lambda s:[[c,c.upper()][c in"aeiou"]for c in s.lower()]  Try it online! Input: A string/sequence of characters Output: a list of characters. ### Explanation The solution converts the string to lower case, then convert all vowels to uppercase. • for c in s.lower() converts the string to lower case, then loop through each character in the string. • [c,c.upper()][c in "aeiou"] converts any vowel to uppercase, and consonant to lower case. c in "aeiou" evaluates to 0 or 1, which is used to index into the list [c,c.upper()]. • Please could you share an explanation of how your lambda Python 3 function works, I'm new to code-golf and my own Python 3 attempt relies on a for loop through list. – user90593 Mar 23 '20 at 19:40 • @AryanBeezadhur the main trick to working out what this answer does is figuring out which meanings the brackets have. The outer ones are a list comprehension, the first inner bracket is a 2 element list, and the second pair of inner brackets are list indexing (using the coercion from booleans to integers) – Potato44 Mar 24 '20 at 10:04 • @Potato44 +1, thanks! – user90593 Mar 24 '20 at 10:06 • Shouldn't the output be a formatted string? – Abdulrahman Bres Mar 26 '20 at 14:31 # CJam, 15 bytes lel"aeiou"_euer  Try it online! ### Explanation l e# Read line el e# To lowercase "aeiou" e# Push this string _ e# Duplicate eu e# To uppercase er e# Transliterate. Implicitly display  # Bash + Core utilities, 25 23 bytes tr aeiou AEIOU<<<${1,,}


Try it online!

Saved 2 bytes thanks to a suggestion of Nahuel Fouilleul.

Input is passed as an argument, output is on stdout.

• saved 2 bytes using lowercase expansion Try it online! – Nahuel Fouilleul Mar 23 '20 at 17:23
• @NahuelFouilleul Thank you -- did you mean something like this? TIO wasn't working on your link ("The permalink could not be decoded"), but I modified the code to use lowercase expansion as you suggested, and saved two bytes. – Mitchell Spector Mar 23 '20 at 18:40

# Python, 53 bytes

lambda s:[(c*2).title().strip('aeiou')[-1]for c in s]


Try it online!

Outputs a list of characters.

Here is an explanation of how it transforms each character c, with examples c='A' and c='B':

                'A'  'B'
(c*2)           'AA' 'BB'  # Two copies of c in a two-character string
.title()        'Aa' 'Bb'  # Title case: uppercase first letter and the rest lowercase
# This disregards the case of c
.strip("aeiou") 'A'  'Bb'  # Remove any leading or trailing lowercase vowels 'aeiou'
# For a two-character string, this removes all such letters
[-1]            'A'  'b'   # Take the last letter


55 bytes

lambda s:[(c*2).title()[~(c in'aieouAEIOU')]for c in s]


Try it online!

If we were instead lowercasing vowels and uppercasing consonants, we wouldn't need the ~() and would have 52 bytes.

• Alternative 53, Python 3 only: lambda s:[max({*(c*2).title()}-{*'aeiou'})for c in s] – Bubbler Mar 25 '20 at 2:36

# sed, 41 25 24 bytes

Saved 16 bytes thanks to Surculose Sputum!!!
Saved a byte thanks to S.S. Anne!!!

s/./\L&/g
y/aeiou/AEIOU/


Try it online!

• 25 bytes – Surculose Sputum Mar 22 '20 at 18:03
• @SurculoseSputum Ah, yes of course. Very nice - thanks! :-) – Noodle9 Mar 22 '20 at 18:05
• 24 bytes – S.S. Anne Mar 22 '20 at 18:11
• @S.S.Anne Interesting, y commands ("Transliterate" according to the docs) act sort of like tr. Nice one - thanks! :-) – Noodle9 Mar 22 '20 at 18:16

# Ruby, 33 bytes

->s{s.downcase.tr"aeiou","AEIOU"}


Straightforward solution: downcase everything, then upcase vowels.

Try it online!

# Jelly,  9  7 bytes

Saved 2 using a variation of Luis Mendo's CJam approach

ØCŒHyŒu


A monadic Link accepting a list of characters which yields a list of characters.

Try it online!

### How?

ØCŒHyŒu - Link: list of characters, S   e.g. "I am OK!"
ØC      - consonants                         "BCDF...XYZbcdf...xyz"
ŒH    - split into two                     ["BCDF...XYZ", "bcdf...xyz"]
Œu - convert (S) to upper-case          "I AM OK!"
y   - translate                          "I Am Ok!"

• This makes much more sense than the other "Jelly" answer. I fiddled with it and got an answer 1 byte longer: ØcṚŒHyŒl by doing the same thing but translating vowels. – RGS Mar 22 '20 at 17:40

# APL (Dyalog Extended), 14 bytesSBCS

Anonymous tacit prefix function.

⌈@(∊∘'aeiou')⌊


Try it online!

⌊ lowercase

⌈@() uppercase at the following positions:

∊∘'aeiou' members of "aeiou"

# Retina, 9 bytes

TvVLVVl


Try it online! Explanation:

TvV


Lowercase vowels get uppercased.

TVV


Uppercase vowels also get uppercased, to avoid being matched later.

TLl


All other uppercase letters get lowercased.

# C (gcc), 75 $$\\cdots\$$72 71 bytes

Added 4 bytes to fixed a bug.
Saved a byte thanks to ceilingcat!!!

u;f(char*s){for(;*s;*s++=u-65&&u-69&&u-73&&u-79&&u-85?*s|32:u)u=*s&95;}


Try it online!

# C (gcc), 58$$\\cdots\$$ 58 bytes

f(char*s){for(;*s;)*s++=index("aeiou",*s|32)?*s&95:*s|32;}


I tried to find a pattern in the vowels' representations using the modulo operator but nothing short enough. Instead, use strchr.

Fixed a bug kindly pointed out by Noodle9 at the cost of 3 bytes.
-1 byte thanks to Noodle9!
-1 byte thanks to Surculose Sputum!
-1 byte thanks to ceilingcat!

Try it online!

# x86 platform-independent machine code, 46 bytes.

Expects the string pointer to be passed in eax, trashes ebx and edx. Entry point is located at 0x26.

Hex dump:

BA 22 82 20 00 D3 EA F6 C2 01 74 0B 8D
51 9F 83 FA 19 8D 59 E0 EB 09 8D 51 BF
83 FA 19 8D 59 20 0F 46 CB 88 08 40 0F
BE 08 85 C9 75 D3 C3


Disassembly:

00000000  BA22822000        mov edx,0x208222
00000005  D3EA              shr edx,cl
00000007  F6C201            test dl,0x1
0000000A  740B              jz 0x17
0000000C  8D519F            lea edx,[ecx-0x61]
0000000F  83FA19            cmp edx,byte +0x19
00000012  8D59E0            lea ebx,[ecx-0x20]
00000015  EB09              jmp short 0x20
00000017  8D51BF            lea edx,[ecx-0x41]
0000001A  83FA19            cmp edx,byte +0x19
0000001D  8D5920            lea ebx,[ecx+0x20]
00000020  0F46CB            cmovna ecx,ebx
00000023  8808              mov [eax],cl
00000025  40                inc eax
00000026  0FBE08            movsx ecx,byte [eax]
00000029  85C9              test ecx,ecx
0000002B  75D3              jnz 0x0
0000002D  C3                ret


byte count = 0x2E = 46

• :( bytes in decimal please – ASCII-only Mar 23 '20 at 3:48
• Two possible options for golfing that bitmap >> (c&31) test of the immediate bitmap: use bts edx, ecx, or use a bitmap that's already shifted by 1 so the bit you want goes into CF instead of the low bit of EDX. (Except that fails for CL&31=0 which doesn't clear CF). Also, you aren't taking any advantage of AL,imm8 short forms like 2-byte test al, imm8. Use ESI as the input pointer so you can lodsb / xchg eax,ecx to do cl = *esi++ Or with BTW, you don't need the byte in CL so it's also better for that reason. – Peter Cordes Mar 23 '20 at 4:29
• @ASCII-only: I fixed the title line of this answer to count in decimal. I think that's allowed even within codegolf's strict rules about not editing other people's code, only fixing formatting and maybe explanations. – Peter Cordes Mar 23 '20 at 8:09
• @Krysztof: Turns out a right-shift works at least as well as bt / salc when you use the ASCII code directly, so it's 1-indexed. I'm not sure why you need so much branching and cmov, though. I think you're separately doing c-'a' and/or c-'A'. You can just mask away the lower-case bit (What is the idea behind ^= 32, that converts lowercase letters to upper and vice versa?); Anyway my answer on this Q ended up branchless other than the loop, 21 bytes. – Peter Cordes Mar 23 '20 at 8:15
• You also don't need a movsx load. This is code-golf: performance isn't important so we don't need to avoid false dependencies or partial-register stalls (e.g. from using a 32-bit cmov after writing 8-bit partial registers). – Peter Cordes Mar 23 '20 at 8:18

# Java 8, 86 34 bytes

S->S.map(c->c^(c^~68174912>>c)&32)


-52 bytes by porting @Arnauld's JavaScript answer, so make sure to upvote him!!

s->{s=s.toLowerCase();for(var p:"aeiou".toCharArray())s=s.replace(p,p&=~32);return s;}


Try it online.

Explanation:

s->{                               // Method with String as both parameter and return-type
s=s.toLowerCase();               //  Convert the entire String to lowercase
for(var p:"aeiou".toCharArray()) //  Loop over the vowels as characters:
s=s.replace(p,p&=~32);         //   And replace the lowercase vowels to uppercase ones
return s;}                       //  Then return the modified String as result


# 05AB1E,  9  6 bytes

Saved 3 using Luis Mendo's CJam approach

lžMDu‡


Try it online! (Footer formats the resulting list of characters as a plain string)

### How?

lžMDu‡         e.g. input="LowEr"  stack: []
l      - push lower-case (input)          ["lower"]
žM    - push lower-case vowels           ["aeiou", "lower"]
D   - duplicate                        ["aeiou", "aeiou", "lower"]
u  - upper-case                       ["AEIOU", "aeiou", "lower"]
‡ - transliterate                    ["lOwEr"]
- implicit print                   lOwEr

• YES...! I was assuming this was Jelly...................................... I was about to come here and comment that I couldn't even find it in the code but now I understand why! Thanks. – RGS Mar 22 '20 at 17:29
• I have a Jelly answer too :) – Jonathan Allan Mar 22 '20 at 17:32

# Io, 72 bytes

Takes input as a special format.

method(x,x map(i,if("aeiou"containsSeq(i),i asUppercase,i asLowercase)))


Try it online!

# Red, 83 82 bytes

func[s][v: charset"aoeiu"parse lowercase s[any[to v change t: v(uppercase t/1)]]s]


Try it online!

# x86-64 machine code, 21 bytes

(Or 20 bytes for an x86-32 version with an explicit length input, allowing dec/jnz as the loop condition. Using cl for a shift count makes it not a win to use loop, and 64-bit mode has 2-byte dec so it's break-even to make it explicit-length).

Callable as void vucd_implicit(char *rdi) with the x86-64 System V calling convention. (It leaves RDI pointing to the terminating 0 byte if you want to use that bonus return value.)

# disassembly: objdump -drwC -Mintel
0000000000401000 <theloop>:
401000:       b8 a0 bb ef fb          mov    eax,0xfbefbba0
401005:       d3 e8                   shr    eax,cl
401007:       30 c8                   xor    al,cl
401009:       24 20                   and    al,0x20
40100b:       30 c8                   xor    al,cl
40100d:       aa                      stos   BYTE PTR es:[rdi],al
000000000040100e <vowel_up_consonant_down>:        # the function entry point
40100e:       8a 0f                   mov    cl,BYTE PTR [rdi]
401010:       84 c9                   test   cl,cl
401012:       75 ec                   jne    401000 <theloop>
401014:       c3                      ret


Notice that the function entry point is in the middle of the loop. This is something you can do in real life; as far as other tools are concerned, theloop is another function that falls into this one as a tailcall.

This uses something like Arnauld's xor/and/xor idea for applying the lcase bit to an input character, instead of the more obvious and cl, ~0x20 to clear it in the original, and al, 0x20 to isolate it from the mask, and or al, cl to combine. That would be 1 byte larger because and cl, imm8 can't use the AL,imm special encoding with no ModRM.

Having the bitmap left-shifted by 5 so the bit we want lines up with 0x20 is also due to @Arnauld's answer. I had been planning to use bt/salc like in a previous vowel/consonant bitmap answer and mask that with 0x20 until I tried Arnauld's way and found it could be done even more efficiently.

NASM source (Try it online! with a test caller that does strlen on a command line arg and uses a write() system call afterward)

global vowel_up_consonant_down
theloop:
; consonant bitmap
;          ZYXWVUTSRQPONMLKJIHGFEDCBA@    For indexing with ASCII c&31 directly
mov   eax, 111110111110111110111011101b << 5   ; line up with the lcase bit
; the low bit is 1 to preserve 0x20 ' '
shr   eax, cl               ; AL & 0x20 is how the lowercase bit *should* be set
xor   al, cl                ; bitdiff = (mask>>c) & c
and   al, 0x20              ; isolate the lowercase bit
xor   al, cl                ; flip the lcase bit if needed
stosb                       ; and store
vowel_up_consonant_down:
mov   cl, [rdi]
test  cl, cl
jnz  theloop               ; }while(c != 0)
ret


## Variants

### no spaces: 19 bytes

If we didn't need to handle spaces (ASCII 0x20), we enter the function at the top, with the mov cl, [rdi] load at the top, but still leave the loop condition at the bottom. So we'd load and re-store the terminating 0, and the XOR that produced it would set ZF. The low bit of the bitmap would be 0 instead of 1.

vucd_pure_alphabetic:
.loop:
mov   cl, [rdi]
...               ; same, but with bitmap[0] => 0
xor   al,cl
jnz  .loop       ; mask>>0 leave the terminating 0 unmodified; xor sets ZF


### Upper-case-only input, like the A to Z in the question indicates: 19 bytes

(Or 17 without spaces either.)

If we can assume the lower-case bit was already cleared on input ASCII bytes, we can save one XOR (and change the other one to an OR)

    ...
shr   eax, cl
and   al, 0x20
or    al, cl
...


### Using the bt instruction:

Normally testing a bitmap is a job for the bt instruction, but where we're not branching on the result, it turns out to be cheaper to shift it, even though that means we can't easily use the loop instruction. (I haven't gone back to this idea to re-golf it after realizing we need to handle spaces).

I suspect there's room for more golfing, but the first version of this I tried was

vucd:
.loop:
mov   dl, [rdi]
;          ZYXWVUTSRQPONMLKJIHGFEDCBA@    1-indexed using ASCII codes directly
mov   esi, 111110111110111110111011101b   ; consonant/vowel bitmap for use with bt
bt    esi, edx              ; CF = mask & (1U << (c&31))
%if CPUMODE == 32
salc                        ; 1B   only sets AL = 0 or 0xFF.  Not available in 64-bit mode
%else
sbb   eax, eax              ; 2B   eax = 0 or -1, according to CF.
%endif
xor   al, dl
and   al, 0x20              ; just the lowercase bit
xor   al, dl
loop .loop
ret


Not re-tested after tweaking to handle spaces.

bt + salc in 32-bit mode costs the same as shr reg,cl + the extra test cl,cl that's needed because we can't use loop. So I think this is also 21 bytes. But 32-bit mode explicit-length can just dec/jnz a reg other than cl for a 20-byte total.

mov esi, imm32 can be hoisted out of the loop, or we can use EAX. Neither affects byte count, only efficiency or the calling-convention.

# Javascript (V8), 97 bytes

s=>[...s].map(c=>{t="aeiouAEIOU";return(t.includes(c)?c.toUpperCase():c.toLowerCase())}).join('')


Takes a string, iterate over every chars and check if the char is a vowel. If so return the char in uppercase, otherwise in lowercase. Then join the return of the map with a void char.

• First post/answer here, if you see some errors or missed case, or just want to improve my code feel free to do so

import Data.Char
f=map(g.toLower)
g x|xelem"aeiou"=toUpper x|1<2=x


Try it online!

# Japt v2.0a0 -m, 10 7 bytes

u r\c_v


Try it

# JavaScript (V8), 93...77 bytes

Log:

• -5 bytes thanks to @Benji
• -14 bytes: switched to case insensitive matching and .test()
s=>[...s].map(c=>/[aeiou]/i.test(c)?c.toUpperCase():c.toLowerCase()).join('')


Try it online!

s=> // es6 arrow function
[...s]. // split input string into array
map(c => // another es6 arrow function, this time for a callback iterating over the array
/[aeiou]/i // case insensitive regex
.test(c)? // use a ternary operator to check if the character matches the regex
c.toUpperCase(): // if true return character to uppercase
c.toLowerCase()) // otherwise return lowercase
.join('') // join the array back into a string


Methods mentioned:

• You could save a few bytes if you change /a|e|i|o|u/ -> /[aeiou] – Benji Mar 25 '20 at 19:28
• right! thanks @Benji – sportzpikachu Mar 26 '20 at 4:21

# T-SQL, 48 bytes

SELECT TRANSLATE(LOWER(v),'aeiou','AEIOU')FROM t


Takes input from a pre-existing table t with varchar column v, per our IO rules.

Converts the entire string to lowercase, then makes just the vowels uppercase. The function TRANSLATE works in SQL 2017 and later.

# Python 3, 50 bytes

lambda s:bytes(c^(c^~68174912>>c%32)&32for c in s)


Try it online!

Port of Arnauld's JS answer using bytes object in Python. Because Python's >> does not imply %32 on its right argument, it must be done manually.

# Charcoal, 14 bytes

⭆↧Ｓ⎇№aeiouι↥ιι


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

  Ｓ             Input string
↧              Lowercased
⭆               Map over characters and join
aeiou      Literal string aeiou
№           Count occurrences of
ι     Current character
⎇            If non-zero
ι   Current character
↥    Uppercased
ι  Else current character
Implicitly print


# Wd, 9 bytes

→d╧o╧╪0╨←


Uncompressed:

("aeiou":)Z


# Explanation

(           % Convert to lowercase
"aeiou"    % All vowel strings
:   % Duplicate
)  % Convert to uppercase
Z % Transliterate


# Batch, 118 115 Bytes

3 bytes saved thanks to Neil

@Set o=%*
@For %%A in (A E I O U b c d f g h j k l m n p q r s t v w x y z)do @Call Set o=%%o:%%A=%%A%%
@ECHO(%O%


Explanation:

Uses Call Set to update variable during operation of For Loop in conjunction with Substring Modification: VarName=%VarName:ToSub=SubValue%.

Substring modification is not case-sensitive - case is determined using the defined For loop set %%A in (set)

• Given that the input is limited to letters and spaces, could you use @set o=%*? – Neil Mar 23 '20 at 11:18

# 05AB1E, 87 6 bytes

-1 byte thanks to Kevin Cruijssen

lžODu‡


Try it online!

• Fails when there are upper-case vowels present in the input – Jonathan Allan Mar 22 '20 at 17:09
• Also not sure why you're treating y` as a vowel, usually it is not considered a vowel. – Jonathan Allan Mar 22 '20 at 17:14
• @JonathanAllan thanks, fixed the bug with uppercase vowels. Regarding your second comment, y is sometimes not considered a vowel, but I sure wouldn’t say that’s “usual”. Y is the sixth vowel letter according to Wikipedia. – Grimmy Mar 22 '20 at 20:54
• You can remove the surrounding map: try it online. – Kevin Cruijssen Mar 23 '20 at 12:31
• @KevinCruijssen thanks! – Grimmy Mar 23 '20 at 12:39