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