Swap capitalization of two strings

27

3

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
SdlkhkfaladlKsdlalksdg7ldklDgsl

Output:

Programming Puzzles & Code Golf
SDlkhkfalADlksdLAlksdg7LDkldgsl

Input:

AAAbbb111
Cc2Dd3Ee4

Output:

AaABbb111
CC2dd3Ee4

Doorknob

Posted 2015-07-27T03:56:46.120

Reputation: 68 138

33I 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 – 2015-07-27T05:12:30.430

1Does the input have to be on the same line? Or can I use some other character (a tab?) to separate them? – kirbyfan64sos – 2015-07-27T15:11:38.607

@Dennis No, the input must be provided as shown in the question. – Doorknob – 2015-07-27T16:04:40.760

@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 – 2015-07-27T16:05:49.947

is a trailing newline allowed? – Downgoat – 2015-07-27T16:06:12.130

@vihan1086 Yes. – Doorknob – 2015-07-27T16:13:04.493

Is this limited to ANSI chars not Unicode, i.e. there is no concern about Turkish and German for instance? – Jodrell – 2015-07-28T14:04:10.373

@Jodrell "They will each contain only printable ASCII" – Doorknob – 2015-07-28T14:14:42.197

so swapping bit 6 would be sufficient? – Jodrell – 2015-07-28T14:23:27.063

@Jodrell Not if the input contains numbers. – ThisSuitIsBlackNot – 2015-07-28T20:27:08.837

You are not specific on the output format. I am in doubt whether you allow to return a list of items instead of two lines separated by a \n character, but I will change my answer from the second to the first, as I've already seen other's answers doing it! – sergiol – 2018-06-10T16:57:43.897

Answers

7

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.

Dennis

Posted 2015-07-27T03:56:46.120

Reputation: 196 637

12

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
SdlkhkfaladlKsdlalksdg7ldklDgsl
AAAbbb111
Cc2Dd3Ee4

Output

abcdefghijklmnopqrstuvwxyz
AAAAAaaaaaAaAaAa----------
Programming Puzzles & Code Golf
SDlkhkfalADlksdLAlksdg7LDkldgsl
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.

Dennis

Posted 2015-07-27T03:56:46.120

Reputation: 196 637

8

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 *

Vartan

Posted 2015-07-27T03:56:46.120

Reputation: 231

6

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
SDlkhkfalADlksdLAlksdg7LDkldgsl

MickyT

Posted 2015-07-27T03:56:46.120

Reputation: 11 735

4

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

Alex A.

Posted 2015-07-27T03:56:46.120

Reputation: 23 761

4

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

Downgoat

Posted 2015-07-27T03:56:46.120

Reputation: 27 116

1This 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 – 2015-07-27T12:16:07.513

@c.P.u1 I've addressed that :) – Downgoat – 2015-07-27T15:04:26.107

4

Mathematica, 173 169 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. :-) )

Eric Towers

Posted 2015-07-27T03:56:46.120

Reputation: 706

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 – 2015-07-27T22:52:05.880

3

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

Beta Decay

Posted 2015-07-27T03:56:46.120

Reputation: 21 478

1@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 – 2015-07-27T19:45:17.440

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 – 2015-07-27T21:43:35.080

See this meta post for further description of why it's helpful.

– mbomb007 – 2015-07-27T21:47:33.467

@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 – 2015-07-28T00:34:10.190

@xnor Thanks for summarizing what I said above. Very helpful. – mbomb007 – 2015-07-28T15:31:16.073

2

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.

c.P.u1

Posted 2015-07-27T03:56:46.120

Reputation: 1 049

2

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.

Sp3000

Posted 2015-07-27T03:56:46.120

Reputation: 58 729

1

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

Blue

Posted 2015-07-27T03:56:46.120

Reputation: 26 661

That is now fixed, it now works for all the test cases. – Blue – 2015-07-27T15:01:49.360

1

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.

LambdaBeta

Posted 2015-07-27T03:56:46.120

Reputation: 2 499

Are you stealing my username? ;) – Beta Decay – 2015-07-27T19:42:59.957

1

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

jake

Posted 2015-07-27T03:56:46.120

Reputation: 111

Could you post an ungolfed version? I'm curious how this works, but have a hard time reading through your symbols ;) – Vartan – 2015-07-28T16:55:03.693

Sure thing. Give me a minute. – jake – 2016-10-18T17:35:51.423

0

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
} 

user47106

Posted 2015-07-27T03:56:46.120

Reputation: 101

0

Jelly, 13 bytes

=Œu=/ị"Ɱż"Œs$

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

Try it online!

Jonathan Allan

Posted 2015-07-27T03:56:46.120

Reputation: 67 804

0

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!

Chas Brown

Posted 2015-07-27T03:56:46.120

Reputation: 8 959

0

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!

sergiol

Posted 2015-07-27T03:56:46.120

Reputation: 3 055

0

Haskell, 109 91 bytes

import Data.Char
(!)=zipWith f
f c|isUpper c=toUpper|isAlpha c=toLower|1<3=id
a#b=[b!a,a!b]

Thanks to @Laikoni for 16 bytes!

Try it online!

Angs

Posted 2015-07-27T03:56:46.120

Reputation: 4 825

0

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 ...

mike m

Posted 2015-07-27T03:56:46.120

Reputation: 41

0

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 =
SDlkhkfalADlksdLAlksdg7LDkldgsl

Luis Mendo

Posted 2015-07-27T03:56:46.120

Reputation: 87 464

0

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 */
}

Cole Cameron

Posted 2015-07-27T03:56:46.120

Reputation: 1 013

0

Ruby, 102

$><<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.

Not that Charles

Posted 2015-07-27T03:56:46.120

Reputation: 1 905

0

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
'

ThisSuitIsBlackNot

Posted 2015-07-27T03:56:46.120

Reputation: 1 050