# Converting a string to lower-case (without built-in to-lower functions!)

The goal of this code-golf is to create a code that lets the user input an ASCII string (contains only printable ASCII characters), and your program outputs the lower-case variant of this string.

Important: you are NOT allowed to use a built-in function that converts the string (or just one character) to lowercase (such as ToLower() in .NET, strtolower() in PHP , ...)! You're allowed to use all other built-in functions, however.

Another important note: The input string doesn't contain only uppercase characters. The input string is a mix of uppercase characters, lowercase characters, numbers and other ASCII printable characters.

Good luck!

• unfortunately, I'll have to opt-out. I'm not a beginner. – John Dvorak Oct 6 '13 at 13:42
• @Jan: Well, with beginner I actually meant that the skill level of this would be 'beginner', not that only beginners would be allowed to enter. I removed the word 'beginner' and surely, you're allowed to enter. – ProgramFOX Oct 6 '13 at 13:45
• Are regular expressions allowed? Only GolfScript could beat s/./\L\0/g. – manatwork Oct 6 '13 at 13:49
• @manatwork: surely \L is built in? – marinus Oct 6 '13 at 13:50
• @manatwork: Yes, a regex is allowed. – ProgramFOX Oct 6 '13 at 13:50

### Shell - 10

Translation of @Gowtham's Perl solution using /bin/tr.

tr A-Z a-z


Sample run:

% tr A-Z a-z <<<'Hello WORLD! @'
hello world! @

• What makes this the accepted answer, out of curiosity? Gowtham had a 10-character solution first… – Ry- Oct 10 '13 at 1:25
• Based on the discussion on meta it seems the reasoning is that Gowtham's solution is 11 chars (because the -p flag counts as one). I agree though, his seems like it deserves more to be accepted.. – FireFly Oct 10 '13 at 5:57
• Ah, thanks – that makes sense. I’ll keep it in mind! – Ry- Oct 10 '13 at 14:32

# Python 2.7 - 30 (with terrible and unapologetic rule abuse)

raw_input().upper().swapcase()


As an anonymous edit pointed out, you can do it in 27 26 in Python 3:

input().upper().swapcase()


I'm flagrantly abusing the rules here, but...

Important: you are NOT allowed to use a built-in function that converts the string (or just one character) to lowercase (such as ToLower() in .NET, strtolower() in PHP , ...)! You're allowed to use all other built-in functions, however.

This takes the strings and coverts it to upper case. Then in a very unrelated method call, it reverses the case of the string - so that any lower case letters become upper case letters... and swaps any upper case letters to lower case letters.

• The Python 3 solution is 26 characters. – Timtech Dec 8 '13 at 12:50
• @Timtech I can't count. – user8777 Dec 8 '13 at 23:48
• It's not just unrelated. It's very unrelated. – Carter Pape Aug 20 '14 at 2:34
• This will have strange results when encountering text that contains the characters ß. – FUZxxl Aug 23 '14 at 14:26

Perl - 11 10 characters.

y/A-Z/a-z/


y/// is same as tr///!

In action:

% perl -pe 'y/A-Z/a-z/' <<< 'Hello @ WORLD !'
hello @ world !

• +1, for the only real-life language that beat out all the less(?) real ones. – Behrooz Oct 6 '13 at 19:57
• Actually that is 11 characters. The -p option is counted as 1. – manatwork Oct 8 '13 at 7:56
• @manatwork Or it should be counted as 2 : - and p :) – Gowtham Oct 8 '13 at 13:15
• 1 if you assume -e (perl -e -> perl -pe), 3 if you assume a script (perl -> perl -p). – nyuszika7h Aug 20 '14 at 9:46
• This could be 9 using y;A-Z;a-z instead! – Dom Hastings Apr 24 at 7:04

## Befunge-98 - 26 22 21 19

~:''-d2*/1-!' *+,#@


Relies on the fact that (c-39)/26 is 1 only for character codes of uppercase ASCII characters (assuming integer division). For each character c, print out c + (((c-39)/26)==1)*' '.

Sample session:

% cfunge lower.b98
hello WORLD!
hello world!
This is a TEST!!11 az AZ @[{
this is a test!!11 az az @[{


### Python 3, 48

input().translate({c:c|32for c in range(65,91)})

• Can you explain how this works? I'm really interested in getting better at Python. I don't get how the map(ord,input()) bit works. – asteri Oct 6 '13 at 17:34
• @JeffGohlke: map applies a function (in this case, ord) to an interable and returns an iterable. It’s like a shorter form of (ord(x) for x in input()). – Ry- Oct 6 '13 at 18:21
• Got it. Thanks for the explanation! – asteri Oct 6 '13 at 18:25
• Your answer follows the spirit of the question, but mine follows the letter of the question... – user8777 Oct 7 '13 at 5:55
• Very nice. Beat my unposted 62 length solution for c in input():print([c,(chr(ord(c)+32))]['@'<c<'['],end=''). I tried some with the map(ord,input()) trick, but missed the multiplying the truth value by 32 and adding it to the character code trick. Very nice. – Steven Rumbalski Oct 8 '13 at 18:56

## Ruby, 18 characters

Nothing really interesting.

gets.tr'A-Z','a-z'


(run in IRB)

Just for fun: a confusing version:

$,=$* *' ';$;=$,.tr'A-Z','a-z';$><<$;


Run like this:

c:\a\ruby>lowercase.rb Llamas are AMAZING!


Output

llamas are amazing!


## J - 30

'@Z'(]+32*1=I.)&.(a.&i.)1!:1]1


J is read right-to-left, so to break this down:

1. Prompt user for input: 1!:1]1
2. Perform algorithm in code-point-space: &.(a.&i.)
3. Identify character range for each letter; the characters between codepoints "@" and "Z" are considered uppercase: 1=I..
4. For each uppercase codepoint, add 32: ]+32* ...
5. Note that step (2) creates an implicit step (5): we started out by projecting from character to integer domain, so now that we're finished, we map those integers back onto characters.

Obviously this particular implementation only considers ASCII; but the approach could be extended to at least the basic multilingual plane in Unicode.

• Nice! Unfortunately, it seems your solution is going the WRONG WAY. ;-) Should be an easy fix though. (Edit: '@Z'(]+32*1=I.)&.(a.&i.)1!:1]1 should do it) – FireFly Oct 6 '13 at 16:33
• Nice catch, thanks. I'm also impressed you were able to fix the code yourself: J isn't the most immediately-accessible language out there :) – Dan Bron Oct 6 '13 at 16:45
• Ah, I've played around some with J myself.. I managed to come up with u:(a.i.x)+32*1='@Z'I.x=.1!:1]1, which matches your length but is much less interesting (as it doesn't make use of 'under'). Speaking of which, I didn't know about dyadic I., so thanks for using that. :-) – FireFly Oct 6 '13 at 16:49
• Cool. But your Befunge solution still has J beat by 4 characters. Obviously I can't let that stand :) I'm trying to see if trim the J solution down by following your lead in relying solely on '@', rather than both '@' and 'Z'. – Dan Bron Oct 6 '13 at 16:57
• (32(23)b.])&.(3&u:), should be 5 bytes shorter. – FrownyFrog Oct 20 '17 at 0:12

C 64 63 59 55 chars

main(c){while(c=getchar(),~c)putchar(c-65u<27?c+32:c);}

• I count only 63 characters there. – manatwork Oct 7 '13 at 9:26
• You can lose 9 characters: drop int  and ,c>=0. They're not necessary here. – JoeFish Oct 7 '13 at 18:00
• we need c>=0 as getchar(EOF) will be < 0. Thanks for other suggestion. – Rozuur Oct 7 '13 at 21:20
• 1. ~(c=getchar()) 2. c-64u<27 – ugoren Oct 8 '13 at 8:28
• Insignificantly small bug: seems there should be 65 instead of 64. pastebin.com/Zc9zMx2W – manatwork Oct 9 '13 at 16:03

Golfscript - 17

Program:

{..64>\91<*32*+}%


Explanation:

1. {}% maps the code inside to every character in string.
2. .. copies the top of the stack (the character) twice.
3. 64> 1 if character code is greater than 64, else 0.
4. \ swaps the two items on the stack (gets the second copy of the letter, and stores the result of 64> in position two).
5. 91< checks to see if character code is less than 91. Similar to step 3.
6. * multiplies the results from steps 3 and 5 together. Only equal to 1, if both steps were true.
7. 32* multiplies the result of step 6 with 32. Will be 32 if step 6 was 1, else 0.
8. + add the result (either 32 or 0) onto the character code.

Example output:

echo HelLO @ WorLD | ruby golfscript.rb upper_to_lower.gs
hello @ world


# Perl: 24 characters

s/[A-Z]/chr 32+ord$&/ge  Sample run: bash-4.1$ perl -pe 's/[A-Z]/chr 32+ord$&/ge' <<< 'Hello @ WORLD !' hello @ world !  • Hem, why chr ord ? I'm pretty sure you won't learn anything in reading my answer ;-) – F. Hauri Dec 4 '13 at 17:46 • Amazing trick, @F.Hauri! – manatwork Dec 4 '13 at 18:00 • @nyuszika7h, the +1 is the -p command line parameter, not a newline. – manatwork Aug 20 '14 at 12:16 • Oh right, sorry. – nyuszika7h Aug 20 '14 at 12:16 # Python (33) If in doubt, use the shell. import os;os.system('tr A-Z a-z')  Regrettably, this is still longer than Lego's solution. • +1 That is indeed not a Python built-in you are using. Only works on linux, but still very rule-bendy!!! – user8777 Oct 9 '13 at 3:31 • @LegoStormtroopr Works everywhere there is a tr command (which does the right thing) on the path of the invoked shell, I suppose. – Paŭlo Ebermann Oct 13 '13 at 9:41 DELPHI const UpChars:set of AnsiChar = ['A'..'Z']; var I: Integer; begin SetLength(Result, Length(pString)); for I := 1 to length(pstring) do Result[i] := AnsiChar((Integer(pString[i] in UpChars))*(Ord(pString[i])+32)); WriteLn(Result); end;  • This is not golf. Don't you feel this piece is very different compared to others ? – Ray Oct 8 '13 at 16:57 • @ray Golfing is about getting your code as short as possible. Delphi isnt a great language for golfing. I use delphi myself and even though there isnt a big chance I could win a golf with delphi, its still fun to challenge yourself. – Teun Pronk Feb 27 '14 at 7:59 ### JavaScript - 109 104 (ES6: 95) Thanks to some for the corrected version. a=prompt();for(b=[i=0];c=a.charCodeAt(i);)b[i++]=String.fromCharCode(c|(c>64&c<91)*32);alert(b.join(""))  The following works if the browser supports ES6 function expressions: alert(prompt().split("").map(c=>String.fromCharCode(c.charCodeAt()|(c>"@"&c<"[")*32)).join(""))  • The first code doesn't work (tested in FF and Chrome) because when trying to get a character after the length of the string, you get undefined and then c.charCodeAt() fails because undefined don't have charCodeAt. A working example 105 characters: a=prompt();for(b=[i=0];c=a.charCodeAt(i);)b[i++]=String.fromCharCode(c|(c>64&&c‌​<91)*32);alert(b.join('')) – some Dec 5 '13 at 13:29 • @some oops, I wonder how I came up with that snippet.. I'm pretty sure I tested that code, maybe I copied a non-working version in or something. Anyway, thanks for the correction. – FireFly Dec 5 '13 at 23:55 • Using a bitwise and instead of a logical one... nice! – some Dec 6 '13 at 0:10 • An even more ES6 solution (79): L=s=>[String.fromCharCode(c.charCodeAt()|(c>"@"&c<"[")*32)for(c of s)].join(''). Usage: L('SoMeTeXt') – Florent Feb 28 '14 at 15:07 • Nice! I'm not sure about making it a mere function though, since all other solutions are "proper" programs. Still, very nice use of for..of regardless. – FireFly Feb 28 '14 at 17:13 ### Perl 18 s/[A-Z]/$&|" "/eg


Something like:

perl -pe 's/[A-Z]/$&|" "/eg' <<<'are NOT allowed to: ToLower() in .NET, strtolower() in PHP' are not allowed to: tolower() in .net, strtolower() in php  and perl -pe 's/[A-Z]/$&|" "/eg' <<< "The input string Doesn't cOntaIn...( C0D3-@01F. ;-)"
the input string doesn't contain...( c0d3-@01f. ;-)


For @FireFly :

perl -pe 's/[A-Z]/$&|" "/eg' <<< "Doesn't this translate @ to \ and [\]^_ to {|}~DEL? " doesn't ... @ to  and [\]^_ to {|}~del?  no. ### More generic: 18 chars anyway: s/[A-Z]/$&|" "/eg


s/[A-Z]/$&^" "/eg  This wont change anything in state: perl -pe 's/[A-Z]/$&^" "/eg' <<< "Doesn't ... @ to \ and [\]^_ to {|}~DEL? "
doesn't ... @ to  and [\]^_ to {|}~del?


All work fine, but the advantage of changing | (or) by ^ (xor) is that the same syntax could be used for toLower, toUpper or swapCase:

toUpper:

perl -pe 's/[a-z]/$&^" "/eg' <<< "Doesn't ... @ to \ and [\]^_ to {|}~DEL? " DOESN'T ... @ TO  AND [\]^_ TO {|}~DEL?  and swapCase (18+1 = 19 chars): perl -pe 's/[a-z]/$&^" "/egi' <<< "Doesn't ... @ to \ and [\]^_ to {|}~DEL? "
dOESN'T ... @ TO  AND [\]^_ TO {|}~del?

• I forgot +1 for -p sorry @manatwork – F. Hauri Dec 4 '13 at 18:04
• Doesn't this translate @ to backtick and [\]^_ to {|}~DEL? And therein lies the tricky part.. – FireFly Dec 4 '13 at 18:15
• @FireFly No, $& have to match [A-Z]. – F. Hauri Dec 4 '13 at 18:19 • Oh, my bad. Very cool, then! – FireFly Dec 4 '13 at 20:56 ## javascript 80 "X".replace(/[A-Z]/g,function($){return String.fromCharCode($.charCodeAt()+32)})  (76 if you remove "X") with prompt and alert - 92 alert(prompt().replace(/[A-Z]/g,function($){return String.fromCharCode($.charCodeAt()+32)}))  fiddle thanks to @FireFly @some @C5H8NNaO4 and @minitech • Er, you'd need to wrap the second argument to replace with function($){return ...}, no? By the way, the first param to the replacement function is the matched string, so you could drop the parens in the regex. – FireFly Oct 7 '13 at 8:00
• How would i go about running it,like this? – C5H8NNaO4 Oct 7 '13 at 8:37
• @C5H8NNaO4 str(code here) – Math chiller Oct 7 '13 at 10:11
• I think all (or at least most) answers in here read from stdin and print to stdout. From what I gather the convention is to use prompt and alert for I/O in JS. – FireFly Oct 7 '13 at 14:17
• You need a /g flag for this to work properly. – Ry- Dec 7 '13 at 14:36

# 05AB1E, 3 bytes

u.š


Port of @user8777 Python 3 answer.

Try it online.

Explanation:

u    # Convert the (implicit) input to uppercase
.š  # Switch the case (upper to lower and vice-versa)
# (and output the result implicitly)


But without any case-altering builtins:

# 05AB1E, 12 11 bytes

ÇIS.u32*+çJ


-1 byte thanks to @Emigna.

Try it online.

Explanation:

Ç            # Get the unicode values of each character of the (implicit) input-String
IS          # Get the input-string, split to characters again
.u        # Check for each if it's uppercase or not (1 if truthy; 0 if falsey)
32*     # Multiply that result by 32 (32 if truhy; 0 if falsey)
+    # Add it to all the unicode values at the same indices in the list
ç   # Convert the now modified unicode values back to characters
J  # And join all characters together to a string again
# (which is output implicitly as result)

• ÇIS.u32*+çJ saves a byte on your 12-byte version. – Emigna Apr 9 '19 at 13:17
• @Emigna Ah, smart. I had tried the .u32*+ approach like this: εÇy.u32*+ç]J, but unfortunately ç wraps the characters in a list, so an additional J or  was required after the ç.. – Kevin Cruijssen Apr 9 '19 at 13:23

## R

### 71 characters:

chartr(paste(LETTERS,collapse=""),paste(letters,collapse=""),scan(,""))


### 83 characters:

a=as.integer(charToRaw(scan(,"")))
b=a%in%(65:90)
a[b]=a[b]+32
rawToChar(as.raw(a))

• That's 86 characters - newlines count as 2 characters. (string-functions.com/length.aspx) – Timtech Dec 8 '13 at 0:42
• @Timtech: In R you can replace newlines in code by ; so no they count just for one character. It could be written: a=as.integer(charToRaw(scan(,"")));b=a%in%(65:90);a[b]=a[b]+32;rawToChar(as.raw(a)) – plannapus Dec 9 '13 at 8:26
• Yes, now I realized. I read up on meta... seems that only on Windows that newlines are 2 characters (I was using a program to measure the length of my code). – Timtech Dec 9 '13 at 11:49

# Q, 18

.....

{x^ssr/[x]..QaA}


# Q (16)

.......

{x^(.Q.A!.Q.a)x}


## PHP (42)

Run from the command line:

-R'echo@str_ireplace($a=range(a,z),$a,$argn);'  -R and the single quotes are not counted. • If you follow Gowtham's Peal solution, you would only count 42 characters. – eisberg Oct 8 '13 at 12:04 • @eisberg: Updated the score, leaving a 43-character version in the history in case of any dispute. – PleaseStand Oct 8 '13 at 13:21 • str_ireplace does case insensitive search, which is stretching the rules, if not breaking them. – ugoren Oct 8 '13 at 13:55 • @ugoren I do not think so. As it is clearly stated that only build in function changing the case are not allowed and this is ignoring the case not changing it. – eisberg Oct 9 '13 at 13:24 ## PowerShell: 6965 64 I've tried a half-dozen ways to get Replace to work the way I want it to without using the long [regex]::Replace syntax, but I haven't had any luck. If anyone else has an idea of what might work, please do suggest it. Golfed code: [regex]::Replace((read-host),"[A-Z]",{[char](32+[char]"$args")})


Changes from original:

• Rearranged last argument so that [int] is no longer needed, per suggestion in comments.

Explanation:

(read-host) gets the user input.

[regex]::Replace(...) tells PowerShell to use RegEx matching to perform replacement operations on a string.

"[A-Z]" matches all uppercase letters.

{...} tells PowerShell to use a script to determine the replacement value.

[char]"$args" takes the current match and types it as an ASCII character. 32+ converts the character to an integer, representing the ASCII code, and increases the value by 32 - which would match ASCII code of the corresponding lowercase letter. [char](...) takes the resulting value and converts it back to an ASCII character. Demo of original: (Current version tested - screenshot not yet posted.) • Haven't checked on how to get around that [regex]::Replace, but you can save 4 chars by changing [int] to + – goric Dec 4 '13 at 21:19 • Actually, the whole last argument can be rearranged to {[char](32+[char]"$args")}, which removes the need to explicitly cast to int and shaves off one more character – goric Dec 4 '13 at 21:42
• @goric Geez, why didn't I think of that already? Still learning, I guess. – Iszi Dec 4 '13 at 21:53

# k2, 15 bytes

I am super late to this one, but I found this cool anyway.

{_ci 32+_ic x}'


Also:

# Pyth, 10 bytes

Doesn't really count because Pyth was created after this was posted. Still cool.

jkmC+32Cdw


# PowerShell, 5349 43 bytes

-6 bytes thanks @Veskah

-join($args|%{[char](32*($_-in65..90)+$_)})  Try it online! • cool! ¯\_(ツ)_/¯ – mazzy Sep 20 '18 at 16:43 • Splat it up for 43 – Veskah Jan 24 at 15:36 # Javascript, 105 prompt().split("").map(function(a){c=a.charCodeAt(0);return String.fromCharCode(c|(c-64?32:0))}).join("")  Actually ther was no output form specified, so run it in console Yea, JavaScript really is verbose with charcode <-> string • c.charCodeAt() -- it defaults to 0 if an index is omitted. Also, breaks on '@' I believe (it gets "lowercased" into backtick) – FireFly Oct 7 '13 at 7:42 • @FireFly Nice, Thanks!, ok i'll gonna fix it =) – C5H8NNaO4 Oct 7 '13 at 7:44 Ruby: 66 def l(s)s.bytes.map{|b|(65..90).include?(b)?b+32:b}.pack('c*');end  ## C# - 108 class P{static void Main(string[]a){foreach(var c in a[0])System.Console.Write( (char)(c>64&&c<91?c+32:c));}}  About 70 for just the method body. Add 5 chars to include a LF/CR in the output: class P{static void Main(string[]a){foreach(var c in a[0]+"\n")System.Console.Write( (char)(c>64&&c<91?c+32:c));}}  A LINQ version would be shorter: class P{static void Main(string[]a){a[0].Any(c=>System.Console.Write( (char)(c>64&&c<91?32+c:c))is P);}}  (103) .. except that it requires using System.Linq; (total: 121). # Haskell - 58 p x|(elem x['A'..'Z'])=[x..]!!32|1<2=x main=interact$map p


# Python 3 - 70

Updated for OP's changes.

I'm a Python newbie, so any critique is welcome.

print("".join(chr(ord(c)+32) if 64<ord(c)<91 else c for c in input()))

• I'm sorry, I had to say that you're not allowed to use a to-lower function on one character. Question updated. – ProgramFOX Oct 6 '13 at 15:19
• Please see my recent comment: your code does only work if the input string contains only uppercase characters, but please note that it also contain other ASCII characters such as lowercase characters and numbers. – ProgramFOX Oct 6 '13 at 15:22
• Okay, will update when I get home – asteri Oct 6 '13 at 16:58
• @ProgramFOX Updated. – asteri Oct 6 '13 at 17:34
• Jeff, check out @minitechs answer. You both have very similar approaches so you should be able to see how, and why his answer is shorter. – user8777 Oct 9 '13 at 3:32

## Perl, 9 + 1 (for -p flag) = 10

$_="\L$_"


\L was specifically asked about and allowed, because even though it's a built-in, it's not a function.

# x86-16 machine code, 14 bytes

Assembled:

ac3c 417c 063c 5a7f 020c 20aa e2f2


Unassembled listing:

       _LOOP:
3C 41      CMP  AL, 'A'    ; is char less than 'A'?
7C 06      JL   _STORE     ; if so, do not convert
3C 5A      CMP  AL, 'Z'    ; is char greater than 'Z'?
7F 02      JG   _STORE     ; if so, do not convert
0C 20      OR   AL, 020H   ; lowercase the char
_STORE:
AA         STOSB           ; store char to [DI], advance DI
E2 F2      LOOP _LOOP      ; continue loop through string


Input string in [SI], length in CX. Output string in [DI].

Output from PC DOS test program:

• @Jonah The byte opcode is in the lefthand column, AC 3C 41`, etc. I'll add the assembled hex byte code to the top for clarity. codegolf.meta.stackexchange.com/a/12340/84624 – 640KB Apr 9 '19 at 16:18