Un cuadrado latino es un cuadrado que tiene símbolos en las filas o columnas sin repetida: .
13420
21304
32041
04213
40132
Y como muchos jugadores de Sudoku saben, no necesitas todos los números para deducir los números restantes.
Su desafío es comprimir un cuadrado latino en la menor cantidad de bytes posible. Debe proporcionar uno o dos programas que comprimen / descomprimen.
Diversa información:
- Los números utilizados siempre serán
0..N-1
, dondeN
es la longitud del borde del cuadrado, yN<=25
- En la descompresión, el cuadrado latino debe ser idéntico a la entrada.
- Sus programas deberían poder (des) comprimir cualquier cuadrado latino (dentro del tamaño cuadrado máximo), no solo los que he proporcionado. Las relaciones de compresión también deberían ser similares.
- En realidad, debe ejecutar la compresión y el descompresor para obtener su puntaje (sin tiempos de ejecución de fin de universo)
Los casos de prueba se pueden encontrar en github . Su puntaje es el tamaño total de los casos de prueba comprimidos.
EDITAR: A partir de las 20:07 del 7 de julio, actualicé los casos de prueba (para solucionar un problema de generación). Vuelva a ejecutar su programa en los nuevos casos de prueba. Gracias Anders Kaseorg .
code-challenge
compression
Nathan Merrill
fuente
fuente
0
aunquen-1
:)n
diferentes símbolos. : PRespuestas:
Python,
1281.3751268.625 bytesCodificamos el cuadrado latino "decisión" a la vez, donde cada decisión es de una de estas tres formas:
En cada paso, hacemos todas las inferencias lógicas que podemos basándonos en decisiones anteriores, luego tomamos la decisión con el menor número de opciones posibles, que por lo tanto toman el menor número de bits para representar.
Las opciones son proporcionadas por un decodificador aritmético simple (div / mod por el número de opciones). Pero eso deja algo de redundancia en la codificación: si k decodifica a un cuadrado donde el producto de todos los números de opciones era m , entonces k + m , k + 2⋅ m , k + 3⋅ m , ... decodifica al mismo cuadrado con algún estado sobrante al final.
Aprovechamos esta redundancia para evitar codificar explícitamente el tamaño del cuadrado. El descompresor comienza tratando de decodificar un cuadrado de tamaño 1. Cada vez que el decodificador termina con el estado restante, arroja ese resultado, resta m del número original, aumenta el tamaño en 1 e intenta nuevamente.
Salida:
fuente
np.stack()
. En este caso, se puede reemplazar connp.array([…])
, y lo he hecho en la versión actual.MATLAB,
3'062.52'888.125 bytesEste enfoque simplemente abandona la última fila y la última columna del cuadrado, y convierte cada entrada en palabras de cierta profundidad de bits. La profundidad de bits se elige mínima para el cuadrado de tamaño dado. (Sugerencia de @KarlNapf) Estas palabras se agregan entre sí. La descompresión es justo lo contrario.
La suma para todos los casos de prueba es 23'105 bits o 2'888.125 bytes. (Todavía se mantiene para los casos de prueba actualizados, ya que el tamaño de mis salidas solo depende del tamaño de la entrada).
fuente
n=9..16
4 bits son suficientes.Python 3, 10772 bits (1346.5 bytes)
Toma 0.1 segundos para comprimir y descomprimir los casos de prueba combinados.
Verifique el puntaje en Ideone .
fuente
len(possible)
es 1 ypossible.index(rows[i][j])
es 0 , por lo que ese símbolo se codifica sin costo.J , 2444 bytes
Se basa en la construcción
A.
para convertir ay desde una permutación de enteros [0, n) y un índice de permutación.Comprimir, 36 bytes
La entrada es una matriz 2D que representa el cuadrado latino. Cada fila se convierte en un índice de permutación, y ese índice se convierte en una lista de 255 dígitos base y se reemplaza con un valor ASCII. Cada cadena se une con el carácter ASCII en 255.
Descomprimir, 45 bytes
Divide la cadena de entrada en cada valor ASCII de 255 y analiza cada grupo como 255 dígitos base. Luego, usando el número de grupos, cree una lista de enteros [0, longitud) y permútala de acuerdo con cada índice y devuélvala como una matriz 2d.
fuente
Python,
605245213556 bytescompress
toma el cuadrado como una cadena multilínea, al igual que los ejemplos y devuelve una cadena binaria, mientras quedecompress
hace lo contrario.Retire la última fila + columna y cierre el resto.
base64
no parece necesariofuente
Python 3, 1955 bytes
Otro más que usa índices de permutación ...
salida
fuente
Python3 -
3,5723,581 bytesdataCompress
toma una lista de tuplas de enteros y devuelve una cadena.dateDeCompress
toma una cadena y devuelve una lista de tuplas de enteros.En resumen, para cada línea, este programa toma ese índice de permutación de líneas y lo guarda en la base 36. La descompresión lleva mucho tiempo con grandes entradas, pero la compresión es realmente rápida incluso en grandes entradas.
Uso:
dataCompress([(2,0,1),(1,2,0),(0,1,2)])
resultado:
c|4|3|0
dataDeCompress("c|4|3|0")
resultado:
[(2, 0, 1), (1, 2, 0), (0, 1, 2)]
fuente
permutations
llamadas enlist
llamadas:permutations
devuelve un generador, que genera perezosamente todas las permutaciones, pero si intenta convertirlo en unlist
, genera ansiosamente todas las permutaciones, lo que toma Un largo tiempo.O(n)
tiempo, en lugar delO(n!)
enfoque de fuerza bruta de verificar todas las permutaciones .Java, 2310 bytes
Convertimos cada fila del cuadrado a un número que represente qué permutación lexicográfica está usando números factorados, también conocido como sistema de números factoriales , que es útil para numerar permutaciones.
Escribimos el cuadrado en un archivo binario donde el primer byte es el tamaño del cuadrado, y luego cada fila tiene un byte para el número de bytes en la representación binaria de un BigInteger de Java, seguido de los bytes de ese BigInteger.
Para invertir el proceso y descomprimir el cuadrado, leemos el tamaño y luego cada BigInteger, y usamos ese número para generar cada fila del cuadrado.
Permutor está adaptado de una clase que escribí hace unos años para trabajar con permutaciones:
Uso:
Con un cuadrado latino adentro
latin.txt
, comprímalo:Y descomprimirlo:
fuente