# Swap capitalization of two strings

your shift key is broken. wheNever you type two lines, the cApitaL
LetteRs in them get swappeD. you must write a program to fiX THIS!

## Description

The input is two strings, s1 and s2, equal in length. They will each contain only printable ASCII and be at least one character in length. You may input these as two strings, an array of two strings, or a single string with s1 and s2 separated by either a tab or newline.

The output is the following:

• For each character c in s1:

• If the character is not a letter, output it unchanged.

• Otherwise, if c is a letter:

• Find the matching character (the one at the same index) in s2.

• If it is a capital letter, output c capitalized.

• If it is a lowercase letter, output c in lowercase.

• Otherwise, output c unchanged.

• Then do the same thing, except with s1 and s2 switched.

Essentially, all letters in s1 for which the matching character in s2 is capital should be capitalized, and all letters in s1 with a lowercase letter at the same index in s2 should become lowercase (and vice versa).

## Test cases

Input:

ABCDEfghijKlMnOpqrstuvwxyz
aaaaaaaaaaaaaaaa----------


Output:

abcdefghijklmnopqrstuvwxyz
AAAAAaaaaaAaAaAa----------


Input:

PRogrammiNG puzZLes & CODe golf


Output:

Programming Puzzles & Code Golf


Input:

AAAbbb111
Cc2Dd3Ee4


Output:

AaABbb111
CC2dd3Ee4

• I cannot for the life of me figure out how this could be caused by a broken shift key, but who am I to argue with the almighty Doorknob? :P – Geobits Jul 27 '15 at 5:12
• Does the input have to be on the same line? Or can I use some other character (a tab?) to separate them? – kirbyfan64sos Jul 27 '15 at 15:11
• @Dennis No, the input must be provided as shown in the question. – Doorknob Jul 27 '15 at 16:04
• @kirbyfan64sos You may take either two strings, an array of strings, or two strings separated by either a tab or a newline. I'll edit that into the question. – Doorknob Jul 27 '15 at 16:05
• is a trailing newline allowed? – Downgoat Jul 27 '15 at 16:06

# Pyth, 19 18 bytes

LCmrW&@dG@drG1d2Cb


This defines a function y that accepts and return a list of strings.

Verify all test cases at once in the Pyth Compiler/Executor.

Thanks to @Jakube for golfing off 1 byte.

### How it works

                   " (implicit) Initialize G to 'abcdefghijklmnopqrstuvwxyz'.

L                  " Define y(b):
Cb "   Zip to turn the two strings into an array of char pairs.
m                "   Map (implicit variable d):
@dG          "     Intersect d with G.
@drG1     "     Intersect d with G.upper().
W&             "     If both are non-empty:
r          d2   "       Apply swapcase() to d.
C                 "   Zip to turn the character pairs back into two strings.


# CJam, 25 bytes

{z{_el_eu&\__:^32&f^?}%z}


This is an anonymous function that pops an array of strings from the stack and leaves one in return.

In supported browsers, you can verify all test cases at once in the CJam interpreter.

### Test cases

Code

qN/2/                     e# Read input and split into arrays of two strings.

{z{_el_eu&\__:^32&f^?}%z}

%                         e# Map the block over all string arrays.
:+N*                      e# Separate the strings by linefeeds.


Input

ABCDEfghijKlMnOpqrstuvwxyz
aaaaaaaaaaaaaaaa----------
PRogrammiNG puzZLes & CODe golf
AAAbbb111
Cc2Dd3Ee4


Output

abcdefghijklmnopqrstuvwxyz
AAAAAaaaaaAaAaAa----------
Programming Puzzles & Code Golf
AaABbb111
CC2dd3Ee4


### How it works

z                       e# Zip to transform the array of strings into an array
e# of character pairs.
{                  }%  e# For each character pair:
_el                   e#   Push a copy and convert to lowercase.
_eu                e#   Push a copy and convert to uppercase.
&               e#   Intersect. The result will be an empty string if
e#   and only if both characters are letters.
\              e#   Swap the character pair on top of the stack.
__            e#   Push two copies.
:^          e#   XOR both characters.
32&       e#   Logical AND with 32. This pushes 32 for letters of
e#   different cases and 0 for letters of the same case.
f^     e#   XOR each character with the result.
?    e#   Select the original copy for non-empty intersection
e#   and the modified one otherwise.
z e# Zip to turn the characters pairs back into two strings.


# C, 126 bytes

This is my first attempt at a code golf, ever. Let me know if I did anything wrong.

I'm using bitwise operations to perform the switching

Golfed:

main(u,a,s,t)char**a,*s,*t;{for(s=a[1],t=a[2];*t;s++,t++)isalpha(*s)*isalpha(*t)?u=(*t^*s)&32,*t^=u,*s^=u:0;*s=10;puts(a[1]);}


Ungolfed:

main(u,a,s,t) char**a,*s,*t; {       // K&R style arguments
for(s=a[1],t=a[2];*t;s++,t++)    // initialize loop.
isalpha(*s) * isalpha(*t) ? // ensure both characters are letters (if)
u = (*t^*s) & 0x20,      // check if characters have swapped case
*t^=u,                   // if so, xor the bit which represents case
*s^=u                    // for both characters in the string.
:0;                          // end ternary statement (endif)
*s=10;                           // replace null terminator in first string
puts(a[1]);                      // with newline. This allows both output to
}                                    // be printed out all at once


edit: replaced && with *

# SQL (PostGreSQL), 427 Bytes

Despite it's huge size, this ended up being quite a bit smaller than I expected. I wasn't quite sure I was going to be able to do it to be honest. I suspect there is a lot that still can be done:)

CREATE FUNCTION F(TEXT,TEXT)RETURNS TABLE(S TEXT) AS'SELECT unnest(array[string_agg(CASE WHEN T~''[A-Z]''THEN upper(S)WHEN T~''[a-z]''THEN lower(S)ELSE S END,''''),string_agg(CASE WHEN S~''[A-Z]''THEN upper(T)WHEN S~''[a-z]''THEN lower(T)ELSE T END,'''')])FROM(SELECT ROW_NUMBER()OVER()N,S FROM regexp_split_to_table($1,'''')X(S))A JOIN(SELECT ROW_NUMBER()OVER()M,T FROM regexp_split_to_table($2,'''')Y(T))B ON N=M'LANGUAGE SQL


Formatted and commented

-- Declare the function spec
CREATE FUNCTION F(TEXT,TEXT)RETURNS TABLE(S TEXT) AS
'SELECT unnest(   -- turns array into a table
array[        -- build array of the column results
string_agg( -- Aggregate the result into a string
CASE
WHEN T~''[A-Z]''THEN upper(S) -- uppercase it if corresponding char is uppercase
WHEN T~''[a-z]''THEN lower(S) -- lowercase it if corresponding char is lowercase
ELSE S END
,''''),
string_agg( -- Same as the previous but swap strings
CASE
WHEN S~''[A-Z]''THEN upper(T)
WHEN S~''[a-z]''THEN lower(T)
ELSE T END
,'''')
])
FROM
-- split the first string
(SELECT ROW_NUMBER()OVER()N,S FROM regexp_split_to_table($1,'''')X(S))A JOIN -- split the second string (SELECT ROW_NUMBER()OVER()M,T FROM regexp_split_to_table($2,'''')Y(T))B
ON N=M
'
LANGUAGE SQL


Test run

SELECT F(A,B) AS Result
FROM (VALUES
('AAAbbb111', 'Cc2Dd3Ee4'),
('ABCDEfghijKlMnOpqrstuvwxyz', 'aaaaaaaaaaaaaaaa----------'),
('PRogrammiNG puzZLes & CODe golf', 'SdlkhkfaladlKsdlalksdg7ldklDgsl')
)A(A,B)

Result
-----------------------------
AaABbb111
CC2dd3Ee4
abcdefghijklmnopqrstuvwxyz
AAAAAaaaaaAaAaAa----------
Programming Puzzles & Code Golf


# Julia, 140 bytes

f(s,t)=(C(x,y)=(i=0;z="";for c=x i+=1;z*=string(isalpha(c)?isupper(y[i])?uppercase(c):islower(t[i])?lowercase(c):c:c)end;z);(C(s,t),C(t,s)))


This creates a function that accepts two strings and returns a tuple of strings. Nothing particularly clever is going on here; we simply define an inner function that directly implements the algorithm in the spec and call it twice.

Ungolfed:

function f(s, t)
C(x, y) = begin
i = 0
z = ""
for c in x
i += 1
if isalpha(c)
if isupper(y[i])
z *= string(uppercase(c))
elseif islower(y[i])
z *= string(lowercase(c))
else
z *= string(c)
end
else
z *= string(c)
end
end
return z
end

return (C(s, t), C(t, s))
end


# JavaScript ES6, 128 108 bytes

s=(a,b,t)=>[...a].map((l,i)=>/[^a-z]/.exec(b[i])?l.toUpperCase():l.toLowerCase()).join+(t?'':
+s(b,a,1))


JavaScript's toUpperCase() and toLowerCase() take up a lot of bytes but String.fromCharCode() is even longer

• This doesn't account for the condition where a character in s2 is not a letter and the corresponding character in s1 is uppercase. In this case, c in s1 must be returned unchanged. – c.P.u1 Jul 27 '15 at 12:16
• @c.P.u1 I've addressed that :) – Downgoat Jul 27 '15 at 15:04

## Mathematica, 173169 155 bytes

f=0>1;t=!f;c=Characters;u=ToUpperCase;StringJoin/@MapThread[#@#2&,{Reverse[{LetterQ@#,#==(u@#)}&/@c@#/.{{f,_}->(#&),{t,t}->u,{t,f}->ToLowerCase}&/@#],c/@#},2]&


This is a function taking an array of two strings, e.g. {"Foo","bAR"} and outputting an array of two strings. Un-spatially-compressing it, rewriting the scheme f@x as f[x] wherever it appears, expanding the notation abbreviations (f=0>1 a.k.a. False,t=!f a.k.a. True, c=Characters, and u=ToUpperCaseQ), and un-replacing UpperCaseQ[#] with #==u@# (this character equals its uppercased version), it is:

StringJoin /@ MapThread[#[#2] &, {
Reverse[
{ LetterQ[#], UpperCaseQ[#] } & /@ Characters[#] /.
{ {False, _} -> (# &), {True, True} -> ToUpperCase,
{True, False} -> ToLowerCase } & /@ #
],
Characters /@ #
}, 2] &


Interfacing: the trailing & makes this a function. Its argument is inserted as the "#" at both instances of /@ #. For instance f=0>1; ... & [{"AAAbbb111", "Cc2Dd3Ee4"}] produces the output {AaABbb111,CC2dd3Ee4}.

Processing: Told in usual outside in order:

• The output of the MapThread[...] is a list of two lists of characters. StringJoin is applied to each of these two lists of characters to produce a list of two strings, the output.
• MapThread[#[#2]&, ... , 2] acts on an array of two 2-by-n element lists. The first list is a 2-by-n array of functions. The second list is a 2-by-n array of characters, Characters /@ #, the lists of characters in the two input strings. It works at depth 2, i.e., on the functions and individual characters.
• Reverse[...] swaps the two sublists of functions so that MapThread will apply the second string's functions to the first string and vice versa.
• { ... } & is an anonymous function that is applied to each of the two input strings.
• {LetterQ[#], UpperCaseQ[#]} & /@ Characters[#] splits a string into a list of characters, then replaces each character with two element lists. In these two element lists, the first element is True if the character is a letter and False otherwise, similarly, the second element indicates whether the character is upper case. UpperCaseQ[] cannot return true if it does not receive a letter.
• /. {{False, _} -> (# &), {True, True} -> ToUpperCase, {True, False} -> ToLowerCase} replaces these two element lists with functions. (Expansion of the abbreviations t and f occurs before any matching is attempted.) If a two element list has False as its first element, it is replaced with the function (# &), the identity function. (The parentheses are necessary, otherwise the arrow binds more tightly than the ampersand.) Otherwise the two element list starts with True, the character was a letter, and we output the functions ToUpperCase and ToLowerCase corresponding to its case. (Checking for this last False is unnecessary, in fact {_,_}->ToLowerCase would work, catching anything that hadn't been replaced yet, but this would be no shorter and more obscure.)

The only challenge was figuring out a succinct way to zip a two dimensional array of functions to an array of arguments.

Edit: Thanks to @Martin Büttner for catching "helpful" cut/paste linebreak backslashes, the 1>0 and 1<0 abbreviations, and also for the guidance to count length in bytes not characters (whatever those are :-) )

Edit2: Further thanks to @Martin Büttner for pointing out that polluting the global namespace is acceptable golf, reminding me of one character function application, and suggesting replacing the two uppercase functions with an abbreviation for one and using the one to emulate the other (saving four characters). (I think he's done this before. :-) )

• More golfitude: use f@g instead of f[g] (throughout your code). I'm also quite sure you don't need a block. Just do (f=0>1;t=!f;c=Characters;StringJoin/@...)&. This pollutes the global namespace, but we're totally fine with that when golfing. Also, I haven't counted, but you might be able to save bytes by storing ToUpperCase in a variable (u, say) and replacing UpperCaseQ@# with #==u@#. – Martin Ender Jul 27 '15 at 22:52

# Python 3, 131 bytes

def j(s,g):p=lambda s,g:''.join(i.upper()if j.istitle()else i.lower()if j.islower()else i for i,j in zip(s,g));return p(s,g),p(g,s)


Function returns strings in a tuple

• @mbomb007 May I ask the point of editing my post? In my opinion strikethroughs are messy, that's why I never use them. – Beta Decay Jul 27 '15 at 19:45
• It's a standard format, and it gives a bit of credit to people that helped you golf it, by showing that this isn't what you originally came up with. Otherwise, in order to see that you changed it significantly at all, they have to view edit history. It's more user-friendly to show the byte-change, but I guess it's up to you whether or not to credit those who helped you. – mbomb007 Jul 27 '15 at 21:43
• See this meta post for further description of why it's helpful. – mbomb007 Jul 27 '15 at 21:47
• @mbomb007 The accepted answer to the meta post you link says there isn't and doesn't need to be a policy about this, even though it does give reasons one might like to include them, so I think it's up to each poster. – xnor Jul 28 '15 at 0:34
• @xnor Thanks for summarizing what I said above. Very helpful. – mbomb007 Jul 28 '15 at 15:31

# Erlang, 157 bytes

f(A,B)->S=string,G=fun(A,B)->[if Q>64andalso Q<91->S:to_upper(P);Q>96andalso Q<123->S:to_lower(P);true->P end||{P,Q}<-lists:zip(A,B)]end,G(A,B)++"\n"++G(B,A).


Zips the two strings (actually, lists) into a two-character-tuple list and maps each character to the appropriate case using a list comprehension.

# Python 2, 101 bytes

lambda*I:["".join([a.upper(),a.lower(),a][~-b.isalpha()or"Z"<b]for a,b in zip(*X))for X in I,I[::-1]]


An anonymous function which takes two strings and returns the output strings in a list. I've marked this as Python 2 because Python 3 doesn't allow I,I[::-1] to sit alone at the end like that.

# Python, 126 bytes

t="".join;s="low","upp";y=lambda a,b:eval("a"+".%ser()"%s[b.isupper()]*b.isalpha());f=lambda a,b:(t(map(y,a,b)),t(map(y,b,a)))


Function f returns strings in a tuple

• That is now fixed, it now works for all the test cases. – Blue Jul 27 '15 at 15:01

# C, 181 bytes

char*x,*y;main(int a,char**_){a?x=_[2],y=_[1],main(0,0),putchar(10),x=_[1],y=_[2],main(0,0):(*x?putchar(!isupper(*x)?!islower(*x)?*y:tolower(*y):toupper(*y)),x++,y++,main(0,0):0);}


Had trouble shortening standard library names in a worthwhile way, (#define'ing them takes 11 characters of overhead). Uses main recursion and global variables x and y as arguments.

main(<non-zero>,argv) = call main(0,{argv[1],argv[2]}) then print newline then call main(0,{argv[2],argv[1]})

main(0,{x,y}) = if x is end of string return 0, else print correct case of first character of x and call main(0,{x+1,y+1}).

Run with the two strings as arguments.

• Are you stealing my username? ;) – Beta Decay Jul 27 '15 at 19:42

# C - 164 153 Bytes - GCC

#define r z[_][w]
main(_,z,w)char**z;{while(--_)for(w=0;r;r+=r<25?97:r<91&&r>64?z[!(_-1)+1][w]-=32,_-1?z[_-1][w]-=97:0,32:0,w++);puts(z[1]),puts(z[2]);}


gcc prog.c

./a.out AfdgF a2dfsd

Will update if I can get wc -c down. Works very well actually

• Could you post an ungolfed version? I'm curious how this works, but have a hard time reading through your symbols ;) – Vartan Jul 28 '15 at 16:55
• Sure thing. Give me a minute. – jake Oct 18 '16 at 17:35

# F#, 211 chars

let n x y=List.fold2(fun a i j->a@match j with|c when c>='A'&&c<='Z'->[Char.ToUpper i]|c when c>='a'&&c<='z'->[Char.ToLower i]|_->[i])[](x|>Seq.toList)(y|>Seq.toList)|>String.Concat
let m a b =n a b+"\n"+n b a


could be better ...

## Matlab, 140

function [s,t]=f(s,t)
c=s>96&s<123;C=s>64&s<91;d=t>96&t<123;D=t>64&t<91;s(c&D)=s(c&D)-32;s(C&d)=s(C&d)+32;t(d&C)=t(d&C)-32;t(D&c)=t(D&c)+32;


Ungolfed:

function [s,t] = f(s,t)
c = s>96 & s<123;         % letters that are lowercase in 1st string
C = s>64 & s<91;          % letters that are uppercase in 1st string
d = t>96 & t<123;         % letters that are lowercase in 2nd string
D = t>64 & t<91;          % letters that are uppercase in 2nd string
s(c&D) = s(c&D) - 32;     % make uppercase in 1st string
s(C&d) = s(C&d) + 32;     % make lowercase in 1st string
t(d&C) = t(d&C) - 32;     % make uppercase in 2nd string
t(D&c) = t(D&c) + 32;     % make lowercase in 2nd string


Example:

>> [s,t]=f('PRogrammiNG puzZLes & CODe golf','SdlkhkfaladlKsdlalksdg7ldklDgsl')
s =
Programming Puzzles & Code Golf
t =


# C, 164 bytes

Pretty much implementing the algorithm as described in the problem. Takes 2 strings as input parameters.

char*a,*b;main(c,v)char**v;{for(a=v[1],b=v[2];*a&&*b;++a,++b)isupper(*a)&&islower(*b)?*a+=32,*b-=32:isupper(*b)&&islower(*a)?*b+=32,*a-=32:0;puts(v[1]);puts(v[2]);}


Ungolfed:

char *a, *b; /* Helpers */

main(c, v)
char **v;
{
/* While strings not terminated... */
for (a = v[1], b = v[2]; *a && *b; ++a, ++b)
isupper(*a) && islower(*b)
? *a += 32, *b -= 32 /* Make first string lowercase, second uppercase */
: isupper(*b) && islower(*a)
? *b += 32, *a -= 32; /* Make second string lowercase, first uppercase */

puts(v[1]); /* print out first string */
puts(v[2]); /* print out second string */
}


$><<gets.chars.zip(gets.chars).map{|i|/[a-z][A-Z]|[A-Z][a-z]/=~i*''?(i.map &:swapcase):i}.transpose*''  Takes the original strings, pairs off letters in arrays. If they are either lower/cap or cap/lower, then swapcase on both. Then transpose the arrays back into our ordered array. This requires a trailing newline in input. # Perl 5.10+, 101 99 bytes perl -p00e '/\n/;s/([a-z])(?=.{$-[0]}([a-z]))/$x=($1^$2)&" ";$s{$-[2]}=$2^$x;$1^$x/egis;s|.|$s{$-[0]}//$&|eg'


96 bytes + 3 bytes for the command line flags p00. Takes a single newline-delimited string as input:

$echo -e "AAAbbb111\nCc2Dd3Ee4" | perl -p00e '...'  Or you can enter input on STDIN: $ perl -p00e '...'
AAAbbb111 <Enter>
Cc2Dd3Ee4 <Ctrl+D>


## Broken down:

perl -p00e'  # Slurp everything into $_, print$_ automatically at the end
/\n/;    # Match first newline, setting $-[0] to length(s1) s/ ([a-z]) # Match a single letter in s1 (?= .{$-[0]}  # Match n chars where n is length(s1) (until corresponding char in s2)
([a-z])   # Corresponding letter in s2
)
/
$x=($1^$2)&" "; # Check whether bit 6 is the same for both chars. # (Only difference between a lowercase and uppercase ASCII letter # is bit 6; ASCII space is 100000 in binary)$s{$-[2]}=$2^$x; # Swap case of corresponding char in s2 and store in %s, # with position as the key$1^$x # Swap case of current char /egis; s|.|$s{$-[0]}//$&|eg  # Do a second pass through $_. If there's a value stored in %s # corresponding to this position, use it '  # First attempt in scala, 138 chars def f(s:String,t:String)={val g=(a:Char,o:Char)=>if(o.isUpper)a.toUpper else a.toLower;s.zip(t).map(c=>(g.tupled(c),g(c._2, c._1))).unzip}  f is a function that take the two input strings and do the job, with a local function, used two times, for changing case of strings. The same code, with indentation and just a litte more readable names : def f_ungolfed(first : String, second : String) = { val aux = (c1: Char, c2: Char) => if (c2.isUpper) c1.toUpper else c1.toLower first.zip(second).map( c => (aux.tupled(c), aux.tupled(c.swap)) ).unzip }  # Jelly, 13 bytes =Œu=/ị"Ɱż"Œs$


A monadic Link accepting and returning lists of two "strings" (lists of characters in Jelly).

Try it online!

# Python 2, 97 bytes

lambda a,b:''.join([x,chr(ord(x)&95|ord(y)&32)][(x+y).isalpha()]for x,y in zip(a+'\n'+b,b+' '+a))


Try it online!

# Tcl, 194 bytes

proc C a\ b {proc L x\ y {expr [[set S string] is u $y]?"[$S tou $x]":"[$S is lo $y]"?"[$S tol $x]":"$x"}
lmap x [split $a ""] y [split$b ""] {append s [L $x$y]
append t [L $y$x]}
list $s$t}


Try it online!

import Data.Char