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]&
Esta é uma função que pega uma matriz de duas strings, por exemplo, {"Foo","bAR"}
e gera uma matriz de duas strings. Un-espacialmente comprimindo-la, reescrevendo o esquema f@x
como f[x]
onde quer que apareça, ampliando as abreviaturas Notation ( f=0>1
aka False
, t=!f
aka True
, c=Characters
e u=ToUpperCaseQ
), e un-substituindo UpperCaseQ [#] com #==u@#
(este personagem é igual a sua versão uppercased), é:
StringJoin /@ MapThread[#[#2] &, {
Reverse[
{ LetterQ[#], UpperCaseQ[#] } & /@ Characters[#] /.
{ {False, _} -> (# &), {True, True} -> ToUpperCase,
{True, False} -> ToLowerCase } & /@ #
],
Characters /@ #
}, 2] &
Interface: o trailing &
torna isso uma função. Seu argumento é inserido como o "#" nas duas instâncias de /@ #
. Por exemplo, f=0>1; ... & [{"AAAbbb111", "Cc2Dd3Ee4"}]
produz a saída {AaABbb111,CC2dd3Ee4}
.
Processamento: Contado normalmente fora em ordem:
- A saída de
MapThread[...]
é uma lista de duas listas de caracteres. StringJoin é aplicado a cada uma dessas duas listas de caracteres para produzir uma lista de duas seqüências, a saída.
MapThread[#[#2]&, ... , 2]
atua em uma matriz de duas listas de elementos 2 por n. A primeira lista é uma matriz de 2 por n de funções. A segunda lista é uma matriz de caracteres 2 por n Characters /@ #
, as listas de caracteres nas duas seqüências de entrada. Funciona na profundidade 2, ou seja, nas funções e nos caracteres individuais.
Reverse[...]
troca as duas sublistas de funções para que o MapThread aplique as funções da segunda sequência à primeira e vice-versa.
{ ... } &
é uma função anônima aplicada a cada uma das duas seqüências de entrada.
{LetterQ[#], UpperCaseQ[#]} & /@ Characters[#]
divide uma string em uma lista de caracteres e substitui cada caractere por duas listas de elementos. Nessas duas listas de elementos, o primeiro elemento é True
se o caractere é uma letra e False
, do mesmo modo, o segundo elemento indica se o caractere está em maiúsculas. UpperCaseQ[]
não pode retornar verdadeiro se não receber uma carta.
/. {{False, _} -> (# &), {True, True} -> ToUpperCase, {True, False} -> ToLowerCase}
substitui essas duas listas de elementos por funções. (A expansão das abreviações t
e f
ocorre antes da tentativa de correspondência.) Se uma lista de dois elementos tiver False
como primeiro elemento, ela será substituída pela função (# &)
, a função de identidade. (Os parênteses são necessários, caso contrário, a seta se liga mais firmemente que o e comercial.) Caso contrário, a lista de dois elementos começa com True
, o caractere era uma letra e produzimos as funções ToUpperCase
e ToLowerCase
correspondentes ao seu caso. (A verificação deste último False
é desnecessária, de fato {_,_}->ToLowerCase
funcionaria, capturando qualquer coisa que ainda não tivesse sido substituída, mas isso não seria mais curto e mais obscuro.)
O único desafio foi descobrir uma maneira sucinta de compactar uma matriz bidimensional de funções em uma matriz de argumentos.
Edit: Obrigado a @Martin Büttner por capturar barras invertidas de corte / colar "úteis", as 1>0
e 1<0
abreviações, e também pela orientação para contar o comprimento em bytes, não em caracteres (sejam eles :-))
Edit2: Mais agradecimentos a @Martin Büttner por apontar que poluir o espaço para nome global é um golfe aceitável, lembrando-me de um aplicativo de função de caractere e sugerindo substituir as duas funções em maiúsculas por uma abreviação de um e usar o outro para emular o outro (salvar quatro caracteres). (Eu acho que ele já fez isso antes. :-))