Praming Puzles & Colf: Condense una cuerda

25

Después de pasar un tiempo en este sitio, he llegado a disfrutar de que las cosas sean lo más cortas posible. Esa puede ser la razón por la que recientemente me ofenden las cadenas que contienen los mismos caracteres más de una vez. Su trabajo es escribir una función o programa que condense una cadena dada de acuerdo con las siguientes reglas:

  • Comience con una condensación 0 , es decir, busque el primer par (más a la izquierda) de los mismos caracteres con otros 0 caracteres entre ellos. Si se encuentra dicho par, elimine uno de los dos caracteres y reinicie el algoritmo realizando otra condensación 0 . Si no se encuentra dicho par, continúe con el siguiente paso. Ejemplos:
    programming-C0-> programing
    aabbcc-C0-> abbcc
    test-C0->test

  • Luego realice una 1 condensación , es decir, busque el primer par de mismos caracteres con 1 otro personaje entre ellos. Si se encuentra dicho par, elimine uno de ellos y todos los caracteres entre ellos y reinicie con una condensación 0 . Si no se encuentra dicho par, continúe con el siguiente paso. Ejemplos:
    abacac-C1-> acac
    java-C1->ja

  • Continúe con una 2-condensación y así sucesivamente hasta una n-condensación con n siendo la longitud de la cadena original, reiniciando cada vez después de que una condensación elimine algunas letras. Ejemplos:
    programing-C2-> praming
    abcdafg-C3->afg

La cadena resultante se llama condensada y contiene cada carácter como máximo una vez.


Entrada:

Una cadena en minúscula de caracteres ascii imprimibles.

Salida:

La cadena condensada de acuerdo con las reglas anteriores.

Ejemplos:

examples     -> es
programming  -> praming
puzzles      -> puzles
codegolf     -> colf
andromeda    -> a
abcbaccbabcb -> acb
if(x==1):x++ -> if(x+
fnabnfun     -> fun
abcdefae     -> abcde

Ejemplos detallados para aclarar cómo funciona el algoritmo:

fnabnfun -C0-> fnabnfun -C1-> fnabnfun -C2-> fnfun -C0-> fnfun -C1-> fun -C0-> fun 
 -C1-> fun -C2-> ... -C8-> fun

abcbaccbabcb -C0-> abcbacbabcb -C0-> abcbacbabcb -C1-> abacbabcb -C0-> abacbabcb 
 -C1-> acbabcb -C0-> acbabcb -C1-> acbcb -C0-> acbcb -C1-> acb -C0-> acb 
 -C1-> ... -C12-> acb

Su enfoque no tiene que implementar el algoritmo desde arriba siempre que su solución y el algoritmo devuelvan la misma salida para todas las entradas permitidas. Este es un desafío de .


¡Gracias a @Linus por los útiles comentarios de sandbox!

Laikoni
fuente
El caso de prueba de @MartinEnder Riley todavía es necesario, porque es el único en el que mi solución Retina no funciona.
mbomb007
@ mbomb007 Ah, ya veo. Buen punto.
Martin Ender
¿La cadena de entrada contendrá caracteres no imprimibles como espacios?
mbomb007
@ mbomb007 No, asumir caracteres ascii imprimibles solo está bien.
Laikoni
@ mbomb007 Sin embargo, que yo sepa, un espacio se considera un carácter ascii imprimible, por ejemplo, aquí .
Laikoni

Respuestas:

6

JavaScript (ES6), 74 bytes

f=
(s,n=0,m=s.match(`(.).{${n}}\\1`))=>s[n]?m?f(s.replace(...m)):f(s,n+1):s
;
<input oninput=o.textContent=f(this.value)><pre id=o>

Neil
fuente
Muy bonito, más corto de lo que hubiera pensado.
ETHproductions
5

Perl, 38 31 30 29 bytes

Esto debería dejar atrás los idiomas ajenos al golf ...

-1 por $-[0]gracias a Riley

-1 por @{-}gracias a Dada

Incluye +1 para -p

Dar entrada sobre STDIN

condense.pl:

#!/usr/bin/perl -p
s/(.)\K.{@{-}}\1// while/./g

Esta versión de 27 bytes debería funcionar, pero no porque Perl no se interpola @-en una expresión regular (consulte /programming/39521060/why-are-etc-not-interpolated-in-strings )

#!/usr/bin/perl -p
s/(.)\K.{@-}\1// while/./g
Ton Hospel
fuente
¿Cómo funciona la @{\@-}pieza? Pensé que @-tenía los índices de cada partido, entonces, ¿cómo se "cuenta" en cada iteración? Además, si imprime @{\@-}antes y después de cada sustitución, solo imprime 1 o 2.
Riley
1
@Riley El /./gprogreso progresa en 1 en la cadena cada vez, excepto cuando la cadena cambia, luego se restablece a 0. Si imprime @-después /./gpero antes de s///que lo vea subir (use una prueba donde la cadena restante es lo suficientemente grande)
Ton Hospel
La impresión $-[0]da los números que esperaría. ¿ @{\@-}Actúa como $-[0]debido al contexto de expresiones regulares pero no cuando imprime por alguna razón? $-[0]es un byte más corto que @{\@-}si son iguales.
Riley
"@{\@-}"no es lo mismo que @{\@-}(sin ").
Riley
@Riley No, pero "@{\@-}"es lo mismo que "@-". Y esto también debería ser cierto para una sustitución de expresiones regulares, pero no lo es. Simularmente $-[0]debería funcionar pero no lo hace. PD: Probablemente de alguna manera te aplicaste el contexto escalar @-cuando
imprimiste
3

CJam , 35 bytes

rL{_,{{(_@_@#I={I)>]sj}*}h]s}fI}j

Pruébalo en línea!


rL{                            }j   | run recursion on input
   _,{                      }fI     | for I from 0 to length(input)
      {                 }h]s        | one pass & clean up
       (_@                          | slice and store leading element A
          _@#I={      }*            | if next A is I steps away
                I)>                 | slice off I+1 element
                   ]sj              | clean up & recursion

Puede ver las condensaciones individuales insertandoed

Linus
fuente
2

Python 2, 117 104 101 bytes

Recursivamente hacer los reemplazos necesarios. Construyo la expresión regular dinámicamente.

import re
def f(s,i=0):t=re.sub(r"(.)%s\1"%("."*i),r"\1",s);e=s==t;return i>len(t)and t or f(t,i*e+e)

Pruébalo en línea

mbomb007
fuente
Las dos líneas de retorno se pueden condensar en return i>len(t) and t or s!=t and f(t) or f(t,i+1)una red de -4 bytes
Quelklef
Se pueden eliminar otros 2 bytes cambiando eso areturn t if i>len(t)else s!=t and f(t)or f(t,i+1))
Quelklef
Aún más, e=s==t;return i>len(t)and t or f(t,i*e+e)y luego puede eliminar el i=0en la definición de la función, pero tendrá que llamar con 0 inicio.
Quelklef
Asumiré que los cuatro espacios están allí no porque estés usando cuatro espacios sino porque SE los expande automáticamente. Si ese no es el caso, puede cambiar todos sus espacios a pestañas o un solo espacio para -9 bytes.
Financia la demanda de Mónica el
@Quelklef El meta prohíbe tomar parámetros adicionales.
mbomb007
1

Perl 53 52

Incluye +1 para -p

for($i=0;$i<length;){$i=(s/(.).{$i}\1/\1/)?0:$i+1;}

Pruébalo con ideone .

Riley
fuente
1

Mathematica, 101 bytes

NestWhile[i=0;StringReplace[#,a_~~_~RepeatedNull~i++~~a_:>a,1]&,#,SameQ,2,ByteCount@#]&~FixedPoint~#&

Debería haber una manera de hacer esto más corto ...

JungHwan Min
fuente
1

PHP, 90 bytes

for($s=$argv[$c=1];$s[$i=++$i*!$c];)$s=preg_replace("#(.).{{$i}}\\1#","$1",$s,1,$c);echo$s;

o 92 bytes

for($s=$argv[1];$s[$i];$i=++$i*!$c)$s=preg_replace("#(.).{".+$i."}\\1#","$1",$s,1,$c);echo$s;   
Jörg Hülsermann
fuente
1
1) primera versión: en +$ilugar de $i+=0(-2). 2) el forbucle en lugar de whilepuede guardar dos bytes y permitir eliminar los rizos (-4). 3) en $i=++$i*!$clugar de $i=$c?0:$i+1(-1). 4) \\2no es necesario, elimine los paréntesis (-2). 5) Puede permitir el límite en 9lugar de la 1velocidad (+0)
Titus
@Titus muy buenas ideas. No había visto esto Gracias
Jörg Hülsermann
Ahora que lo pienso de nuevo ... +$ino funciona en todos los casos. Tratar hammer. PHP no se queja de las llaves vacías en la expresión regular; pero no coincide con lo deseado. Por cierto: cuento 91, no 90. Pero prueba el nuevo 1)for($s=$argv[$c=1];$s[$i=++$i*!$c];)
Titus
@Titus Sí, de hecho vuelvo $i+=0y probaré tu propuesta más tarde. ¿Qué significa con martillo?
Jörg Hülsermann
@Titus está de acuerdo con el mismo problema si hay puzzlealgo más, (.)//1pero está de acuerdo con su propuesta o con el$i´=0
Jörg Hülsermann
1

Ruby, 75 64 57 bytes

(56 bytes de código + popción de línea de comando).

Usar interpolación de cadenas dentro de una expresión regular para controlar la longitud de las coincidencias que se reemplazan

i=0
~/(.).{#{i}}\1/?sub($&,$1)&&i=0: i+=1while i<$_.size

Prueba:

$ ruby -p condense.rb <<< fnabnfun
fun
daniero
fuente
1

Haskell , 97 88 bytes

(0?)
(a:s)!(b:t)|a==b=a:t|1<3=a:s!t
s!_=s
m?s|length s<m=s|a<-s!drop m s=sum[m+1|a==s]?a

Pruébalo en línea!


Versión antigua de 97 bytes:

(a:s)!(b:t)|a==b=a:t|1<3=a:s!t
s!_=s
m?s|length s==m=s|a<-s!drop m s=(last$0:[m+1|a==s])?a
c=(0?)

Pruébalo con ideone .

Explicación:

(a:s)!(b:t)|a==b = a:t         --perform condensation
           |1<3  = a:s!t       --recursively compare further
 s   ! _         = s           --no condensation performed

La (!)función realiza una n-condensación cuando se le da una cadena una vez completa y una vez con los primeros n caracteres eliminados, por ejemplo, abcdbey cdbepara una 2-condensación, comparando recursivamente los dos caracteres iniciales.

m?s|length s==m   = s         --stop before performing length-s-condensation
   |a <- s!drop m s           --a is the m-condensation of s
    = (last$0:[m+1|a==s])?a   --disguised conditional:
                              -- if a==s       if the m-condensation did not change s
                              -- then (m+1)?a  then perform m+1-condensation
                              -- else 0?a      else restart with a 0-condensation

c=(0?)                        -- main function, initialise m with 0
Laikoni
fuente