Eliminar caso duplicado y cambiado

27

Gol

El objetivo de este desafío es: dada una cadena como entrada, eliminar pares de letras duplicados, si el segundo elemento del par es de mayúsculas opuestas. (es decir, mayúsculas se convierte en minúsculas y viceversa).

Los pares deben reemplazarse de izquierda a derecha. Por ejemplo, aAadebería convertirse aay no aA.

ejemplos

Salidas, entradas:

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

La entrada consta de símbolos ASCII imprimibles.

No debe eliminar dígitos duplicados u otros caracteres que no sean letras.

Reconocimiento

Este desafío es lo contrario de "Duplicate & switch case" de @nicael . ¿Puedes revertirlo?

¡Gracias por todos los contribuyentes de la caja de arena!

Catalogar

El Fragmento de pila al final de esta publicación genera el catálogo a partir de las respuestas a) como una lista de la solución más corta por idioma yb) como una tabla de clasificación general.

Para asegurarse de que su respuesta se muestre, comience con un título, utilizando la siguiente plantilla de Markdown:

## Language Name, N bytes

¿Dónde Nestá el tamaño de su envío? Si mejora su puntaje, puede mantener los puntajes antiguos en el título, tachándolos. Por ejemplo:

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

Si desea incluir varios números en su encabezado (por ejemplo, porque su puntaje es la suma de dos archivos o desea enumerar las penalizaciones de la bandera del intérprete por separado), asegúrese de que el puntaje real sea el último número en el encabezado:

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

También puede hacer que el nombre del idioma sea un enlace que luego aparecerá en el fragmento:

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

aloisdg dice Reinstate Monica
fuente
44
Jaja, eso es NniIcCeE :)
nicael
@nicael Me alegra que lo apruebe :)
aloisdg dice Reinstate Monica
¿Cuál es la salida para abB:? abBo ab?
Downgoat
@Downgoat abBdebería salirab
aloisdg dice Reinstate Monica
1
@raznagul ¿por qué lo haría? Dividirlo: aa; aA; AA, solo el par medio coincide con el patrón y se convierte a, entonces aa; a; AA
LLlAMnYP

Respuestas:

12

Jalea , 8 bytes

ṛŒsḟḟȧµ\

Pruébalo en línea! o verificar todos los casos de prueba .

Cómo 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
fuente
Más corto que el maldito Regex!
aloisdg dice Reinstate Monica
2
Vence a Retina en un desafío de cuerdas ._.
TuxCrafting
11

Retina , 18 bytes

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

Pruébalo en línea!

Explicación

Esta es una sustitución simple (y bastante simple) que coincide con los pares relevantes y los reemplaza solo con el primer carácter. Los pares se combinan activando la insensibilidad de mayúsculas y minúsculas a la mitad del patrón:

(.)     # 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.

La sustitución simplemente reescribe el personaje que ya capturamos en el grupo de 1todos modos.

Martin Ender
fuente
1
¡Buena respuesta! ¡Debuggex funciona muy bien con este!
aloisdg dice Reinstate Monica
5

Brachylog , 44 bytes

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

Brachylog no tiene expresiones regulares.

Explicación

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

C #, 87 75 bytes

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

Con la poderosa expresión regular de Martin Ender. C # lambda donde están la entrada y la salida string.

12 bytes guardados por Martin Ender y 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 donde están la entrada y la salida string. El algoritmo es ingenuo. Este es el que uso como referencia.

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 gracias a Martin Ender!


¡Pruébalos en línea!

aloisdg dice Reinstate Monica
fuente
@ TùxCräftîñg De hecho, pero es fácil de leer así. Verifique mi versión de golf para obtener una respuesta menos detallada :)
aloisdg dice Reinstate Monica
4

Perl, 40 24 + 1 = 25 bytes

Usa la misma expresión regular que Martin.
Usa la -pbandera

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

Pruébalo en ideone

TuxCrafting
fuente
Si usa el indicador -p, puede eliminar casi todo su código, excepto el s /// para un buen ahorro.
Dom Hastings
4

Python 3, 64 59 58 bytes

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

Pruébalo en Ideone .

Dennis
fuente
4

C, 66 bytes

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

Pyth, 24 20 bytes

4 bytes gracias a @Jakube.

Esto todavía usa expresiones regulares, pero solo para tokenizar.

shM:zj\|+s_BVGrG1\.1

Banco de pruebas.

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.
  • Versión de 24 bytes aquí .
Monja permeable
fuente
3

JavaScript (ES6), 71 68 bytes

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

Explicación:

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>'@', la única forma de parseInt(c+l,36)ser un múltiplo de 37 es para ambos cy ltener el mismo valor (no pueden tener valor cero porque excluimos el espacio y el cero, y si no tienen valor, la expresión evaluará NaN<1cuál es falso) es para ellos ser la misma letra. Sin embargo, sabemos que no son la misma letra entre mayúsculas y minúsculas, por lo que deben ser iguales entre mayúsculas y minúsculas.

Tenga en cuenta que este algoritmo solo funciona si verifico todos los caracteres; si trato de simplificarlo haciendo coincidir las letras, fallará en cosas como "a+A".

Editar: Guardado 3 bytes gracias a @ edc65.

Neil
fuente
Use reemplazar en lugar de mapa. 68. Pero soy demasiado vago para descubrir cómo poner '' 'dentro de un comentario (buen truco mod 37)
edc65
@ edc65 No necesito ninguna `s si la uso replace. (Solo los tenía antes para tratar de ser coherente, pero luego jugué mi respuesta mientras la editaba para presentarla y volví a ser inconsistente. 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);}

Puerto de CA de mi respuesta C # . Mi C puede ser un poco mala. Ya no uso mucho el idioma. Cualquier ayuda es bienvenida!

  • 1 byte guardado gracias al truco de Lowjacker : a!=b=a^b
  • 1 byte guardado gracias al truco de Walpen : a&&b=a*b
  • 12 bytes guardados por el truco de Lynn e inspirados aquí por TùxCräftîñg
  • 1 byte guardado gracias al truco de Joey Adams e inspirado aquí por orlp: moviendo la variable a global
  • 2 bytes guardados por SEJPM al resolver mi (c|32)==(d|32)problema bit a bit
  • 5 bytes guardados por Pietu1998

Código:

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

Pruébalo en línea!

aloisdg dice Reinstate Monica
fuente
1
Creo que puede incrementar el puntero para guardar algunos bytes. He encontrado esto (no probado):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 Me olvidé de este. Corregí tu propuesta con base en la respuesta de Lynn. ¡Gracias por la ayuda!
aloisdg dice Reinstate Monica
1
Creo que puedes cambiar s+++1a ++s.
PurkkaKoodari
@ Pietu1998 De hecho, puedo!
aloisdg dice Reinstate Monica
1
cy dsiempre será ASCII imprimible, por lo que 95debería funcionar en lugar de ~32. Además, creo c;d;f(char*s){for(;*s;){putchar(c=*s);s+=isalpha(c)*(d=*(++s))&&(!((c^d)&95)&&c^d);}}que funcionaría (pero no probado).
PurkkaKoodari
3

MATL , 21 bytes

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

Pruébalo en línea! . O verificar todos los casos de prueba .

Explicación

Esto procesa cada personaje en un bucle. Cada iteración compara el carácter actual con el carácter anterior. Este último se almacena en el portapapeles K, que se inicializa 4de forma predeterminada.

El carácter actual se compara con el anterior dos veces: primero sin distinción entre mayúsculas y minúsculas y luego con mayúsculas y minúsculas. El carácter actual debe eliminarse si y solo si la primera comparación fue verdadera y la segunda fue falsa. Tenga en cuenta que, dado que el portapapeles K contiene inicialmente 4, el primer carácter siempre se mantendrá.

Si se elimina el carácter actual, el portapapeles K debe restablecerse (de modo que se mantendrá el siguiente carácter); de lo contrario, debe actualizarse con el carácter actual.

"            % 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
fuente
2

Java 7, 66 bytes

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

Usó la expresión regular de Martin Ender de su respuesta Retina .

Ungolfed y código de prueba:

Pruébalo aquí

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"));
  }
}

Salida:

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

JavaScript (ES6), 61 bytes , 57 bytes

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

Gracias a Neil por guardar 5 bytes.

cPu1
fuente
1
Malas noticias: has contado mal, y en realidad son 62 bytes. Buenas noticias: ¡puedo ahorrarte cinco bytes! s=>s.replace(/./g,c=>l=c!=l&/(.)\1/i.test(l+c)?'':c,l='')
Neil
Oh, lo siento, conté usando "code".length, no me di cuenta de que había una secuencia de escape allí. Gracias
cPu1
Intenta usarlo (code).toString().length.
Neil
Sí, o(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
fuente
OK, voy a morder. ¿Por qué el ===?
Neil
0==""pero no 0===""@Neil
edc65 18/07/2016
1

Convexo, 18 bytes

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

Pruébalo en línea!

Enfoque similar a la respuesta Pyth de @Leaky Nun . Construye la matriz ["aA" "bB" ... "zZ" "Aa" "Bb" ... "Zz" '.], se une por el '|carácter y prueba la entrada en función de esa expresión regular. Luego toma el primer personaje de cada partido.

GamrCorps
fuente