Resolver una transformación Diagonal Burrows-Wheeler

11

Introducción

En este desafío, resolverás transformaciones diagonales de Burrows-Wheeler. Aquí hay una descripción general de lo que es una transformación diagonal de Burrows-Wheeler. Para codificar un mensaje, primero debe garantizar que tenga una longitud impar (es decir, 5, 7, 9, etc.). Luego haces una cuadrícula, npor n, donde nestá la longitud del mensaje. La primera fila es el mensaje original. Cada fila después de eso es la fila de arriba, pero cambió 1 carácter a la izquierda con el primer carácter moviéndose hacia atrás. Por ejemplo:

Hello World
ello WorldH
llo WorldHe
lo WorldHel
o WorldHell
 WorldHello
WorldHello 
orldHello W
rldHello Wo
ldHello Wor
dHello Worl

Luego, toma cada letra en la diagonal NW a SE y la coloca en una nueva cadena:

Hello World  H
ello WorldH  l
llo WorldHe  o
lo WorldHel  W
o WorldHell  r
 WorldHello  d
WorldHello   e
orldHello W  l
rldHello Wo  (space)
ldHello Wor  o
dHello Worl  l

Su mensaje codificado es HloWrdel ol. Para decodificar, primero tome la longitud del mensaje codificado, agregue 1 y divida por 2. Llamemos a este número x. Ahora que sabemos x, comenzando en la primera letra, cada letra es xposterior a la última, dando vueltas. Por ejemplo:

H   l   o   W   r   d   e   l     o   l
1   

Then...

H   l   o   W   r   d   e   l     o   l
1                       2

And again...

H   l   o   W   r   d   e   l     o   l
1   3                   2

Until you get...

H   l   o   W   r   d   e   l       o   l
1   3   5   7   9  11   2   4   6   8  10

¡Ahora solo reorganiza las letras en el orden correcto para obtenerlas Hello World!

Desafío

Su desafío es escribir dos programas, funciones o uno de cada uno. Sin embargo, ambos deben usar el mismo idioma. El primer programa aceptará una cadena como entrada a través de STDIN, argumentos de programa o parámetros de función y la codificará utilizando este método. El segundo programa aceptará una cadena como entrada a través de STDIN, argumentos de programa o parámetros de función y la decodificará utilizando este método.

Requisitos

Primer programa / función

  • Una sola entrada de cadena usando cualquier método mencionado anteriormente.
  • Debe codificar la cadena utilizando un estilo de transformación diagonal Burrows-Wheeler.

Segundo programa / función

  • Una sola entrada de cadena usando cualquier método mencionado anteriormente.
  • Debe decodificar la cadena con un estilo de transformación diagonal Burrows-Wheeler.

Restricciones

  • No puede utilizar ninguna función incorporada o externa que realice esta tarea.
  • Las lagunas estándar no están permitidas.
  • Ambos programas / funciones deben estar en el mismo idioma.

Puntuación

Este es el código de golf, por lo que gana el programa más corto en bytes .

Si necesito agregar más información, ¡deja un comentario!

GamrCorps
fuente
2
¿Tenemos que convertir la cadena de entrada de longitud par a longitud impar?
Optimizador
55
Esta no es una transformación de Burrows-Wheeler.
FUZxxl
3
Una transformación de Burrows-Wheeler es diferente porque la matriz de todas las rotaciones se ordena lexicográficamente antes de tomar los últimos elementos.
FUZxxl
@Optimizer no es necesario.
GamrCorps

Respuestas:

12

CJam, (4 + 8 =) 12 bytes

Programa de codificación:

q2/z

Pruébalo en línea aquí

Programa de decodificación:

q_,2/)/z

Pruébalo en línea aquí

Cómo (o más bien, por qué) funcionan :

La transformación Diagonal Burrows-Wheeler es básicamente cualquier otro carácter de la cadena, con ajuste desde el final. Si tratamos la cadena como una matriz 2D de 2 columnas, simplemente se reduce a tomar la transformación de la matriz. Ejemplo:

Hello World

Se representa como matriz 2D como

He
ll
o 
Wo
rl
d

Ahora, simplemente leyéndolo en columna, dé:

HloWrdel ol

Cuál es la transformación de Burrows-Wheeler.

La decodificación es simplemente inversa del proceso, escribe la cadena como una matriz 2D de 2 filas y lee en columna.

Expansión de código :

Codificador:

q          "Read the input";
 2/        "divide it into sub arrays of 2 characters";
   z       "Take transform";

Descifrador:

q_,        "Read the input, take copy and get length of copy";
   2/      "Divide the length by 2";
     )/    "Increment and split the input into two rows";
       z   "Take transform";
Optimizador
fuente
7

Python 2, 61 bytes

E=lambda x:x[::2]+x[1::2]
D=lambda y:(-~len(y)/2*y)[::len(y)/2+1]

ECifra y Ddescifra. No estoy contando el E=y D=para el puntaje.

El descifrado toma todos nlos caracteres que se envuelven, donde nes la mitad de la longitud de la cadena redondeada. La razón por la que esto se invierte es eso, 2y nson inversos en el módulo de la longitud de la cadena, por lo que tomar cada nth carácter se invierte tomando cada 2nd.

Si se permitiera usar una sola función, podría hacer 44 bytes

def F(x,b):n=1+len(x)**b>>b;return(n*x)[::n]

Cifra cuando bes Falsey descifra cuando bes True. La expresión 1+len(x)**b>>bes igual a [2,len(x)/2+1][b].

xnor
fuente
4

J, 10 + 10 = 20

   ({~#|2*i.@#) 'Hello World'
HloWrdel ol

   (/:#|2*i.@#) 'HloWrdel ol'
Hello World

(Las llaves circundantes no se cuentan en la puntuación, ya que no forman parte de la definición de la función).

Gracias por FUZxxl por una mejora de 3 bytes.

Ahora se muestra muy bien que las dos funciones son inversas, ya que la primera toma caracteres de las posiciones definidas por la lista #|2*i.@#y la segunda función ordena los caracteres usando la misma lista como ordenando.

Pruébelo en línea aquí.

randomra
fuente
El primero de ellos se puede hacer de 10 caracteres, así: {~#|2*i.@#.
FUZxxl
@FUZxxl Gracias, actualizado. Ahora la relación entre las dos funciones se muestra muy bien.
randomra
3

Pyth - 5 + 11 = 16 bytes

¡Noté un patrón! ~ Danza feliz ~ La transformación es realmente solo un bucle a través de la cadena que selecciona todos los demás elementos. Solo funciona en modo impar ya que de lo contrario nunca obtendría la mitad de los elementos. Esto es equivalente a rotar una matriz de 2 de ancho.

Codificador:

%2*2z

El corte de pasos de Python no gira, así que repetí la cuerda.

%2      Take every other elements
 *2z    Double input string

Descifrador:

K/hlz2%K*Kz

Una vez más, no hay vuelta para cortar en rodajas.

K/hlz2       K=length of (input+1)/2
%K           Every kth element
 *Kz         From K*the input
Maltysen
fuente
@FryAmTheEggman Estoy bastante seguro de que solo se supone que toma una cadena de longitud impar. Fue al comienzo de la descripción.
Maltysen
Ups, lo siento. : S
FryAmTheEggman
2

GNU sed -r, (20 + 104 + 1) = 125

El +1 extra en el puntaje es para la opción -r sed. Se suponen cadenas de entrada de longitud impar.

Codificador:

s/.*/&&/
s/(.)./\1/g
  • Duplica la cadena de entrada
  • Suelta cada personaje impar (contando desde 1)

Descifrador:

El decodificador se utiliza :como un marcador temporal, por lo que si aparece en la cadena de entrada, obtendrá un comportamiento indefinido. Si la cadena de entrada está restringida a los 95 caracteres ASCII, estos marcadores se pueden reemplazar con algo fuera del rango ASCII (por ejemplo, BEL 0x7) para solucionar esto.

s/.*/:&:/
:l;s/:(.)(.+)(.):/\1:\2:\3/;tl
s/:(.*)/\1:/
:m;s/(.)(.*):(.?)(.*):(.*)/\2:\4:\5\1\3/;tm
s/://g
  • Ponga :marcadores al principio y al final de la cadena de entrada.
  • Mezcle el primer personaje hacia :adelante y el segundo :hacia atrás un carácter a la vez hasta que los :marcadores estén a ambos lados del personaje del medio
  • Elimine el primero :y agregue otro :al final dejando "A: B:", donde A es la cadena compuesta de caracteres impares de la entrada de texto sin formato y B es la cadena compuesta de los caracteres pares
  • Agite los caracteres de A y B juntos después del último :para volver a ensamblar la entrada de texto sin formato
  • Eliminar los :marcadores restantes
Trauma digital
fuente
2

JavaScript ES6, 41 + 49 = 90 bytes

Codificador

(t=>t.replace(/./g,(_,o)=>t[o*2%t.length]))('Hello World')

Descifrador

(t=>t.replace(/./g,(_,o)=>t[-~(l=t.length)/2*o%l]))('HloWrdel ol')

Estas son funciones anónimas, por lo que solo cuento el código dentro de los paréntesis porque esa es la definición completa de la función. Pruébelo con el fragmento a continuación: (modificado para usar ES5)

NinjaOsoMono
fuente
¿Qué tal esto [t=>t.replace(/./g,(_,o)=>t[o*2%t.length]),t=>t.replace(/./g,(_,o)=>t[(1+(l=t.length))/2*o%l])]? Lo usas como [...][0]('encode string')y [...][1]('decode string'). ¡No hay nada que diga que esto no se puede hacer! Y ahorras 1 byte.
Ismael Miguel
Gracias, pero dice escribir 2 funciones, y no creo que esto cuente.
NinjaBearMonkey
Eso sigue siendo 2 funciones. Las reglas no especifican nombres o formas de acceder a las funciones. Solo dice que debes usar 2 funciones.
Ismael Miguel
1
@IsmaelMiguel Ahora que lo pienso, creo que las funciones anónimas están permitidas por sí mismas, por lo que usar eso me ahorra aún más bytes.
NinjaBearMonkey
Me alegra que hayas reducido el recuento de bytes.
Ismael Miguel