Remover caixa duplicada e comutada

27

Objetivo

O objetivo desse desafio é: dada uma sequência como entrada, remova pares de letras duplicados, se o segundo item do par for de capitalização oposta. (ou seja, maiúsculas se tornam minúsculas e vice-versa).

Os pares devem ser substituídos da esquerda para a direita. Por exemplo, aAadeve se tornar aae não aA.

exemplos

Entradas saídas:

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

A entrada consiste em símbolos ASCII imprimíveis.

Você não deve remover dígitos duplicados ou outros caracteres que não sejam letras.

Reconhecimento

Esse desafio é o oposto do "Duplicate & switch case" de @nicael . Você pode reverter isso?

Obrigado por todos os colaboradores da sandbox!

Catálogo

O snippet de pilha na parte inferior desta postagem gera o catálogo a partir das respostas a) como uma lista da solução mais curta por idioma eb) como uma tabela geral de líderes.

Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:

## Language Name, N bytes

onde Nestá o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Se você quiser incluir vários números no cabeçalho (por exemplo, porque sua pontuação é a soma de dois arquivos ou você deseja listar as penalidades do sinalizador de intérpretes separadamente), verifique se a pontuação real é o último número no cabeçalho:

## Perl, 43 + 2 (-p flag) = 45 bytes

Você também pode transformar o nome do idioma em um link que será exibido no snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

aloisdg diz Restabelecer Monica
fonte
4
Haha, isso é NniIcCeE :)
nicael
@nicael Estou feliz que você aprove :)
aloisdg diz Reinstate Monica
qual é a saída para abB:? abBou ab?
Downgoat
@Downgoat abBdeve produzirab
aloisdg diz Reinstate Monica
1
@raznagul por que seria? Dividi-lo: aa; aA; AA, apenas o par do meio corresponde ao padrão e se torna a, então aa; a; AA
LLlAMnYP

Respostas:

12

Geléia , 8 bytes

ṛŒsḟḟȧµ\

Experimente online! ou verifique todos os casos de teste .

Como funciona

ṛŒsḟḟȧµ\  Main link. Argument: s (string)

      µ   Convert all links to the left into a chain (unknown arity) and begin a
          new chain.
       \  Do a cumulative reduce by the chain to the left.
          Left argument:   r (previous result or first character)
          Right argument:  c (next character)
ṛ           Set the return value to c.
 Œs         Swap c's case.
    ḟ       Remove c from r (if present).
            This yields an empty string if c and r are identical (repeated letter
            with the same case or non-letter) and r otherwise.
            Note that r will be empty if the previous character has been removed.
   ḟ        Remove the resulting characters (if any) from c with swapped case.
            This yields c with swapped case if the result to the right does not
            contain c; otherwise, it yields the empty string.
     ȧ      Flat logical AND with c.
            Replace swapped case c with c; do not modify an empty string.
Dennis
fonte
Mais curto que o maldito Regex!
aloisdg diz Reinstate Monica
2
Bata Retina em um desafio de cordas ._.
TuxCrafting
11

Retina , 18 bytes

(.)(?!\1)(?i)\1
$1

Experimente online!

Explicação

Essa é uma substituição única (e bastante simples) que combina os pares relevantes e os substitui apenas pelo primeiro caractere. Os pares são correspondidos ativando a distinção entre maiúsculas e minúsculas na metade do padrão:

(.)     # Match a character and capture it into group 1.
(?!\1)  # Use a negative lookahead to ensure that the next character *isn't* the same
        # as the character we just captured. This doesn't advance the position of the
        # regex engine's "cursor".
(?i)    # Now activate case-insensitivity for the remainder of the pattern.
\1      # Match the second character with a backreference to the first. With the i
        # modifier activated, this will match if the two characters only differ
        # by case.

A substituição simplesmente devolve o personagem que já capturamos em grupo 1.

Martin Ender
fonte
1
Boa resposta! Debuggex funciona muito bem com este!
aloisdg diz Reinstate Monica
5

Braquilog , 44 bytes

.v|.l1|hA,?bhB(@uA;A@uB),?bb&~b.hA|?b&~b.h~h?

Brachylog não tem expressões regulares.

Explicação

    .v          Input = Output = ""
|               OR
    .l1         Input = Output = string of one character
|               OR
    hA,         A is the first char or the Input
    ?bhB        B is the second char of the Input
    (
        @uA         B uppercased is A
        ;           OR
        A@uB        A uppercased is B
    ),
    ?bb&        Call recursively on Input minus the first two elements
    ~b.hA       Output is the result of that call with A appended before it
|               OR
    b&          Call recursively on Input minus the first element
    ~b.h~h?     Output is the result of that call with the first element of Input appended
                  before it
Fatalizar
fonte
5

C #, 87 75 bytes

s=>System.Text.RegularExpressions.Regex.Replace(s,@"(.)(?!\1)(?i)\1","$1");

Com o poderoso regex de Martin Ender. C # lambda onde estão a entrada e a saída string.

12 bytes salvos por Martin Ender e TùxCräftîñg.


C #, 141 134 bytes

s=>{var r="";for(int i=0,l=s.Length;i<l;i++){var c=s[i];r+=c;if(char.IsLetter(c)&i+1<l&&(c|32)==(s[i+1]|32)&c!=s[i+1])i++;}return r;};

C # lambda onde estão a entrada e a saída string. O algoritmo é ingênuo. Este é o que eu uso como referência.

Código:

s=>{
    var r = "";
    for(int i = 0; i < s.Length; i++)
    {
        r+=s[i];
        if (char.IsLetter(s[i]) & i+1 < s.Length)
            if (char.ToLower(s[i])==char.ToLower(s[i+1])
              & char.IsLower(s[i])!=char.IsLower(s[i+1]))
                i += 1;
    }       
    return r;
};

7 bytes graças a Martin Ender!


Experimente-os online!

aloisdg diz Restabelecer Monica
fonte
@ TùxCräftîñg De fato, mas é fácil ler assim. Verifique minha versão golfed para uma resposta menos detalhada :)
aloisdg diz Reinstate Monica
4

Perl, 40 24 + 1 = 25 bytes

Use o mesmo regex que Martin.
Use a -pbandeira

s/(.)(?!\1)(?i)\1/\1/g

Teste em ideone

TuxCrafting
fonte
Se você usar o sinalizador -p, poderá remover quase todo o seu código, exceto o s ///, para uma boa economia!
Dom Hastings
4

Python 3, 64 59 58 bytes

r=input()
for c in r:r=c[c.swapcase()==r!=c:];print(end=r)

Teste em Ideone .

Dennis
fonte
4

C, 66 bytes

l;main(c){for(;~(c=getchar());)l=l^c^32|!isalpha(c)?putchar(c):0;}
orlp
fonte
3

Pitão, 24 20 bytes

4 bytes graças a @Jakube.

Isso ainda usa regex, mas apenas para tokenização.

shM:zj\|+s_BVGrG1\.1

Suíte de teste.

shM:zj\|+s_BVGrG1\.1   input as z
         s_BVGrG1      generate ['aA', 'Aa', 'bB', 'Bb', ..., 'zZ', 'Zz']
        +        \.    add "." to the back of the array
     j\|               insert "|" between every element of the array,
                       forming a new long string, which will be our
                       tokenizer: "aA|Aa|bB|Bb|cC|Cc|...|yY|Yy|zZ|Zz|."
                       the "." at the end is to capture the remaining characters
  :z               1   return all matches of z against that regex
                       this is effectively a tokenizer
 hM                    take the first character of each token
s                      join all the transformed tokens together, and then
                       implicitly print to STDOUT.
  • Versão de 24 bytes aqui .
Freira Furada
fonte
3

JavaScript (ES6), 71 68 bytes

s=>s.replace(/./g,c=>l=c!=l&&c>'0'&&parseInt(c+l,36)%37<1?'':c,l='')

Explicação:

s=>s.replace(/./g,c=>   Loop over each character in the string
 l=                     Save result for next loop
  c!=l&&                Check whether characters differ
  c>'@'&&               Check minimum character code
  parseInt(c+l,36)%37<1 Check if characters have same value
  ?'':c,                If so then delete this character
 l='')                  Initial empty previous character

Dado c>'@', a única maneira de parseInt(c+l,36)ser um múltiplo de 37 é para ambos ce lter o mesmo valor (eles não podem ter valor zero porque excluímos espaço e zero, e se eles não tiverem valor, a expressão avaliará NaN<1qual é false) é que eles tenham a mesma letra. No entanto, sabemos que eles não são a mesma letra com distinção entre maiúsculas e minúsculas, portanto devem ser a mesma sem distinção entre maiúsculas e minúsculas.

Observe que esse algoritmo só funciona se eu verificar todos os caracteres; se eu tentar simplificá-lo combinando letras, falhará em coisas como "a+A".

Editar: salvou 3 bytes graças a @ edc65.

Neil
fonte
Use substituir em vez de mapa. 68. Mas eu sou muito preguiçoso para descobrir como colocar ''' dentro de um comentário (bom truque mod 37)
edc65
@ edc65 Não preciso de `s se usar replace. (Eu só tive-los antes de tentar ser consistente, mas então eu golfed minha resposta durante a edição lo para a apresentação e se tornou inconsistente novamente Suspiro ....)
Neil
3

C, 129 127 125 107 106 105 93 92 90 88 85 78 bytes

c;d;f(char*s){for(;putchar(c=*s);)s+=isalpha(c)*(d=*++s)&&(!((c^d)&95)&&c^d);}

Porta CA da minha resposta C # . Meu C pode estar um pouco ruim. Eu não uso muito o idioma. Qualquer ajuda é bem vinda!

  • 1 byte economizado graças ao truque de Lowjacker : a!=b=a^b
  • 1 byte economizado graças ao truque de Walpen : a&&b=a*b
  • 12 bytes salvos pelo truque de Lynn e inspirados aqui por TùxCräftîñg
  • 1 byte economizado graças ao truque de Joey Adams e inspirado aqui pelo orlp: movendo variável para global
  • 2 bytes salvos pelo SEJPM, resolvendo meu (c|32)==(d|32)problema bit a bit
  • 5 bytes salvos por Pietu1998

Código:

c;d;f(char*s) {
    for(;putchar(c=*s);)
        s+=isalpha(c)*(d=*++s)&&(!((c^d)&95)&&c^d);
}

Experimente online!

aloisdg diz Restabelecer Monica
fonte
1
Eu acho que você pode incrementar o ponteiro para salvar alguns bytes. Eu encontrei este (não testado):f(char*s){while(*s) {char c=*s,d=s+1;putchar(c);s+=isalpha(c)&&d&&((c|32)==(d|32)&&c!=d);}}
TuxCrafting
@ TùxCräftîñg Esqueci-me deste. Corrigi sua proposta com base na resposta de Lynn. Obrigado pela ajuda!
aloisdg diz Reinstate Monica
1
Eu acho que você pode mudar s+++1para ++s.
PurkkaKoodari
@ Pietu1998 Na verdade eu posso!
aloisdg diz Reinstate Monica
1
ce dsempre será ASCII imprimível, portanto, 95deve funcionar no lugar de ~32. Além disso, acho c;d;f(char*s){for(;*s;){putchar(c=*s);s+=isalpha(c)*(d=*(++s))&&(!((c^d)&95)&&c^d);}}que funcionaria (mas não foi testado).
PurkkaKoodari
3

MATL , 21 bytes

"Kk@k=K@XK=>?4XKx}K&h

Experimente online! . Ou verifique todos os casos de teste .

Explicação

Isso processa cada caractere em um loop. Cada iteração compara o caractere atual com o caractere anterior. O último é armazenado na área de transferência K, que é inicializada 4por padrão.

O caractere atual é comparado com o anterior duas vezes: primeiro sem diferenciação de maiúsculas e minúsculas e depois sensível a maiúsculas e minúsculas. O caractere atual deve ser excluído se e somente se a primeira comparação for verdadeira e a segunda for falsa. Observe que, como a área de transferência K contém inicialmente 4, o primeiro caractere sempre será mantido.

Se o caractere atual for excluído, a área de transferência K deve ser redefinida (para que o próximo caractere seja mantido); caso contrário, deve ser atualizado com o caractere atual.

"            % Take input string implicitly. For each char from this string:
  K          %   Push previous char, initiallized to number 4
  k          %   Convert to lower case. For numbers it rounds down
  @          %   Push current char
  k          %   Convert to lower case. 
  =          %   True if current and previous chars are (case-insensitively) equal
  K          %   Push previous char
  @          %   Push current char
  XK         %   Update clipboard K with current char. This doesn't affect the stack
  =          %   True if current and previous chars are (case-sensitively) equal
  >?         %   If first comparison was true and second was false
    4XKx     %     Reset clipboard K to 4
  }          %   Else
    K        %     Push previous char
    &h       %     Concatenate horizontally to gradually build the output string
Luis Mendo
fonte
2

Java 7, 66 bytes

String c(String i){return i.replaceAll("(.)(?!\\1)(?i)\\1","$1");}

Utilizou a expressão regular de Martin Ender em sua resposta da Retina .

Ungolfed & código de teste:

Experimente aqui.

class Main{
  static String c(String i){
    return i.replaceAll("(.)(?!\\1)(?i)\\1", "$1");
  }

  public static void main(String[] a){
    System.out.println(c("bBaAdD"));
    System.out.println(c("NniIcCeE"));
    System.out.println(c("Tt eE Ss tT"));
    System.out.println(c("sS Ee tT"));
    System.out.println(c("1!1!1sStT!"));
    System.out.println(c("nN00bB"));
    System.out.println(c("(eE.gG.)"));
    System.out.println(c("Hh3lL|@!"));
    System.out.println(c("Aaa"));
    System.out.println(c("aaaaa"));
    System.out.println(c("aaAaa"));
  }
}

Saída:

bad
Nice
T e S t
s E t
1!1!1st!
n00b
(e.g.)
H3l|@!
Aa
aaaaa
aaaa
Kevin Cruijssen
fonte
2

JavaScript (ES6), 61 bytes , 57 bytes

s=>s.replace(/./g,c=>l=c!=l&/(.)\1/i.test(l+c)?'':c,l='')

Agradecimentos a Neil por salvar 5 bytes.

cPu1
fonte
1
Más notícias: você errou a conta e são 62 bytes. Boas notícias: posso economizar cinco bytes! s=>s.replace(/./g,c=>l=c!=l&/(.)\1/i.test(l+c)?'':c,l='')
Neil
Ah, desculpe, contei usando "code".length, não percebi que havia uma sequência de fuga lá. Graças
CPU1
Tente usar (code).toString().length.
Neil
Sim, ou(code+"").length
cPu1
1

JavaScript (ES6) 70

(s,p,q)=>s.replace(/./g,c=>p!=c&q===(d=parseInt(c,36))?q='':(q=d,p=c))

f=(s,p,q)=>s.replace(/./g,c=>p!=c&q===(d=parseInt(c,36))?q='':(q=d,p=c))

;
[['bBaAdD','bad']
,['NniIcCeE','Nice']
,['Tt eE Ss tT','T e S t']
,['sS Ee tT','s E t']
,['1!1!1sStT!','1!1!1st!']
,['nN00bB','n00b']
,['(eE.gG.)','(e.g.)']
,['Hh3lL|@!','H3l|@!']
,['Aaa','Aa']
,['aaaaa','aaaaa']
,['aaAaa','aaaa']]
.forEach(
  x=>
  {
    var i=x[0],k=x[1],r=f(i)
    console.log(k==r?'OK':'KO',i,r)
  }
)

edc65
fonte
OK, eu vou morder. Por que o ===?
Neil
0==""mas não 0===""@Neil
edc65
1

Convexo, 18 bytes

V±V.+'.+'|*\ô{0=}%

Experimente online!

Abordagem semelhante à resposta Pyth de @Leaky Nun . Ele constrói a matriz ["aA" "bB" ... "zZ" "Aa" "Bb" ... "Zz" '.], une-se pelo '|caractere e testa a entrada com base nesse regex. Depois é preciso o primeiro caractere de cada partida.

GamrCorps
fonte