38
\$\begingroup\$

The goal is, having taken a string as input, duplicate each latin letter and "toggle" its case (i.e. uppercase becomes lowercase and vice-versa).

Example inputs & outputs:

Input      Output
bad        bBaAdD
Nice       NniIcCeE
T e S t    Tt eE Ss tT
s E t      sS Ee tT
1!1!1st!   1!1!1sStT!
n00b       nN00bB     
(e.g.)     (eE.gG.)
H3l|@!     Hh3lL|@!

The input consists of printable ASCII symbols.

You shouldn't duplicate non-latin letters, numbers, special chars.

\$\endgroup\$
1
  • 19
    \$\begingroup\$ This is a very nice, simple-but-not-trivial challenge. \$\endgroup\$
    – user45941
    Jul 9, 2016 at 1:45

46 Answers 46

17
\$\begingroup\$

Python, 56 54 bytes

lambda s:''.join(c+c.swapcase()*c.isalpha()for c in s)

Test it on Ideone.

\$\endgroup\$
4
  • \$\begingroup\$ Dang! Out golfed me by 4 bytes... \$\endgroup\$
    – R. Kap
    Jul 8, 2016 at 20:57
  • \$\begingroup\$ How does this maintain the non-letter characters? I'd think they'd show up as empty strings. \$\endgroup\$ Jul 8, 2016 at 21:21
  • 1
    \$\begingroup\$ @atlasologist As you can see on Ideone, they do not. * has higher precedence than +, so it only affects the c with swapped case. \$\endgroup\$
    – Dennis
    Jul 8, 2016 at 21:22
  • \$\begingroup\$ Ohh, okay, I didn't think of it like that. Nice. \$\endgroup\$ Jul 8, 2016 at 21:24
16
\$\begingroup\$

JavaScript ES6, 70 68 66 64 bytes

Saved 2 bytes thanks to @Kevin Lau - not Kenny

Saved 2 bytes thanks to @Cᴏɴᴏʀ O'Bʀɪᴇɴ

s=>s.replace(/[A-Z]/gi,l=>l+l[`to${l<"a"?"Low":"Upp"}erCase`]())

Explanation

This uses a really hacky:

l[`to${l<"a"?"Low":"Upp"}erCase`]()

which ungolfed is:

l[`to${
   l < "a" ?
   "Low" : 
   "Upp"
}erCase`]()

Basically l < "a" checks if the code point of the letter is less then the code point of a (therefore being an uppercase letter). If it is it'll do to + Low + erCase which becomed l['toLowerCase']() and makes the character lowercase. ` quotes allow string formatting so essentially you can think of:

`to${l < "a" ?"Low" : "Upp"}erCase`

as: "to" + (l<"a" ? "Low" : "Upp") + "erCase" which generates the function to call (make the string upper or lower case). We put this in square brackets [ ... ] which lets us access a property given its name as a string. This returns the appropriate function and then we just call it.

\$\endgroup\$
6
  • 3
    \$\begingroup\$ /[A-Z]/gi is a shorter regex :3 \$\endgroup\$
    – Value Ink
    Jul 8, 2016 at 20:28
  • \$\begingroup\$ @KevinLau-notKenny oh nice catch, thanks! \$\endgroup\$
    – Downgoat
    Jul 8, 2016 at 20:29
  • 1
    \$\begingroup\$ to${l<"a"?"Lower":"Upper"}Case to to${l<"a"?"Low":"Upp"}erCase \$\endgroup\$ Jul 8, 2016 at 21:14
  • \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ oh nice, thanks! \$\endgroup\$
    – Downgoat
    Jul 8, 2016 at 21:38
  • 4
    \$\begingroup\$ l[`to${l<"a"?"Low":"Upp"}erCase`]() I think we have a new definition of evil. \$\endgroup\$
    – gcampbell
    Jul 9, 2016 at 11:53
12
\$\begingroup\$

Jelly, 5 bytes

żŒsQ€

Try it online!

How it works

żŒsQ€  Main link. Argument: s (string)

 Œs    Yield s with swapped case.
ż      Zip s with the result.
   Q€  Unique each; deduplicate each pair of characters.
\$\endgroup\$
0
10
\$\begingroup\$

Ruby, 37 33 (30 + -p flag) bytes

swapcase to the rescue! Sort of. -4 bytes from @Lynn.

gsub(/[a-z]/i){$&+$&.swapcase}
\$\endgroup\$
2
  • \$\begingroup\$ gsub(/[a-z]/i){$&+$&.swapcase} plus the p flag is 31 bytes. \$\endgroup\$
    – Lynn
    Jul 8, 2016 at 22:54
  • 1
    \$\begingroup\$ @Lynn I believe consensus was edit difference needed from default script, so the p flag is (space)-p aka 3 bytes. \$\endgroup\$
    – Value Ink
    Jul 8, 2016 at 23:16
8
\$\begingroup\$

C, 63 60 bytes

f(char*s){for(;*s;s++)isalpha(putchar(*s))&&putchar(32^*s);}

Uses the fact that 'a' XOR 32 == 'A', etc.

Three bytes saved thanks to FryAmTheEggman.

\$\endgroup\$
5
  • \$\begingroup\$ you can move the s++ in the last putchar (&&putchar(32^*s++)) to save one byte \$\endgroup\$ Jul 11, 2016 at 13:43
  • \$\begingroup\$ I think you can replace && with *, can't you? \$\endgroup\$
    – aloisdg
    Jul 16, 2016 at 18:13
  • 1
    \$\begingroup\$ I’m pretty sure both of those don’t work, if I think about how &&’s short-circuiting behaviour works. \$\endgroup\$
    – Lynn
    Jul 16, 2016 at 20:13
  • \$\begingroup\$ f(char*s){isalpha(putchar(*s))&&putchar(32^*s);*s&&f(1+s);} recursive? \$\endgroup\$
    – l4m2
    Mar 19, 2018 at 4:23
  • 1
    \$\begingroup\$ f(char*s){*s&&f(1+s,isalpha(putchar(*s))&&putchar(32^*s));} recursive? \$\endgroup\$
    – l4m2
    Mar 24, 2018 at 6:29
6
\$\begingroup\$

CJam, 11 bytes

l_el_eu.+.|

Test it here.

Explanation

l      e# Read input.
_el    e# Duplicate, convert to lower case.
_eu    e# Duplicate, convert to upper case.
.+     e# Concatenate the two characters in matching positions from those two
       e# strings. E.g. "ab!" "AB!" would give ["aA" "bB" "!!"].
       e# For each character from the original string and the corresponding 
.|     e# string from this list, take the set union (which eliminates duplicates
       e# and keeps the order the values appear in from left to right, so that
       e# the original case of each letter comes first).
\$\endgroup\$
5
\$\begingroup\$

Pyth, 7 bytes

sm{+dr2

Test suite.

sm{+dr2    input: Q
sm{+dr2dQ  implicit arguments

        Q  input
 m         for each character as d:
     r2d       swapcase
   +d          prepend d
  {            deduplicate
s          join as string
\$\endgroup\$
1
  • \$\begingroup\$ Haha, that's really fast :D \$\endgroup\$
    – nicael
    Jul 8, 2016 at 20:18
5
\$\begingroup\$

Python 3.5, 60 56 bytes:

for i in input():print(end=i+i.swapcase()[:i.isalpha()])

A full program. Will try to golf more.

Try It Online! (Ideone)

\$\endgroup\$
5
\$\begingroup\$

Haskell, 73 bytes

l=['a'..'z']
u=['A'..]
(>>= \c->c:maybe""pure(lookup c$zip l u++zip u l))
\$\endgroup\$
5
\$\begingroup\$

Cheddar, 118 104 bytes

(s)->s.chars.map((i)->{if String.letters has i.lower{if i<"a"{i+i.lower}else{i+i.upper}}else{i}}).join()

First real Cheddar answer!!! This is a lot less climactic than I thought it would be... ;_;

Works with release 1.0.0-beta.9, non-competing.


As you can tell I didn't design cheddar to be golfy :/

Ungolfed:

(str) -> str.chars.map(
    (i) -> {
        if String.letters has i {
            if i < "a" { // Check char code, meaning it's upper case if true
                i+i.lower
            }
            else {
                i+i.upper
            }
        } else {
            i
        }
    }
).join()

Usage:

var doThing = <code here>;
doThing("input...");

Update: 7/14/16 I've finished ternaries making this come down to 84 bytes

Cheddar, 84 bytes

(s)->s.chars.map((i)->String.letters has i.lower?i<"a"?i+i.lower:i+i.upper:i).join()

works as of version v1.0.0-beta.14

\$\endgroup\$
7
  • 4
    \$\begingroup\$ Yay! We've been waiting for this moment for a long time! \$\endgroup\$
    – DJMcMayhem
    Jul 10, 2016 at 18:39
  • \$\begingroup\$ With one or two method name changes, is also valid Sidef \$\endgroup\$
    – cat
    Jul 10, 2016 at 21:11
  • \$\begingroup\$ @cat o_o the similarity is unsettling \$\endgroup\$
    – Downgoat
    Jul 10, 2016 at 21:13
  • \$\begingroup\$ Well, they're both influenced by Perl, Perl 6, Ruby, Python, etc, so it's not that surprising :P \$\endgroup\$
    – cat
    Jul 10, 2016 at 21:32
  • 1
    \$\begingroup\$ @cat oh no no no no no, cheddar was not influenced by python \$\endgroup\$
    – Downgoat
    Jul 10, 2016 at 21:33
4
\$\begingroup\$

Retina, 28 27 21 bytes

Those are tabs, not spaces.

.
$&  $&
T`lL    p`Ll_`  .

Try it online

Thanks for the suggestions everyone.

\$\endgroup\$
8
  • \$\begingroup\$ The spaces are eaten by SE. \$\endgroup\$ Jul 8, 2016 at 20:25
  • \$\begingroup\$ [A-Za-z] -> i`[A-Z] \$\endgroup\$
    – Downgoat
    Jul 8, 2016 at 20:36
  • \$\begingroup\$ Martin and I were talking in chat, and we came up with: retina.tryitonline.net/… \$\endgroup\$ Jul 8, 2016 at 20:41
  • \$\begingroup\$ @FryAmTheEggman Ah, I forgot about _. I'm going to use tabs so I can test all test cases at once, though. \$\endgroup\$
    – mbomb007
    Jul 8, 2016 at 20:45
  • 1
    \$\begingroup\$ But the test suite doesn't have to be golfed :P Just leaving a note saying "the first line makes it run separately on each line" is usually good enough. Here, it would save you the craziness of tab characters. \$\endgroup\$ Jul 8, 2016 at 21:44
4
\$\begingroup\$

C, 87 80

Pass a string as input to f() and the output is written to STDOUT. The string is not modified.

f(char*v){for(;*v;++v)putchar(*v),isalpha(*v)?putchar(*v-32+64*!islower(*v)):0;}
\$\endgroup\$
2
  • \$\begingroup\$ Can you provide a way to try it online? \$\endgroup\$
    – aloisdg
    Jul 9, 2016 at 13:58
  • \$\begingroup\$ @aloisdg Try ideone.com \$\endgroup\$
    – cat
    Jul 10, 2016 at 1:52
4
\$\begingroup\$

sed, 30 bytes

29 bytes code + 1 byte parameter -r

s/([a-z])|([A-Z])/&\u\1\l\2/g

Usage:

echo -e 'bad\nNice\nT e S t\ns E t\n1!1!1st!\nn00b\n(e.g.)\nH3l|@!' |\
sed -r 's/([a-z])|([A-Z])/&\u\1\l\2/g'
\$\endgroup\$
4
\$\begingroup\$

J, 31 29 bytes

[:;]<@~."1@,.tolower,.toupper

Explanation

[:;]<@~."1@,.tolower,.toupper  Input: s
                      toupper  Convert s to all uppercase
             tolower           Convert s to all lowercase
                    ,.         Join them as columns in a 2d array
   ]                           Identity function, get s
           ,.                  Prepend s as a column to the 2d array
      ~."1@                    Take the unique chars on each row
    <@                         Box them
[:;                            Unbox the list of boxes and join their contents and return
\$\endgroup\$
4
\$\begingroup\$

Haskell, 121, 101, 85, 82

import Data.Char
g n|isLower n=toUpper n|1<2=toLower n
(>>= \x->x:[g x|isAlpha x])
\$\endgroup\$
4
  • 3
    \$\begingroup\$ By replacing the if-then-else by guards, you can save 15 bytes or so. And isLower is shorter than the construct with elem, for 5 bytes more. \$\endgroup\$
    – arjanen
    Jul 9, 2016 at 6:00
  • 1
    \$\begingroup\$ >>= is concatMap (or concat.map) with arguments flipped: f n = n >>= (\x->if isAlpha x then[x,r x]else[x]). You can go pointfree and omit the function name and replace the definition of f with (>>= \x->if isAlpha x then[x,r x]else[x]). \$\endgroup\$
    – nimi
    Jul 9, 2016 at 18:40
  • 1
    \$\begingroup\$ Instead of otherwise you can use any expression that evaluates to True, e.g. 1<2. You can replace the if .. then .. else with a list comprehension: \x->[x]++[g x|isAlpha x]. Oh, and there's a bug: the second toUpper in g must be a toLower. \$\endgroup\$
    – nimi
    Jul 11, 2016 at 16:36
  • 1
    \$\begingroup\$ Oh, one more: [x]++ is x:. \$\endgroup\$
    – nimi
    Jul 11, 2016 at 17:57
4
\$\begingroup\$

Perl, 36 bytes (35 + -n flag)

s/[a-z]/$&.(ord$&<97?lc$&:uc$&)/ige

(-p tag needed)

(-2 bytes thanks to @Dom Hasting)

Short explanation:
ord returns the numeric value of a char. ord(any lower case) >= 97, and ord(any upper case) <= 90).

Run with :

perl -pe 's/[a-z]/$&.(ord$&<97?lc$&:uc$&)/ige'
\$\endgroup\$
3
  • \$\begingroup\$ You still need to use /i or your regexp will match several codepoints between letters. \$\endgroup\$ Jul 12, 2016 at 0:14
  • \$\begingroup\$ @OlegV.Volkov oh right, thanks, answer edited. \$\endgroup\$
    – Dada
    Jul 12, 2016 at 10:31
  • \$\begingroup\$ Got it down one more byte, using your method: Try it online! \$\endgroup\$
    – Xcali
    Apr 3, 2018 at 3:20
4
\$\begingroup\$

Ruby, 31+1=32 30+1=31 bytes

With the -p flag, run

gsub(/(?<=(.))/){$1.swapcase!}

Takes advantage of the fact that swapcase! will return nil on anything but an ASCII letter, which translates to an empty string when returned out of the gsub block. @Jordan saved a byte by capturing the previous character in a look-behind.

\$\endgroup\$
6
  • \$\begingroup\$ Matching with // and then using $`[-1] is clever. \$\endgroup\$
    – Jordan
    Aug 29, 2016 at 14:55
  • 1
    \$\begingroup\$ I managed to shave off six bytes with lookbehind: gsub(/(?<=(.))/){$1.swapcase!}. Same basic concept, though, so feel free to use it. \$\endgroup\$
    – Jordan
    Aug 29, 2016 at 15:13
  • \$\begingroup\$ Cool! That looks one byte shorter to me. \$\endgroup\$
    – histocrat
    Aug 29, 2016 at 15:58
  • \$\begingroup\$ Er, yes, one byte. I think I had some extra code in there to test that I accidentally counted. \$\endgroup\$
    – Jordan
    Aug 29, 2016 at 16:08
  • \$\begingroup\$ There is no need to use the self-modifying version of .swapcase!. (I mean, remove the !.) \$\endgroup\$
    – manatwork
    Aug 29, 2016 at 16:19
4
\$\begingroup\$

R, 191 187 168 156 98 99 bytes

99 bytes due to improvements fro Giuseppe and MickyT.

paste0(x<-unlist(strsplit(readline(),"")),gsub("[^A-Za-z]","",chartr("a-zA-Z","A-Za-z",x)),collapse="")
\$\endgroup\$
5
  • \$\begingroup\$ 98 bytes -- maybe sometime next year, we can find another golf of this, hahaha. \$\endgroup\$
    – Giuseppe
    Mar 23, 2018 at 19:54
  • 1
    \$\begingroup\$ I hate to be the bearer of bad new, but it fails on test cases with spaces. readline() can be used, but it will cost a byte \$\endgroup\$
    – MickyT
    Apr 2, 2018 at 23:15
  • \$\begingroup\$ @MickyT thanks, fixed now. \$\endgroup\$
    – rturnbull
    Apr 2, 2018 at 23:28
  • \$\begingroup\$ @MickyT scan will work with input given wrapped in quotes (as is often the case for command-line arguments in other languages) \$\endgroup\$
    – Giuseppe
    Apr 3, 2018 at 0:46
  • \$\begingroup\$ @Giuseppe Sorry I didn't realise that. I just thought it automatically split on whitespace unless you specify a non whitespace character. Sorry rturnbull \$\endgroup\$
    – MickyT
    Apr 3, 2018 at 7:03
3
\$\begingroup\$

05AB1E, 7 bytes

Code:

vyyš«Ù?

Explanation:

v       # For each in input.
 yyš    # Push y and y swapcased.
    «Ù  # Concatentate and uniquify.
      ? # Print without a newline.

Uses the CP-1252 encoding. Try it online!

\$\endgroup\$
6
  • \$\begingroup\$ Maybe you could provide a link to the interpreter? \$\endgroup\$
    – nicael
    Jul 8, 2016 at 20:39
  • 2
    \$\begingroup\$ @nicael It IS linked... It's right there on github. \$\endgroup\$
    – mbomb007
    Jul 8, 2016 at 20:39
  • \$\begingroup\$ So no online interpreter? :( \$\endgroup\$
    – nicael
    Jul 8, 2016 at 20:42
  • \$\begingroup\$ @nicael Then download it, and run it. There doesn't have to be an online interpreter, just an interpreter. \$\endgroup\$
    – mbomb007
    Jul 8, 2016 at 20:42
  • 1
    \$\begingroup\$ @nicael Yeah, there is no online interpreter available yet :(. The offline version should work though. \$\endgroup\$
    – Adnan
    Jul 8, 2016 at 20:42
3
\$\begingroup\$

Pyke, 8 6 bytes

FDl4+}

Try it here!

\$\endgroup\$
3
\$\begingroup\$

V, 21 bytes

Try it online!

Too many bytes...

Ó./°ò
Íá/°°
Îlg~lÎHògJ
\$\endgroup\$
3
\$\begingroup\$

Actually, 8 bytes

`;Öo╔`MΣ

Try it online!

Explanation:

`;Öo╔`MΣ
`;Öo╔`M   for each character in input:
 ;          duplicate the character
  Ö         swap case
   o        append to original character
    ╔       remove duplicated characters
       Σ  concatenate
\$\endgroup\$
3
\$\begingroup\$

MATL, 11 9 bytes

tYov"@uv!

Try it Online

Explanation

        % Implicitly grab input as string
t       % Duplicate the input
Yo      % Swap case of all characters
v       % Vertically concatenate the original and swap-cased versions
"       % For each column (letter in the original)
  @u    % Compute the unique values (without sorting)
  v!    % Vertically concatenate with the existing output and transpose
        % Implicit end of for loop and implicit display
\$\endgroup\$
3
\$\begingroup\$

Common Lisp (Lispworks), 262 bytes

(defun f(s)(let((b""))(dotimes(i(length s))(if(lower-case-p(elt s i))(progn #1=(setf b(concatenate 'string b(string #2=(elt s i))))(setf b(concatenate 'string b(string(char-upcase #2#)))))(progn #1#(setf b(concatenate 'string b(string(char-downcase #2#)))))))b))

ungolfed:

(defun f (s)
  (let ((b ""))
    (dotimes (i (length s))
      (if (lower-case-p (elt s i))
          (progn
           #1=(setf b (concatenate 'string b (string #2=(elt s i))))
           (setf b (concatenate 'string b (string (char-upcase #2#)))))
        (progn
          #1#
          (setf b (concatenate 'string b (string (char-downcase #2#)))))))
    b))

Usage:

CL-USER 1 > (f "abc")
"aAbBcC"

CL-USER 2 > (f "bad")
"bBaAdD"
\$\endgroup\$
3
  • \$\begingroup\$ This might be smaller if the input is coerced into a list and append is used instead of (concatenate 'string ...) \$\endgroup\$
    – Wezl
    Jun 25, 2020 at 21:18
  • \$\begingroup\$ Invalid because It duplicates spaces. :r \$\endgroup\$
    – Wezl
    Jun 25, 2020 at 21:33
  • \$\begingroup\$ You can (coerce (apply 'nconc (map... over string where map collects a list of list of chars. I reduced it to 162 bytes Try It Online \$\endgroup\$
    – Thun_A
    Jul 3, 2021 at 17:21
3
\$\begingroup\$

Perl, 28 22 21 bytes (20 + -p flag)

s/[a-z]/$&.$&^$"/ige
\$\endgroup\$
4
  • \$\begingroup\$ I imagine you can save a byte by using $" instead of ' ', but I haven't tested. \$\endgroup\$
    – msh210
    Jul 14, 2016 at 22:11
  • \$\begingroup\$ @msh210, nice! How could I forget to check perlvar for default strings? Thanks! \$\endgroup\$ Jul 15, 2016 at 11:08
  • \$\begingroup\$ Not sure if it's a version change or something, but it seems . has higher precedence than ^ resulting in slightly wrong output, but you can combine \K and capturing match for the 19 bytes and valid output: Try it online! \$\endgroup\$ Jun 25, 2020 at 21:06
  • \$\begingroup\$ Just realised you don't need to /i any more with \pl for another -1! \$\endgroup\$ Jun 25, 2020 at 21:16
3
\$\begingroup\$

Stax, 7 6 bytes

Thanks to @recursive for a byte saved!

┤§ÆP♦■

Run and debug it at staxlang.xyz! (link is to unpacked version)

Unpacked (7 bytes):

c:~\{um

Explanation:

c:~\{um
c          Copy the top element of the stack (the input, in this case).
 :~        Switch case of each letter in the copy.
   \       Zip. This produces an array of two-character strings.
    { m    Map a block over this array of two-character strings.
     u       Get all unique elements.
           Implicit concatenate and print.
\$\endgroup\$
4
  • \$\begingroup\$ Thanks for giving stax a try. One easy improvement you can make is to use u instead of :g. It will get all the unique elements in an array, which is exactly what you want in this case. Other than that, this looks well golfed. \$\endgroup\$
    – recursive
    Mar 28, 2018 at 22:29
  • \$\begingroup\$ @recursive Thanks! Forgot about that one :/ Will edit in soon. \$\endgroup\$ Mar 29, 2018 at 4:29
  • \$\begingroup\$ Doesn't work for 123. You may need to change the format for all inputs (i.e. quote them). The link is also broken. You need to replace m=11 with m=2. There is a PPCG post generating button on staxlang.xyz so you may want to use that one. \$\endgroup\$ Apr 2, 2018 at 23:21
  • \$\begingroup\$ @WeijunZhou Thanks, fixed! \$\endgroup\$ Apr 3, 2018 at 0:48
2
\$\begingroup\$

Python, 59 bytes

lambda s:''.join((x,x+x.swapcase())[x.isalpha()]for x in s)

Edited to fix repeating non-alphabetic characters

\$\endgroup\$
0
2
\$\begingroup\$

Julia, 40 bytes

!s=[print(c,isalpha(c)?c$' ':"")for c=s]

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ not s is (list comprehension) okay, Julia... \$\endgroup\$
    – cat
    Jul 10, 2016 at 0:36
2
\$\begingroup\$

PHP 4.1, 57 bytes

This code assumes access through a web server (Apache, for example), using the default configuration.

You can pass the string by sending the key S by any means (POST, GET, COOKIE, SESSION...).

<?for($i=0;$c=$S[$i++];)echo$c,ctype_alpha($c)?$c^' ':'';
\$\endgroup\$
2
\$\begingroup\$

C#, 82 71 bytes

s=>string.Concat(s.Select(c=>c+(char.IsLetter(c)?(char)(c^32)+"":"")));

C# lambda where the input and the output are string. Try it online.

11 bytes thanks to @Lynn trick.

\$\endgroup\$

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.