Rosetta Stone Challenge: Run-Length Encoding v2.0

8

El objetivo de Rosetta Stone Challenge es escribir soluciones en tantos idiomas como sea posible. ¡Muestra tu programación multilingüismo!

El reto

Hemos hecho RLE ser plano , pero sólo se consideran carreras de un solo carácter. Por supuesto, a veces podemos ahorrar aún más si consideramos series de varios caracteres.

Tomar aaaxyzxyzxyzddddpor ejemplo. Esto se puede comprimir a 3a3{xyz}4d. Su tarea es escribir un programa de función que, dada una cadena de letras y espacios que distingue entre mayúsculas y minúsculas, lo comprime de manera óptima utilizando la codificación de longitud de ejecución para ejecuciones de varios caracteres.

Puede tomar la entrada a través del argumento de función, STDIN o ARGV y devolver el resultado o imprimirlo en STDOUT.

Las ejecuciones no deben estar anidadas, por lo que aaabbbaaabbbdeben estarlo 3a3b3a3b, no 2{3a3b} . Es decir, la cadena debe estar codificada (o decodificada) en una sola pasada.

Consecuencias de la compresión óptima

Algunos ejemplos donde la aplicación ingenua de la codificación de longitud de ejecución puede conducir a resultados subóptimos:

  • abab no debe ser "comprimido" a 2{ab}
  • aaaabcdeabcdeno debe ser comprimido 4abcdeabcdesino en su 3a2{abcde}lugar.

Si hay dos versiones óptimas (por ejemplo, aay 2ao abcabcy 2{abc}) cualquiera de los resultados está bien.

Ejemplos

Input              Output

aa                 aa -or- 2a
aaaaaAAAAA         5a5A
ababa              ababa
abababa            a3{ba} -or- 3{ab}a
foo foo bar        2{foo }bar
aaaabcdeabcde      3a2{abcde}
xYzxYz             xYzxYz -or- 2{xYz}
abcabcdefcdef      abcab2{cdef}
pppqqqpppqqq       3p3q3p3q
pppqqqpppqqqpppqqq 3{pppqqq}

Puntuación

Cada idioma es una competencia separada en cuanto a quién puede escribir la entrada más corta, pero el ganador general sería la persona que gane la mayoría de estas subcompeticiones. Esto significa que una persona que responde en muchos idiomas poco comunes puede obtener una ventaja. El golf de código es principalmente un factor decisivo para cuando hay más de una solución en un idioma: la persona con el programa más corto obtiene crédito por ese idioma.

Si hay un empate, el ganador sería la persona con la mayor cantidad de envíos de segundo lugar (y así sucesivamente).

Reglas, restricciones y notas

Mantenga todas sus presentaciones diferentes contenidas en una sola respuesta.

Además, no hay travesuras con básicamente la misma respuesta en dialectos de idiomas ligeramente diferentes. Seré el juez en cuanto a qué presentaciones son lo suficientemente diferentes.

Tabla de clasificación actual

Esta sección se actualizará periódicamente para mostrar la cantidad de idiomas y quién lidera cada uno.

  • C # (265) - edc65
  • JavaScript (206) - edc65
  • Python (214) - Voluntad
  • VB.NET (346) - edc65

Ranking de usuarios actuales

  1. edc65 (3)
  2. Voluntad (1)
Martin Ender
fuente

Respuestas:

1

JavaScript (E6) 206

Casi seguro de que es óptimo. Comienzo a tratar de codificar la cadena más larga con la ganancia máxima, y ​​codifico recursivamente lo que queda a la izquierda y a la derecha. Después de cada intento mantengo el resultado más corto.

Notas de golf (JS específico)

  • Pseudo argumentos en lugar de locales (para recursión)
  • Compare longitudes usando un índice fuera de límites que le da 'indefinido'
R=(s,n=s,d=s.length>>1,w,i,j,c)=>{
  for(;d;--d){
    for(i=-1;s[d+d+i++];){
      w=s.slice(i,j=i+d);
      for(r=1;w==s.substr(j,d);j+=d)++r;
      c=d>1?r+'{'+w+'}':r+w,
      // c[d*r-1]|| /* uncomment this line (+10 bytes) to have faster response
      n[(c=R(s.slice(0,i))+c+R(s.slice(j))).length]&&(n=c)
    }
  }
  return n
}

Prueba en la consola FireFox / FireBug

;['aa','aaaaaAAAAA','ababa','abababa','foo foo bar', 'aaaabcdeabcde',
  'xYzxYz', 'abcabcdefcdef', 'pppqqqpppqqq','pppqqqpppqqqpppqqq']
.forEach(x=>console.log(x+' -> '+R(x)))

Salida

aa -> aa
aaaaaAAAAA -> 5a5A
ababa -> ababa
abababa -> 3{ab}a
foo foo bar -> 2{foo }bar
aaaabcdeabcde -> 3a2{abcde}
xYzxYz -> xYzxYz
abcabcdefcdef -> abcab2{cdef}
pppqqqpppqqq -> 3p3q3p3q
pppqqqpppqqqpppqqq -> 3{pppqqq}

C # (.NET 4.0) 265

Exactamente el mismo algoritmo

string R(string s)
{
  string n=s,c,w;
  int l=s.Length,d=l/2,i,j,r;
  for(;d>0;--d)
  {
    for(i=0;d+d+i<=l;i++)
    {
      w=s.Substring(i,d);
      for(j=i+d,r=1;j+d<=l&&w==s.Substring(j,d);j+=d)++r;
      c=d>1?r+"{"+w+"}":r+w;
      // if(c.Length<d*r){ // uncomment this line for faster execution
        c=R(s.Substring(0,i))+c+R(s.Substring(j));
        n=c.Length<n.Length?c:n;
      //} // and this one of course
    }
  }
  return n;
}

Pruebe en LinqPad, modo 'programa C #', agregue un main después de la función R

void Main()
{
  string[] test = {"aa","aaaaaAAAAA","ababa","abababa","foo foo bar","aaaabcdeabcde",
  "xYzxYz","abcabcdefcdef","pppqqqpppqqq","pppqqqpppqqqpppqqq"};
  test.Select(x => new { x, r=R(x) }).Dump("Result");
}

Misma salida

VB.Net (.NET 4) 346 (probablemente)

Mismo algoritmo y misma biblioteca, pero el idioma es lo suficientemente diferente

No puedo estar seguro sobre el conteo de bytes, ya que Visual Studio sigue formateando el código y agregando espacios.

Notas de golf: mejor usa algo más

function R(s as string)

  dim n=s,c,w
  dim l=s.Length,i,j,d
  for d=l\2 to 1 step-1
    for i=0 to l-d-d
      w=s.Substring(i,d)
      j=i+d
      r=1
      do while (j+d<=l andalso w=s.Substring(j,d))
        r=r+1
        j=j+d
      loop
      c=if(d>1,r & "{" & w & "}",r & w)
      if(c.Length<d*r) then
        c=R(s.Substring(0,i))+c+R(s.Substring(j))
        if c.Length<n.Length then n=c
      end if
    next
  next
  return n

end function
edc65
fuente
Puede deshacer la adición de espacios. Si escribe un carácter que lo hace formatear, presione ctrl-z para deshacer el formateo. Significa dos caracteres en lugar de uno cada cierto tiempo, pero es mejor que eliminar todos los espacios y avances de línea después.
Jerry Jeremiah
3

Python 214

def t(s):
 b=s;l=len;r=range(1,l(s))
 for i in r:
  p=s[:i];b=min(b,p+t(s[i:]),key=l);x=1
  for j in r:k=i*j+i;x*=p==s[i*j:k];b=min(b,(b,''.join((`j+1`,"{"[i<2:],p,"}"[i<2:],t(s[k:]))))[x],key=l)           
 return b

(la sangría del segundo nivel es pestaña)

Como se trata de , este es el enfoque recursivo ingenuo sin salida anticipada, por lo que es realmente muy lento.

Será
fuente