Codificar - Mezclar - Decodificar


23

Reto

Su tarea es codificar un número entero como una cadena de caracteres ASCII , luego decodificarlo con éxito después de que dicha cadena se haya barajado aleatoriamente.

Escribirás dos programas / funciones , que se denominarán codificador y decodificador. .

Codificador

  • Entrada: un número entero n en el rango [0,2311] .
  • Salida: una cadena s de ASCII caracteres (no necesariamente imprimible).

Descifrador

  • Entrada: una permutación aleatoria s de la cadena s .
  • Salida: el entero n .

Tanteo

Sea A la longitud máxima de s en todos los valores posibles de n . Si el codificador actúa de manera no determinista (lo cual está permitido, ver más abajo), entonces la A será la longitud máxima de s que puede ocurrir (posiblemente ).

Sea LE la longitud del codificador en bytes y LD la longitud del decodificador en bytes.

Entonces su puntaje es A(LE+LD) .

La victoria se otorga a la presentación la puntuación más baja .

Límite de tiempo

Hay un límite de tiempo algo arbitrario de 1 minuto en el tiempo de ejecución tanto del codificador como del decodificador para un solo caso de prueba (es decir, un único valor de n ).

El objetivo es evitar una solución que encuentre que la fuerza bruta codifica enumerando todas las secuencias con ciertas propiedades. Si su solución hace algo más inteligente que eso, lo más probable es que se ajuste a la restricción de tiempo y se considerará válida. Del mismo modo, si funciona en TIO para algunos valores seleccionados al azar de n , se considerará válido. De lo contrario, lo probaré en mi máquina, pero tenga en cuenta que si su solución es pura fuerza bruta, seguramente fallará.

Reglas

  • El codificador y el decodificador deben estar escritos en el mismo idioma .
  • El decodificador debe generar el número entero correcto n para cada permutación posible s de la cadenas devuelta por elcodificador.
  • El codificador y el decodificador se no se les permite compartir información de cualquier forma (por ejemplo, por medio de variables globales o archivos).
  • La salida del codificador no necesita ser determinista (es decir, la misma entrada n puede producir diferentes cadenas de salida si el codificador se ejecuta varias veces), pero el decodificador siempre debe adivinar el número entero correcto n .
  • El codificador y el decodificador pueden tomar y devolver el número entero n de cualquier manera conveniente (por ejemplo, si n=14 está bien que la entrada sea 14, "14"o [1,4]).
  • El codificador puede emitir la cadena s ya sea por impresión en stdout o por devolver una cadena, una lista / matriz de caracteres o una lista / matriz de enteros en el intervalo [0,127] ; tenga en cuenta que el decodificador recibirá como entrada una permutación de s devuelta por el codificador , por lo que debe aceptar la cadena s en el mismo formato que s .
  • Las lagunas estándar están prohibidas.
  • Si es posible, explique cómo funciona su código y por qué el puntaje que reclama es correcto.

Ejemplo

Suponga que n=14 .

  • El codificador recibe 14como entrada. Puede salir "qwerty".
  • El decodificador recibe una permutación "qwerty"como entrada, por ejemplo "tweyqr". Debe salir14 (en cualquier formato conveniente).

El codificador podría haber regresado[113,119,101,114,116,121] , en cuyo caso el decodificador habría recibido (por ejemplo) [116,119,101,121,113,114].

Tenga en cuenta que la cadena devuelta por el codificador también puede incluir caracteres ASCII no imprimibles (pero siempre en el rango[0x00, ..., 0x7F] ).


Seguramente la longitud de salida no puede ser infinita, no puedes mezclar una cadena infinita
H.PWiz

@ H.PWiz No, no puede, pero la longitud puede ser ilimitada si el codificador no es determinista
Delfad0r

"El codificador y el decodificador no pueden compartir información de ninguna manera" ¿Esto incluye funciones auxiliares? es decir, una función personalizada que calcula N factorial más tres (ejemplo aleatorio)
pizzapants184

¿Puede nuestro codificador devolver una cadena / lista vacía?
pizzapants184

2
@Kroppeb Sí, a partir de ahora las reglas dicen que debe contar los bytes dos veces. Sin embargo, estoy muy interesado en ver una presentación con dos programas idénticos.
Delfad0r

Respuestas:


12

Gelatina , (17 bytes + 18 bytes) × longitud 6 = 210 puntos

b36µỤỤ + × 3µŒ¿b3U + Ṣ
Ṣ: 3_J
Ṣ% 3Uḅ3œ? Çḅ36

Pruébalo en línea! (o con información adicional de depuración)

Después de haber intentado resolver este desafío con el objetivo de la condición de victoria establecida, pensé que sería interesante optar por una condición de victoria alternativa hipotética: dado una longitud máxima posible mínima para la salida.

Explicación

Codificación

El primer paso en la codificación es representar la entrada como base 36 ( b36). 36 6 = 2176782336> 2147483647, por lo que habrá como máximo 6 dígitos en el resultado, cada uno de los cuales está en el rango 0–35.

A continuación, transformamos esto en una representación que contiene 6 dígitos diferentes . Hay varios algoritmos posibles para esto, pero el que se usa aquí es agregar 1 al dígito más pequeño, 2 al segundo más pequeño, 3 al tercero más pequeño, y así sucesivamente. Esto significa que si dos dígitos fueran iguales, uno de ellos se considerará arbitrariamente más pequeño y, por lo tanto, se volverán diferentes; y obviamente, este algoritmo no puede causar que dos dígitos diferentes se vuelvan iguales. Para representar esto en Jelly, utilizamos ("ordenar índices por valores") para obtener una lista de los índices en orden; para agregar el original a la nueva lista. El resultado es una representación del número de entrada como seis dígitos diferentes en el rango 1-41 (mínimo 0 + 1, máximo 35 + 6).nuevamente para invertir eso, mapeando efectivamente cada elemento del original a su posición en orden ordenado; yµ…+

Luego dividir esto en otra forma: una ordenada lista de dígitos en el rango 1-41, junto a un número del 1 al 720 que representa cuál de las 720 permutaciones posibles los dígitos estaban en (El. Œ¿Y extraer el número de permutación y ordenados lista respectivamente.)

Finalmente, convertimos el número del 1 al 720 en la base 3 ( b3), lo invertimos ( U) y codificamos los seis dígitos de la base 3 y los seis dígitos del 1 al 41 empaquetándolos en un solo carácter ASCII usando el divmod inverso (el valor de el carácter mod 3 es el dígito base 3, el valor dividido entre 3 es el 1-41 dígito). El rango posible de resultados es (1 × 3) + 0 = 3 como mínimo, y (41 × 3) + 2 = 125 como máximo, dentro de nuestro rango ASCII. El empaquetado se realiza a través de ×3y +, junto con un adicional µpara asegurarse de que cada comando opere en el bit de datos correcto. (Aquí hay un pequeño truco de golf, ya que hacemos la multiplicación por 3 antes de extraer la permutación; eso ahorra la necesidad de gastar un byte en un personaje de agrupación).

Por cierto, la razón para invertir el número base 3 es porque puede tener menos dígitos que el número 1–41. (No puede tener más; ¡el número más pequeño para el que n !> 3 n está ligeramente por encima de 6.) Jelly inserta efectivamente ceros finales al sumar dos números de diferentes longitudes, para que coincidan; los ceros finales afectarían la interpretación del número, pero los ceros iniciales no lo harían, por lo que lo inverso se usa para garantizar que los ceros adicionales terminen en algún lugar que no estropee nuestra respuesta.

Descodificación

El primer paso en la decodificación es extraer los dos números (el número base 3 y el número 1-41). Podemos obtener sus dígitos con bastante facilidad con division ( :3) y modulo ( %3) respectivamente, pero ¿cómo saber en qué orden estaban? Bueno, el número 1–41 tenía sus dígitos en orden ordenado, y los dígitos en las posiciones correspondientes de los dos números se almacenaban en los mismos caracteres; por lo tanto, podemos determinar en qué orden se barajaron los dígitos del número 1–41 (observando sus valores relativos) y saber que los dígitos del número base 3 deben haberse barajado de la misma manera. De hecho, debido a que los caracteres de nuestra codificación ASCII se ordenan de la misma manera que los dígitos del número 1–41 (todos eran distintos y son más significativos que los números de la base 3),. Entonces, ambas extracciones comienzan con , seguidas de %3o :3según corresponda.

Si bien los dígitos del número 1–41 todavía están ordenados, tenemos una forma muy conveniente / concisa de volver a los 0–35 dígitos de la base 36; solo resta 1 del primero, 2 del segundo, 3 del tercero, y así sucesivamente. En Jelly, podemos hacer eso con _J("índice de resta").

Mientras tanto, en la otra rama de la decodificación, revertimos los dígitos del número de la base 3 nuevamente en orden ( U), y lo convertimos de la base 3 nuevamente en un índice de permutación con ḅ3.

Entonces podemos combinar las dos ramas con œ?Ç; œ?significa "permutar dado este índice de permutación", y Çsignifica "el resultado de aplicar la línea de arriba", es decir, es lo que le dice a Jelly que ejecute ambas líneas por separado en la misma entrada.

Lo que tenemos ahora son los dígitos del número original, en la base 36 (debido a _J), y en el orden original (debido a la œ?), por lo que simplemente podemos hacer una ḅ36conversión de la base 36 a un solo entero.

Comentario

El tio! el enlace anterior usa 312699167 como el número para codificar. Este número en la base 36 es [5, 6, 6, 8, 7, 35], y por lo tanto muestra todos los aspectos de la codificación: el 35 prueba el límite del rango 0-127 que tenemos; los duplicados 6 prueban la resolución de dígitos idénticos en la base original 36; y el hecho de que los dígitos están casi (pero no del todo) ordenados significa que el número de permutación es muy pequeño, lo que le da muchos menos dígitos que el número base 36 y, por lo tanto, muestra la necesidad de invertirlo antes de agregarlo al original.

Es realmente conveniente cómo encajan todas las constantes aquí. 36 6 es solo lo suficientemente alto como para caber 2 31 , 3 6 es solo lo suficientemente alto como para caber 6 !, y (36 + 6) × 3 es solo lo suficientemente alto como para caber dentro de las 128 posibilidades que tenemos. (La última restricción aquí es la menos estricta, porque podríamos usar la indexación 0 en lugar de la indexación 1 para usar caracteres en el rango 0-2. Aún así, eso solo daría suficiente espacio para usar 37 como base en lugar de de 36.)


9

Gelatina , ( 4 3 bytes + 6 5 bytes) × longitud 8 = 80 64 puntos

b⁴Ä
ṢŻIḅ⁴

Pruébalo en línea!

Gelatina , ( 2 1 byte + 4 3 bytes) × longitud 10 = 60 40 puntos

UNA
ṢŻI

Pruébalo en línea!

Explicación

Solución 1

Esto está usando un algoritmo diferente de la mayoría de las otras respuestas. Comenzamos codificando el valor en hexadecimal ( b⁴), como con las otras respuestas, luego tomamos una suma acumulativa ( Ä). Cada entrada dará claramente una salida diferente (ya que ambas operaciones son reversibles), y dado que la codificación hexadecimal contendrá como máximo 8 dígitos cuyos máximos son 7 (para el octavo último dígito) y 15 (para el último al séptimo) últimos dígitos), el número máximo en la lista de salida será 7+ (7 × 15) = 112, menos que los 127 requeridos por la pregunta. Además, la salida necesariamente estará ordenada, lo que nos permitirá revertir la combinación aleatoria.

Para el decodificador, primero revertimos el shuffle con un sort ( ); luego invierta la suma acumulativa, anteponiendo un cero ( Ż) y tomando la diferencia de pares consecutivos ( I); luego vuelva a convertir de hexadecimal ( ḅ⁴).

Solución 2

La pregunta en realidad nos permite tomar la entrada como una lista de dígitos (presumiblemente decimales), para que podamos "engañar" simplemente eliminando la conversión de base; el número máximo utilizado en la salida será 2 + (9 × 9) = 83 (en realidad 82 porque 2999999999 está fuera de rango, por lo que la peor entrada posible es 1999999999). La codificación resultante es bastante terrible a medida que avanzan las codificaciones para este problema, pero tiene la ventaja de ser muy breve para generar, lo que supera la verbosidad de la codificación.

Esta respuesta se parece tanto a hacer trampa que no es mi solución principal para este problema, pero parece que vale la pena agregarla porque técnicamente cumple con las reglas y produce una mejor puntuación.

Comentario

Tengo algunos algoritmos en mente para obtener menos de la longitud 8, pero parece poco probable que pueda implementar un algoritmo de longitud 7 en ≤9 bytes (sin trampa) o ≤5 bytes (trampa), por lo que según la puntuación en la pregunta, esto Es probablemente la mejor manera de hacerlo. (De todos modos, podría intentar una solución para el desafío alternativo "minimizar la duración de la codificación", solo por diversión).

A diferencia de algunas de las soluciones, el uso de 16 como base aquí no es crítico; Hay muchos otros números que funcionarían para una solución de longitud 8 (por ejemplo, 18). Elegí 16 para la primera solución simplemente porque Jelly tiene una forma de 1 byte para representar eso, y otras bases viables tendrían que usar múltiples bytes del programa. Por supuesto, la segunda solución necesita usar 10 como base para explotar la escapatoria.

Gracias a @Dennis por señalar algunos nuevos comandos de Jelly que hicieron que este algoritmo fuera aún más difícil de escribir.


3
Äes la abreviatura de +\, Żes la abreviatura de 0;.
Dennis

7

Lenguaje de programación de Shakespeare , 10 * (264 + 494) = 8650 7910 7580

Codificador: 264 bytes

,.Ajax,.Ford,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Open mind.Be you nicer zero?You be the sum ofyou the product ofthe sum ofI a big big pig the sum ofa big big big big cat a big big pig.If soSpeak thy.Ford:You are the sum ofyou a cat.If soLet usAct I.

Pruébalo en línea!

Decodificador: 494

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Open mind.Is you nicer a pig?If soRemember you.If soLet usAct I.Scene V:.Ford:Remember I.Ajax:Recall.Is you worse the sum ofPage twice the sum ofa big big cat a cat?If soYou be the difference betweenyou Page.If soOpen heart.If notlet usScene V.Scene X:.Ford:Recall.Ajax:Be I nicer zero?If soRemember I.If soLet usScene X.[Exit Ajax][Enter Page]Ford:You be the sum ofyou twice twice the sum ofa big big cat a pig.Let usAct I.

Pruébalo en línea!

Esto fue una cosa.

El codificador codifica cada dígito como el dígito más el índice del dígito multiplicado por doce. El decodificador almacena toda la entrada en la memoria del Ford y luego realiza un bucle sobre un contador, emitiendo y eliminando cada dígito por debajo del contador * 12 + 10.

Explicación:

Codificador

,.Ajax,.Ford,.Act I:.Scene I:.      Boilerplate introducing the two characters
[Exeunt][Enter Ajax and Ford]       Enter the two characters Ajax and Ford
                                    Ford will be handling the input
                                    Ajax will be the counter
Ajax:Open mind.                     Set Ford to the next character of input
Be you nicer zero?                  Check if it is EOF
You be the sum of                   Set Ford to the sum of 
    you                             His original value (48 to 58)
    the product of                 
          the sum of               
              I                     Ajax's value
              a big big pig         Minus 4 (this handles the offset of 48)
          the sum of                Multiplied by
              a big big big big cat 2^4
              a big big pig.        + -2^2 = 12
                                    This essentially sets Ford to (F+12*(A-4))
If soSpeak thy.                      If not EOF, print Ford's value
Ford:You are the sum ofyou a cat.   Increment Ajax's value
If soLet usAct I.                   If not EOF, Repeat again.

Descifrador

,.Ajax,.Ford,.Page,.Act I:.Scene I:.  Boilerplate introducing three characters
                                      Ajax is the spare stack
                                      Ford is the storage stack
                                      Puck is the counter, increasing by 12
[Exeunt][Enter Ajax and Ford]            Enter Ajax and Ford onto the stage
Ajax:Open mind.                          Get the next character of input
Is you nicer a pig?                      If not EOF
If soRemember you.                         Store the value in Ford's memory
If soLet usAct I.                          And repeat the loop
Scene V:.                                Otherwise move to the next scene
Ford:Remember I.                         Store Ford's value (initially -1 from EOF) in Ajax's memory
Ajax:Recall.                             Get the next value from Ford's memory
Is you worse the sum of                  Is the value smaller than
        Puck                                  Puck's value
        twice the sum ofa big big cat a cat?  + 10 ?
                                              i.e. is it the next digit?
If soYou be the difference betweenyou Puck.   If so, subtract Puck's value from Ford
If soOpen heart.                              And print Ford's value
If notlet usScene V.                     If that was not the digit, repeat
Scene X:.
Ford:Recall.                             Get the next value from Ajax's memory
Ajax:Be I nicer zero?                    Until the -1
If soRemember I.                         Returning the values to Ford's memory
If soLet us Scene X.                     Repeat until Ajax's memory is exhausted
[Exit Ajax][Enter Page]                  Swap Ajax and Page
Ford:You be the sum of                   Set Puck's value to
              you                        Puck +   
              twice twice the sum of     2*2*(
                           a big big cat      4
                           a pig.             -1) = 12
Let usAct I.                             And start from the beginning again, having removed one number

5

Python 2.7, 31 * (52 + 37) = 2759

Codificador ( 69 52 bytes):

lambda n:[chr(i)if n&(1<<i)else""for i in range(32)]

Decodificador ( 41 37 bytes):

lambda s:sum([1<<(ord(c))for c in s])

Almacena todos los bits distintos de cero en el número de entrada como valores ascii. El valor del carácter ascii almacena la posición del bit establecido. Por ejemplo, el valor 'a' significaría que el bit 97 está establecido.

Algunas mejoras, gracias a @ Delfad0r

Pruébalo en línea!


¡Bienvenido a PPGC! Puede soltar el e = y el d = al principio: las funciones anónimas están perfectamente bien. Además, tenga en cuenta que la declaración del problema dice claramente que el codificador puede devolver una lista de enteros en lugar de caracteres, por lo que puede evitar la conversión de entero-> carácter-> entero. Además, puede usar en n&(1<<i)lugar de n&(1<<i)>0y guardar 2 bytes. Finalmente, el límite superior para i(127) es demasiado, 32 es suficiente y ahorra 1 byte.
Delfad0r

1
Indique su puntaje de acuerdo con la sección de Puntuación en la declaración del problema.
Delfad0r

@ Delfad0r ¿La puntuación es correcta ahora? Y gracias por los consejos.
Hein Wessels

Creo que el puntaje se debe a (52+37)*31=2759que el más largo es cuando se establecen los 31 bits.
Jonathan Allan el

El codificador puede ser lambda n:[chr(i)*(n&1<<i>0)for i in range(32)]para guardar 6 bytes.
mypetlion

5

Stax , puntaje 8 × (10 + 9) = 152

Codificador, 10 bytes

Ç·MÉJ'♀τ│½

Ejecutar y depurarlo

16|E{i16*+m Full program, implicit input
16|E        Get hexadecimal digits
    {     m Map:
     i16*+    Add 16 * loop index
            Implicit output as string

El codificador emite la cadena en un orden creciente.

Decodificador, 9 bytes

üL∟n╫k∞‼9

Ejecutar y depurarlo

o{16%m16|E Full program, implicit input
o          Sort string
 {16%m     Module each element by 16
      16|E Interpret as array of hex digits


5

Python 3 , 8 * (45 + 38) = 664

Codificador (45 bytes):

lambda n:[16*i+(n>>4*i)%16 for i in range(8)]

Decodificador (38 bytes):

lambda l:sum(x%16<<x//16*4 for x in l)

Pruébalo en línea!


1
Puede eliminar los espacios antes de "for", lambda l:sum(x%16<<x//16*4for x in l)funciona bien :)
FatalError

44
Esto no funciona. La salida no es ASCII simple (en el rango 0..127)
GB

2
@GB mi error. Lo rompí con mi última edición. Volviendo ahora
Curtis Bechtel

guardar 3 bytes en el codificador: lambda n:[n>>4*i&15|i<<4for i in range(8)]y 1 en el decodificador: lambda l:sum(x%16<<x//16*4for x in l)para una puntuación total de 632
Aaron

4

JavaScript (ES6), 8 * (40 + 32) = 576

El codificador genera una matriz de 0 0 a 8enteros El decodificador toma el mismo formato que la entrada.

Codificador (40 bytes)

E=(n,k=0)=>n?[k|n&15,...E(n>>4,k+16)]:[]

Decodificador (32 bytes)

s=>s.map(c=>s|=c%16<<(c/4&~3))|s

Manifestación

Pruébalo en línea!

¿Cómo?

La entrada se divide en 8 bloques de 4 bits y cada bloque se codifica con 1 entre 16 caracteres posibles. El bit más significativo del último bloque nunca se establece.

       3222222222211111111110000000000
bit:   0987654321098765432109876543210
       \_/\__/\__/\__/\__/\__/\__/\__/
block:  7  6   5   4   3   2   1   0

block #0 is encoded with char. 00 to 0F (NUL to SI)
block #1 is encoded with char. 10 to 1F (DLE to ES)
block #2 is encoded with char. 20 to 2F (' ' to '/')
block #3 is encoded with char. 30 to 3F ('0' to '?')
block #4 is encoded with char. 40 to 4F ('@' to 'O')
block #5 is encoded with char. 50 to 5F ('P' to '_')
block #6 is encoded with char. 60 to 6F ('`' to 'o')
block #7 is encoded with char. 70 to 77 ('p' to 'w')

4

Gelatina , (8 + 9) bytes * 8 longitud máxima = 136

b⁴+J’Ɗ⁴¡

Codificador (el pie de página formatea la lista como Python lo haría para mayor claridad)

Ṣ_J‘Ɗ⁴¡ḅ⁴

Descifrador

Teóricamente es posible tener una longitud máxima de seis, ¿se puede hacer en 22 bytes o menos?

Es imposible con una longitud máxima de cinco desde yo=0 0yo=5 5(127+yo127)=321402081<231-1

¿Cómo?

Ya que 231-1es codificable como 8 dígitos hexadecimales ( 7fffffffo [7,15,15,15,15,15,15,15]) entonces podemos agregar el índice basado en cero de cada dígito hexadecimal multiplicado por 16 para garantizar que dicha conversión esté siempre en orden ordenado mientras se mantienen incluso los valores más a la derecha (es decir [7,15,15,15,15,15,15,15] + [0,16,32,48,64,80,96,112] = [7,31,47,63,79,95,111,127]). La decodificación está invirtiendo este mismo proceso.

Codificador :

b⁴+J’Ɗ⁴¡ - Link: integer, n    e.g. 1234
 ⁴       - literal 16               16          
b        - convert to base          [4,13,2]
       ¡ - repeat...
      ⁴  - ...16 times:
     Ɗ   -   last 3 links as a monad:
   J     -     range of length        [1,2,3]     iter 2    iter 3    ...  iter 16
  +      -     add                    [5,15,5]   [5,16,7]   [5,17,9]  ...  [5,30,35]
    ’    -     decrement              [4,14,4]   [4,15,6]   [4,16,8]  ...  [4,29,34]
         -                                                                 [4,29,34]

Decodificador :

Ṣ_J‘Ɗ⁴¡ḅ⁴ - Link: list of integers   e.g. [29,34,4]
Ṣ         - sort                          [4,29,34]
      ¡   - repeat...
     ⁴    - ...16 times:
    Ɗ     -   last 3 links as a monad:
  J       -     range of length           [1,2,3]
 _        -     subtract                  [3,27,31]   [3,26,29]   [3,25,27]  ...  [3,12,1]
   ‘      -     increment                 [4,28,32]   [4,27,30]   [4,26,28]  ...  [4,13,2] 
        ⁴ - literal 16                    16
       ḅ  - from base                     1234

"dígitos hexadecimales", seguro. ("dígitos usando hexadecimal simple" es más largo, y "dígitos" solo implica decimal.)
Erik the Outgolfer

Lo cambié a pesar de que debería haber sido obvio por el contexto, ya que inmediatamente me referí a los dígitos hexadecimales.
Jonathan Allan el

Su cálculo está desactivado en uno: hay 321402081 combinaciones con reemplazo con una longitud máxima de 5, y 7177979809 con una longitud máxima de 6.
Anders Kaseorg

@AndersKaseorg oops, así es, así que es posible con una longitud máxima de 6 ... ¡dando 22 bytes para jugar!
Jonathan Allan

4

Shakespeare Lenguaje de programación , 31 * (472 + 383 379 344) = 26505 26381 25296

Puntuación anterior: 16909322 * (246 + 217) = 7829016086

Esto todavía es muy alto, pero es lo más bajo en lo que puedo pensar ahora.

Codificador:

,.Ajax,.Ford,.Act I:.Scene I:.[Enter Ajax and Ford]Ajax:Remember a pig.Ford:Listen tothy.Scene V:.Ajax:Remember the remainder of the quotient betweenI a big cat.Ford:You be the quotient betweenyou a big cat.Be you nicer zero?If solet usScene V.Remember a pig.Scene X:.Ajax:Recall.Ford:Am I worse zero?If notremember I.If notlet usScene X.Ajax:You zero.Scene L:.Ford:Recall.Ajax:You be the sum ofyou a cat.Am I nicer zero?If sospeak thy.Am I worse zero?If notlet usScene L.

Pruébalo en línea!

Descifrador:

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:You cat.Ford:Open mind.Remember the sum ofyou I.Scene V:.Ajax:Am I nicer a cat?If soyou be twice you.Ford:If soyou be the sum ofyou a pig.If solet usScene V.[Exit Ford][Enter Page]Page:Recall.Ajax:Am I worse a cat?If notyou be the sum ofyou Ford.If notlet usAct I.Open heart

Pruébalo en línea!

Básicamente, si la cadena contiene un carácter con el código ASCII (n + 1), se establece el enésimo dígito binario.


344 bytes para el decodificador
Jo King

3

Python 3, (208 bytes + 200 bytes) * 6 de longitud = 2448

Pruébalo en línea! (contiene ambos, el byte adicional es la nueva línea entre ellos).

-4 bytes (puntaje -24) utilizando la lista vacía (que permitió que más cosas comenzaran en 0)

Codificador (208 bytes)

def E(n,h=128):
    T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1
    d=l=0
    s=[]
    while n>=T(h,d):
        n-=T(h,d)
        d+=1
    for i in range(d):
        while n>=T(h-l,d+~i):
            n-=T(h-l,d+~i)
            l+=1
        s+=[l]
    return s

Decodificador (200 bytes)

def D(s):
    T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1
    s.sort()
    l=0
    d=len(s)
    n=sum(T(128,D)for D in range(d))
    for i in s:
        for j in range(l,i):
            n+=T(128-j,d-1)
        l=i
        d-=1
    return n

Observaciones:

  • La combinación aleatoria se puede revertir sin pérdidas para listas estrictamente no crecientes (es decir, ordenadas).

  • Las listas numéricas estrictamente no crecientes de la misma longitud se pueden ordenar totalmente (como están en Python).

  • Podemos definir que las listas se ordenan primero por longitud para formar un orden total de todas las listas ordenadas.

  • Podemos formar una secuencia de indexable de estas listas si definimos que los valores sólo son válidos en una lista son números enteros de 0al 127inclusivo (es decir, existe un número finito de listas válidos con longitud L).

Estrategia:

  • Codificador: dado un número N, encuentre la lista Nválida estrictamente no creciente.

  • Decodificador: Dada una lista válida (barajada), ordénela y devuelva su índice en la secuencia de listas válidas.

Explicación de código común:

  • T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1

  • Calcule el númeron th d-simplex

    • Para d=0siempre1

    • Para d=1, n(el número de puntos en una línea de puntos con longitud n)

    • para d=2,yo=1norteyo, (el número de puntos en un triángulo de puntos con longitud lateral n)

    • para d=3,j=1norteyo=1jyo, (el número de puntos en un tetraedro de puntos con longitud lateral n)

Explicación del codificador:

  • def E(n,h=128): d=l=0, s=[]

  • nes el número de entrada, hes el "valor alto" (es decir, el número más alto permitido + 1), des la longitud que será la salida, ses la salida, les el "valor bajo" (comenzando en 0, explicado más adelante)

  • while n>=T(h,d):` n-=T(h,d)`d+=1

  • Hay listas de T(h,d)longitud válidas d, y nuestro cálculo es más fácil si nes un índice relativo a la lista [0]*d(en el índice 0) en lugar de un índice real, por lo tanto, disminuya en nconsecuencia. Esto también ajusta d(la longitud) para que sea correcto para lo dado n.

  • for i in range(d):

  • Efectivamente: "para el i+1número th en la lista"

    • Aquí es donde explicaré l, el "valor bajo"

    • Después de que un número se ha puesto en la lista, no hay un número menor que el que se puede poner en la lista (para mantenerlo ordenado), así les el último número que se agregó a la lista.

    • while n>=T(h-l,d+~i):` n-=T(h-l,d+~i)`i+=1

    • Si nes demasiado grande para codificarse con un len este "dígito", ajústelo en nconsecuencia e incrementel

    • s+=[l]

    • Codifique ncon un len este "dígito".

    • Al principio, tenemos hopciones para qué "dígito" poner a continuación, pero una vez que ponemos un "dígito" (que se asigna a l), estamos limitados a h-lopciones para el siguiente "dígito".

    • Al principio había T(h,d)listas válidas, pero hemos agregado un "dígito" l, disminuyendo el número de "dígitos" que quedan d-1y el número de "dígitos" próximos válidos h-l, por lo que el número de listas válidas después de esto esT(h-l,d-1)

Explicación del decodificador:

  • def D(s):, s.sort(), l=0,d=len(s)

  • ses la lista de entrada (barajada), por s.sort()lo que; les el "valor bajo" ( hel "valor alto" es literalmente 128s en el código para guardar bytes), nes el número de salida, des la longitud.

  • n=sum(T(128,D)for D in range(d))

  • Ajuste nal punto en la secuencia de[0]*length

  • for i in s:

  • Para cada dígito:

    • for j in range(l,i):, n+=T(128-j,d-1)

    • Ajuste nal punto en la secuencia de[...prevdigits, thisdigit, 0...]

      • l=i: Establezca el "valor bajo" en el dígito más reciente

      • d-=1: Disminuye la longitud desde que usamos un dígito

  • return n: Después de nhaber sido ajustado para todos los dígitos, es el número correcto; devolverlo.

Lo siento si esto no está claro, pero aquí está mi versión original de depuración no golfizada. , que no utiliza la lista vacía, por lo que es 1 de todos los números utilizados en esta versión


3

Ruby , (36 + 29 bytes) * 8, puntaje 520

Codificar:

->n{(0..7).map{|x|(n>>x*=4)%16+x*4}}

Pruébalo en línea!

Descodificar:

->a{a.sum{|x|x%16<<(x/4&28)}}

Pruébalo en línea!

Cómo funciona:

El número se codifica utilizando fragmentos de 4 bits y un índice de 3 bits.

El decodificador toma la matriz de entrada y vuelve a colocar cada mordisco en su lugar.


3

Carbón , puntaje 10 * (10 + 15) = 250.

Utiliza decimal; la solución previa basada en base 16 obtuvo 328 296 264

Puede generar caracteres no imprimibles. En particular, el carácter 10 es difícil de ingresar a Charcoal.

Codificador, 10 bytes:

⭆⮌S℅⁺Iι×χκ

Pruébalo en línea! El enlace es a la versión detallada del código.

Decodificador, 15 bytes:

IΣES×﹪℅ιχXχ÷℅ιχ

Pruébalo en línea! El enlace es a la versión detallada del código.

Versión que usa una lista de enteros puntajes 360 296 (base 16; el decimal sería 310):

Codificador, 19 bytes:

NθIE⁸⁺﹪÷θX¹⁶ι¹⁶×¹⁶ι

Pruébalo en línea! El enlace es a la versión detallada del código.

Decodificador, 18 bytes:

IΣEE⁸N×﹪ι¹⁶X¹⁶÷ι¹⁶

Pruébalo en línea! El enlace es a la versión detallada del código.

Version usando caracteres imprimibles anota 360 (era 416 384 368 en base 16):

Codificador, 19 bytes:

⭆⮌S℅⁺Iι×χ⁺κ×⁵⊕׳÷κ⁵

Pruébalo en línea! El enlace es a la versión detallada del código.

Decodificador, 17 bytes:

Fθ⊞υ⌈Φθ¬№υκ⭆υ﹪℅ιχ

Pruébalo en línea! El enlace es a la versión detallada del código.


2

Brachylog , 17 + 18 bytes * 8 longitud = 280

Codificador:

ḃ₁₆I∧7⟧₁;Iz₁~ḃ₁₆ᵐ

Descifrador:

ḃ₁₆I∧7⟧₁;Iz₁~ḃ₁₆ᵐp

Se puede agregar una p al final del codificador sin ningún efecto. El decodificador se ejecuta colocando el resultado (aleatorio) como salida y obteniendo el número original en la entrada.

Si hubiera un predicado de suma acumulativa (implementado correctamente), el puntaje podría descender a 20

Pruébalo en línea!


@ Delfad0r agregando la p al codificador haría que fuera el mismo código para codificar y decodificar
Kroppeb

2

05AB1E , puntuación: (2 + 2 bytes ) * 11 longitud máxima = 44

Codificador (2 bytes ):

Pruébalo en línea.

Decodificador (2 bytes ):

Pruébalo en línea.

La entrada del codificador y la salida del decodificador son una lista de dígitos.

La segunda respuesta de Jelly del puerto de @ ais523 .

Explicación:

    # Undelta (automatically prepends a 0)
      #  i.e. [3,0,4,7,8,2,0,1,9] → [0,3,3,7,14,22,24,24,25,34]

{     # Sort
      #  i.e. [14,7,22,25,24,3,0,24,34,3] → [0,3,3,7,14,22,24,24,25,34]
 ¥    # Deltas
      #  i.e. [0,3,3,7,14,22,24,24,25,34] → [3,0,4,7,8,2,0,1,9]

Debido a que antepone un cero a la salida, la longitud de la salida es la longitud de la entrada + 1. Desde231-1 tiene una longitud de 10 dígitos, la longitud máxima de la salida es 11.


2

Gol> <> , 8 * (14 + 13) = 216

Codificador Pruébelo en línea! , 14 bytes:

I8FfPSD8*L+o|;

Decoder ¡ Pruébelo en línea! , 13 bytes:

iEh8SD4*2$X*+

Dado que esto puede generar caracteres ASCII no imprimibles, lo que hace que se entremezcle con el decodificador, ahora hay una versión que usa números en la salida / entrada:

Codificador Pruébelo en línea! , 14 bytes:

I8FfPSD8*L+N|;

Decoder ¡ Pruébelo en línea! , 13 bytes:

IEh8SD4*2$X*+

Codificación:

The encoding works by breaking the given number into 8 x 4bit chunks. These chunks are then shifted right by 3 bit and the original location of the chunk is appended on the end as a number between 0 and 7. Thus the encoding looks like this:

0AAAABBB
 |__|    -> the original part of the number
     |_| -> the position of the chunk inside the original number 0 = LSB and 7 = MSB

2

Perl 6, 10 * (10 + 12) = 340 220

Encoder:

{^@_ Z~@_}

Decoder:

{.sort X%10}

Try it online!

The encoder function zips each digit with the 0-index of the number. Then the encoder sorts the list of numbers and gets the modulo by 10, in other words the second digit of the number.

The total is 10, since that's the maximum length of 231-1.


1

Haskell, 10*(23+51) = 740

Here's a program that encodes, shuffles, decodes and validates values: Try it online!

Encoder, 23 bytes

zipWith((+).(10*))[0..]

Try it online!

Decoder, 51 bytes

map snd.sortOn fst.map(`divMod`10)
import Data.List

Try it online!

Explanation

Since we're allowed to use input as decimal digits, we'll use that.. The encoder maps each digit that occurs to 10*index + digit, note that all digits will be in [0..9] so we can reverse the above by using divMod. After restoring the indices and the digits it's only a matter of sorting by the indices and getting rid of them.

The solution is expected to work for values up to 2311=2147483647 which is 10 digits long, so the maximum code-point we get will be 99=81<128. Also each digit will be converted to a "character", so we'll end up with a maximal length of 10.


1

Husk, 10*(7+8) = 150

Straight port of my Haskell solution only with the observation that 109=90<128 (Husk's N is 1-based):

Encoder, 7 bytes

zo+*10N

Try it online!

Decoder, 8 bytes

m→Ö←m‰10

Try it online!


1

APL (Dyalog Unicode), LE+LD=36;A=8288.

d←{16n-16×⍳≢n←⍵[⍋⍵]}
e←(⊢+16×⍳∘≢)16⊥⍣¯1

Try it online! (contains 5 extra bytes for the assignments and the newline).

Uses ⎕IO←0

How:

(⊢+16×⍳∘≢)16⊥⍣¯1  Encoder; input 1234
          16⊥⍣¯1  Convert input to base 16  4 13 2
      ⍳∘≢           [0..length of the list-1]  0 1 2
   16×              times 16  0 16 32
 ⊢+                 plus the original list  4 29 34

{16n-16×⍳≢n←⍵[⍋⍵]}  Decoder; input   34 4 29
              [⍋⍵]   Grade  up  2 0 1
                    Index  with that list  4 29 34
           n        assign that to n
      16×⍳≢          16×[0..length(n)-1]  0 16 32
    n-               subtract that from n  4 13 2
 16                 Decode from base 16  1234

1

PHP, 8*(44+53) = 776

encoder, 44 bytes:

for(;$n=&$argn;$n>>=4)echo$n&15|16*$i++," ";

prints space separated list of integers. Run as pipe with -nR.

maximum 8 bytes with 4 data bits (lower nibble) and 3 weight bits (upper nibble).

Simply put:
Put each hex digit in an own character and use the upper half of the byte to store the digit´s position.

example:

1457893891 (0x56e5b203) will turn into
0x03, 0x10, 0x22, 0x3b, 0x45, 0x5e, 0x66, 0x75
3 16 34 59 69 94 102 117

decoder, 53 bytes:

while($i++<8)$n+=(15&$x=$argv[$i])<<($x>>4)*4;echo$n;

or

while($i++<8)$n+=(15&$x=$argv[$i])<<($x/4&~3);echo$n;

or

for(;$i<9;$x=$argv[++$i])$n+=$x%16<<($x/4&~3);echo$n;

take integers from command line arguments. Run with -nr.


Try them online.


0

Python 2, 10*(68+54) = 1220

e=lambda n:"".join(chr(int(`i`+j))for i,j in enumerate(`n`)if j<'L')
d=lambda s:int("".join(`ord(c)%10`for c in sorted(s)))

Try it online!

EDIT: Thanks to Jo King for the pointers - not sure why I was offsetting by 32, in retrospect.

Encodes the position and value of each place as a single character, starting with [space] (position 0, value 0) the NUL byte 0x0.

Decodes by:

  • sorting the string (Python will sort characters by their ordinal value)
  • converts each character into its ordinal value
  • takes the last digit of each ordinal integer
  • joins the integers into a string
  • converts the joined string back into an int

Do you need the 32 offset? Also, [-1] could be %10 instead, in the right place
Jo King

0

C (gcc), 10*112 = 1120

c,i;e(i,s)char*s;{for(c=1;i;c+=10,i/=10)*s++=c+i%10;*s=0;}
d(char*s){for(i=0;c=*s++;i+=--c%10*pow(10,c/10));s=i;}

Try it online!

I have global variables, but they are not actually passing any info between two functions. Variable declaration for c is used in both functions saving me 2 bytes in code length.

A version that uses printable ASCII only for a 3 5 byte penalty is here:

c,i;e(i,s)char*s;{for(c=32;i;c+=10,i/=10)*s++=c+i%10;*s=0;}
d(char*s){for(i=0;c=*s++;i+=(c-=32)%10*pow(10,c/10));s=i;}

Thanks @ceilingcat for 70 points improvements.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.