Lowercase, but not just the letters
Given a string of printable ASCII characters, convert them all to lowercase, except not just the letters.
ASCII characters that are letters have a bit in their binary representation that is 0
for uppercase, and 1
for lowercase. Setting this bit to 1
for a non-letter character that previously had it set to 0
results in it changing to a completely unrelated character, which for this challenge we will call the lowercase version of that character.
Input
- A sequence of characters, each of which is a printable ASCII character (character codes 32 to 126 inclusive)
- This may be a string or any ordered data structure of characters
- There will never be an underscore
_
(character code 95) as its lowercase version is character code 127, which is outside the printable range and used as a control character - Your code must work for inputs of up to 16 characters
Output
- A sequence of the same number of characters as the input
- This may be a string or any ordered data structure of characters. It does not need to match the input format (provided it is consistent between inputs)
- For example, you may take input as an array of characters, and output as a string, provided this format does not change for different inputs
- Each character is either the same as the input, if it was a lowercase version already, or otherwise the lowercase version of the input character
Examples
A letter
Character "A" is character code 65, or 1000001
in binary. The bit in position 5 from the right, representing $2^5$, is 0
. Setting this bit to 1
gives 1100001
, or 97, which is the character code for "a". So the lowercase version of "A" is "a", as expected.
A non-letter
Character "^" is character code 94, or 1011110
in binary. The bit in position 5 from the right, representing $2^5$, is 0
. Setting this bit to 1
gives 1111110
, or 126, which is the character code for "~". So the lowercase version of "^" is "~".
Test cases
Test cases are in the format "input" : "output"
Note that "
and \
have both been escaped with a preceding \
, because they are enclosed in double quotes, but each still represents a single character)
" " : " "
"!" : "!"
"\"" : "\""
"#" : "#"
"$" : "$"
"%" : "%"
"&" : "&"
"'" : "'"
"(" : "("
")" : ")"
"*" : "*"
"+" : "+"
"," : ","
"-" : "-"
"." : "."
"/" : "/"
"0" : "0"
"1" : "1"
"2" : "2"
"3" : "3"
"4" : "4"
"5" : "5"
"6" : "6"
"7" : "7"
"8" : "8"
"9" : "9"
":" : ":"
";" : ";"
"<" : "<"
"=" : "="
">" : ">"
"?" : "?"
"@" : "`"
"A" : "a"
"B" : "b"
"C" : "c"
"D" : "d"
"E" : "e"
"F" : "f"
"G" : "g"
"H" : "h"
"I" : "i"
"J" : "j"
"K" : "k"
"L" : "l"
"M" : "m"
"N" : "n"
"O" : "o"
"P" : "p"
"Q" : "q"
"R" : "r"
"S" : "s"
"T" : "t"
"U" : "u"
"V" : "v"
"W" : "w"
"X" : "x"
"Y" : "y"
"Z" : "z"
"[" : "{"
"\\" : "|"
"]" : "}"
"^" : "~"
"`" : "`"
"a" : "a"
"b" : "b"
"c" : "c"
"d" : "d"
"e" : "e"
"f" : "f"
"g" : "g"
"h" : "h"
"i" : "i"
"j" : "j"
"k" : "k"
"l" : "l"
"m" : "m"
"n" : "n"
"o" : "o"
"p" : "p"
"q" : "q"
"r" : "r"
"s" : "s"
"t" : "t"
"u" : "u"
"v" : "v"
"w" : "w"
"x" : "x"
"y" : "y"
"z" : "z"
"{" : "{"
"|" : "|"
"}" : "}"
"~" : "~"
"([({Enclosed})])" : "({({enclosed})})"
"A@B.c" : "a`b.c"
Rules
- There is no requirement to use bitwise operations to achieve the correct output
- Provided your output is correct for each test case input, your code is valid
Explanations are optional, but I'm more likely to upvote answers that have one.
[Python 3], 35 bytes …
2y ago
J, 15 bytes ``` 7 u:32 OR …
2y ago
[C (gcc)], 36 bytes …
2y ago
J, 39 char Solution: ``` …
2y ago
Japt, 3 bytes c|H Tr …
2y ago
APL (Dyalog APL), 42 bytes …
2y ago
JavaScript, 52 51 28 bytes …
2y ago
7 answers
Python 3, 35 bytes
lambda x:[chr(ord(i)|32)for i in x]
Performs a list comprehension on the input string; for each character it:
- transforms it into the ASCII character code integer representation using
ord()
- performs a
binary or
with32
(or0b100000
) to convert it to lower-case - transforms it back into a string representation using
chr()
Inputs as a string, outputs as a list
0 comment threads
J, 15 bytes
7 u:32 OR 3 u:]
Port of Shaggy's answers. Evaluates as 3 forks 7 u: (32 OR (3 u:]))
7 u:32 OR 3 u:]
] : right argument
3 u: : 3&u: converts a string to a list of char codes
32 OR : bitwise OR the result with 32
7 u: : 7&u: converts a list of char codes to a string
1 comment thread
J, 39 char
Solution:
(a.{~ a.((6|.8{.1)+.(_8&{.))&.#:"0@i.])
Test example:
(a.{~ a.((6|.8{.1)+.(_8&{.))&.#:"0@i.]) '([({Enclosed})])A@B.c'
({({enclosed})})a`b.c
How it works:
6|.8{.1 creates binary 0 0 1 0 0 0 0 0
_8&{. ensures that binari from ascii is 8 bit
(6|.8{.1)+.(_8&{.) makes third bit 1
a.((6|.8{.1)+.(_8&{.))&.#:"0@i. searches for text on right in character vector a.,...
...then converts to binary, then ensures third bit is 1, then, using &. reverses the binary
a.{~ converts the reversed binary, which is an ascii number, back to character text
1 comment thread
C (gcc), 36 bytes
f(int*p){for(;*p;putchar(32|*p++));}
Similar solutions:
- 36 bytes too but with new lines:
f(int*p){for(;*p;*p|=32,puts(p++));}
- 37 bytes using recursion:
f(int*p){*p&&putchar(32|*p)&&f(++p);}
APL (Dyalog APL), 42 bytes
{⎕UCS⊢2⊥1@2⊢(7⍴2)⊤⎕UCS⍵}
In APL, base encoding(⊤
) returns a matrix, so setting the lowercase bit is very easy with 1@2
, setting the entire second row to 1.
2 comment threads