El cifrado VIC es uno de los cifrados de lápiz y papel más complicados jamás diseñados. Utilizado en la década de 1950 por el espía soviético Reino Häyhänen, con el nombre en código "VICTOR", su principio principal es la seguridad a través de la ofuscación; una gran cantidad de ofuscación.
Su tarea es escribir un programa o función que tome un mensaje y lo codifique utilizando el cifrado VIC. También he publicado un desafío de decodificador de cifrado VIC aquí . Si alguna de las siguientes instrucciones no es clara, no dude en preguntar sobre ellas en los comentarios. Las instrucciones están adaptadas de este sitio .
Codificación del cifrado VIC
Preparación
Necesitará cinco entradas:
- el mensaje de texto sin formato
- una palabra clave o frase corta que contiene las letras más comunes en su idioma
- una frase clave, como una cita o una línea de una canción (al menos 20 caracteres)
- una fecha (u otro número de seis dígitos o más)
- un número de agente personal
En la práctica, estos últimos cuatro deben ser acordados previamente por el remitente y el destinatario, incluido si el número de agente del remitente o el destinatario se utiliza en la codificación.
Mi mensaje de ejemplo será: We are discovered. Take what you can. Burn everything else. Move to Safehouse Foxtrot 3.
Estaremos codificando en inglés (aunque puede usar cualquier idioma y alfabeto que prefiera) y las letras más comunes en el alfabeto inglés son A, E, I, N, O, R, S, T
. Usaré la palabra clave SENATORI
.
Mi frase clave es una cita de Richard Feynman: "El primer principio es que no debes engañarte a ti mismo, y eres la persona más fácil de engañar".
Como fecha, usaré el 31 de julio de 2016 (en el formato 3172016
), que es el día en que escribí esta descripción.
El número personal que he elegido para mí es 9
.
Resumen de pasos
- Derive las claves intermedias para usar en los siguientes pasos.
- Construye y aplica el tablero de damas a caballo.
- Construya y aplique la primera tabla de transposición.
- Construya y aplique la segunda tabla de transposición (interrumpida).
- Finalice el mensaje insertando el grupo indicador de mensaje.
Submecanismos
Dos cosas más que explicar antes de entrar en el meollo del asunto: los procesos de adición de cadena y secuenciación.
La adición de cadena, también conocida como un generador de Fibonacci rezagado, funciona tomando una secuencia de dígitos inicial, agregando los primeros dos dígitos sin llevarlos (agréguelos juntos luego mod 10
) y agregando el resultado al final. Por ejemplo:
79081
7 + 9 = 6
790816
9 + 0 = 9
7908169
0 + 8 = 8
79081698
8 + 1 = 9
790816989
1 + 6 = 7
7908169897
... and so on
La secuenciación es esencialmente tomar una secuencia de letras o dígitos y etiquetarlos por su orden alfabético / numérico. Los duplicados se etiquetan de izquierda a derecha. Por ejemplo:
E X A M P L E
0 # A
1 0 2 # Es
1 0 3 2 # L
1 0 4 3 2 # M
1 0 4 5 3 2 # P
1 6 0 4 5 3 2 # X
3 3 0 5 8 4 2 0 4 7 5 4 8 1
0 1 # 0s
0 1 2 # 1
0 3 1 2 # 2
4 5 0 3 1 2 # 3s
4 5 0 6 3 1 7 8 2 # 4s
4 5 0 9 6 3 1 7 10 8 2 # 5s
4 5 0 9 6 3 1 7 11 10 8 2 # 7
4 5 0 9 12 6 3 1 7 11 10 8 13 2 # 8s
Aquí uso la indexación cero, pero indexe como quiera.
1. Claves intermedias
Divida las primeras 20 letras de la frase clave en dos grupos de 10 y secuencialice cada uno individualmente, lo que llamaremos S1
y S2
.
THEFIRSTPR
S1: 8201357946
INCIPLEIST
S2: 2603751489
Elija un identificador de mensaje aleatorio de 5 dígitos M
(esta puede ser una de las entradas si lo prefiere):
M = 47921
Reste, sin pedir prestado (restar mod 10
), los primeros cinco dígitos de la fecha clave 3172016
de M
:
M 47921
date - 31720
= 16201
Cadena agregue el resultado hasta que tenga diez dígitos:
1620178218
Agregue estos dígitos a S1
, sin llevar o mod 10
, para obtener G
:
1620178218
S1 + 8201357946
G = 9821425154
Arriba S2
, escriba la secuencia 0123456789. Localice cada dígito de G
en la secuencia 0123456789 y reemplácelo con el dígito directamente debajo de él S2
. El resultado es T
.
0123456789
S2 2603751489
G 9821425154
T 9806705657
Use la adición de cadena para expandir T
a 60 dígitos.
9806705657
becomes
980670565778637511245490262369939288595822106344304316978734
Estos últimos 50 dígitos, en cinco filas de diez dígitos cada uno, forman el U
bloque.
T 9806705657
U 7863751124
5490262369
9392885958
2210634430
4316978734
Los dos últimos dígitos no iguales del U
bloque se agregan individualmente al número personal del agente para dar el ancho de las dos transposiciones, p
y q
.
9 + 3 = 12 (p, primer ancho de transposición) 9 + 4 = 13 (q, segundo ancho de transposición)
Secuencializar T
y utilizar esta secuencia para copiar fuera de las columnas del U
bloque, de arriba a abajo, en una nueva fila de dígitos, V
.
T 9806705657
seqT 9804612537
U 7863751124
5490262369
9392885958
2210634430
4316978734
V 69911 56837 12548 26533 30206 13947 72869 49804 84323 75924
Secuencialice los primeros p
dígitos para obtener la clave para la primera transposición K1
, y los siguientes q
dígitos para la clave para la segunda K2
.
First 12 6 9 9 1 1 5 6 8 3 7 1 2
K1 6 10 11 0 1 5 7 9 4 8 2 3
Next 13 5 4 8 2 6 5 3 3 3 0 2 0 6
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
Finalmente, secuencialice la fila final del U
bloque para obtener C
los encabezados de columna para el tablero de damas:
U5 4316978734
C 3105968724
2. Tablero de damas a caballo
Primero, daré mi ejemplo de tablero de ajedrez y luego explicaré los principios para crearlo de esa manera:
3 1 0 5 9 6 8 7 2 4
S E N A T O R I
2 B D G J L P U W Y .
4 C F H K M Q V X Z #
La primera línea de letras es nuestra palabra clave corta SENATORI
. Su palabra clave puede ser cualquier cadena sin duplicados, pero dado que define la fila superior de su tablero de ajedrez, elija sabiamente. Encima de la palabra clave está C
, y las otras filas son el resto del alfabeto en el orden que elija. En mi caso, llené el tablero con el resto del alfabeto latino, un signo de puntuación .
y una marca para demarcar números #
. Esencialmente, el tablero de ajedrez es un cifrado de sustitución elegante. Por ejemplo, "E" se sustituirá con 1
, y "W" se sustituirá con 27
.
Una vez que hemos codificado nuestro mensaje de texto sin formato con este tablero de ajedrez, pero primero, debemos hacer que el comienzo de nuestro mensaje sea menos obvio dividiéndolo en una posición aleatoria y haciéndolo todo en mayúscula. Para denotar el otro comienzo original, usamos dos puntos completos..
We are discovered. Take what you can. Burn everything else. Move to Safehouse Foxtrot 3.
se convierte
HING ELSE. MOVE TO SAFEHOUSE FOXTROT#3#.. WE ARE
DISCOVERED. TAKE WHAT YOU CAN. BURN EVERYT
Codificamos con el tablero de ajedrez, dándonos:
407020 1293124 496481 96 354114062831 416479869443442424 271 581
2173436481812124 95451 274059 22628 435024 232880 14818229
Si la longitud del mensaje no es divisible por 5, agregamos algunos caracteres nulos para rellenar el mensaje. Nuestro mensaje tiene 109 dígitos, así que agregaré un nulo: "4".
40702 01293 12449 64819 63541 14062 83141 64798 69443 44242 42715
81217 34364 81812 12495 45127 40592 26284 35024 23288 01481 82294
Nota: Dado que mi mensaje de ejemplo no contiene números, diré aquí que puede designar, digamos, como #3#
, que está codificado como 44344
aquí.
3. Primera transposición
Cree la tabla de transposición escribiendo K1
(desde la sección Claves intermedias) seguido del mensaje codificado del paso anterior, en filas de la misma longitud, debajo de la clave:
K1 6 10 11 0 1 5 7 9 4 8 2 3
4 0 7 0 2 0 1 2 9 3 1 2
4 4 9 6 4 8 1 9 6 3 5 4
1 1 4 0 6 2 8 3 1 4 1 6
4 7 9 8 6 9 4 4 3 4 4 2
4 2 4 2 7 1 5 8 1 2 1 7
3 4 3 6 4 8 1 8 1 2 1 2
4 9 5 4 5 1 2 7 4 0 5 9
2 2 6 2 8 4 3 5 0 2 4 2
3 2 8 8 0 1 4 8 1 8 2 2
9 4
Tomando las columnas numeradas en orden de sus números obtenemos:
060826428 246674580 151411542 246272922 961311401 082918141
4414434239 118451234 334422028 293488758 0417249224 794943568
4. Segunda transposición
La primera transposición fue relativamente simple. Éste, sin embargo, es una transposición interrumpida. El patrón de interrupción está determinado por el ancho de la tabla y la clave. En nuestro ejemplo, tenemos 110 dígitos y 13 columnas, lo que significa que tendremos 8 filas completas y 6 sobras. Comenzamos a completar la primera fila, pero nos detenemos en la columna 0 y continuamos de la siguiente manera:
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
0 6 0 8 2 6 4 2 8 stop at 0
2 4 6 6 7 4 5 8 0 1 continue in a triangle pattern
5 1 4 1 1 5 4 2 2 4 6
2 7 2 9 2 2 9 6 1 3 1 1
4 0 1 0 8 2 9 1 8 1 4 1 4 until the end
4 1 4 4 3 4 2 3 9 1 1 restart and stop at 1
8 4 5 1 2 3 4 3 3 4 4 2
2 0 2 8 2 9 3 4 8 8 7 5 8
0 4 1 restart and stop at 2
Luego llenamos los últimos espacios con los dígitos restantes.
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
0 6 0 8 2 6 4 2 8 7 2 4 9
2 4 6 6 7 4 5 8 0 1 2 2 4
5 1 4 1 1 5 4 2 2 4 6 7 9
2 7 2 9 2 2 9 6 1 3 1 1 4
4 0 1 0 8 2 9 1 8 1 4 1 4
4 1 4 4 3 4 2 3 9 1 1 9 4
8 4 5 1 2 3 4 3 3 4 4 2 3
2 0 2 8 2 9 3 4 8 8 7 5 8
0 4 1 5 6 8
Ahora, leemos las columnas exactamente de la misma manera que lo hicimos en la primera transposición.
71431148 42711925 861904185 22614147 45499243 28261334 80218938
641701404 025244820 645224398 271283226 94944438 064214521
Y divide todo en grupos de 5 dígitos:
71431 14842 71192 58619 04185 22614 14745 49924 32826 13348 02189
38641 70140 40252 44820 64522 43982 71283 22694 94443 80642 14521
5. Finalice el mensaje
El paso final es insertar nuestro identificador de mensaje aleatorio 47921
, en el mensaje mismo. El último dígito de la fecha clave 6
indica la distancia que debe estar el grupo desde el final.
71431 14842 71192 58619 04185 22614 14745 49924 32826 13348 02189 38641
70140 40252 44820 64522 43982 47921 71283 22694 94443 80642 14521
Notas para este desafío
- Se le dan un mínimo de cinco entradas: el mensaje, la palabra clave de la letra, la frase clave, la fecha y un número personal. Puede incluir dos entradas adicionales: el identificador de mensaje aleatorio y los valores nulos necesarios para rellenar el mensaje, o su función puede generar algunos números aleatorios por sí solo.
- Puede suponer que todas las entradas son válidas, con el número correcto de dígitos y letras (identificador de mensaje de 5 dígitos, al menos 20 dígitos para la frase clave, y así sucesivamente). Puede suponer que a sus cadenas (el mensaje y las palabras clave) ya se les han eliminado todos los signos de puntuación y espacios, excepto los que permite en su versión, y que los números ya están demarcados con signos numéricos.
- La primera palabra clave no debe tener letras duplicadas, y en su código, puede suponer que nunca tiene letras duplicadas.
- El idioma que usa para codificar no importa, siempre y cuando el idioma sea preexistente, el alfabeto sea preexistente y usted especifique qué idioma usará en su respuesta.
- Cualquiera que sea el alfabeto que emplee para su tablero de damas, puede agregar o quitar símbolos para rellenar el tablero de ajedrez. Especifique para qué utiliza esos símbolos (por ejemplo, puntuación, un símbolo separado de "mensaje de inicio", símbolos para palabras comunes). Puede renunciar por completo al signo de número y deletrear los números o incluir cada dígito en el tablero de ajedrez, usando la ranura donde el signo de número era para otra cosa. Especifique qué tablero de ajedrez utilizó en su respuesta.
- La salida debe ser una cadena de grupos de cinco dígitos separados por espacios, una lista de enteros de cinco dígitos o algo similar.
- Usé indexación cero y
0123456789
en mi ejemplo. Puede usar 1-indexing y1234567890
, o algún otro sistema en su respuesta, siempre que especifique lo que usó.
Aquí hay un ejemplo de implementación en Ideone .
Esta es una publicación larga y escribí la mayor parte a mano, por lo que si hay alguna parte confusa en esta publicación o errores en mi conteo y transposición, hágamelo saber. ¡Buena suerte y buen golf!
fuente
adding the first two digits without adding
¿Te refieres a llevar?without borrowing
ywithout carrying
? ¿Te refieres a sumar y restar mod10
, es decir(6+7) mod 10 = 3
y(6-8) mod 10 = 8
?Respuestas:
Python 3 ,
14231348132413161300128612501249120912061204 bytesEste es definitivamente el golf más largo que he hecho, y el único golf en el que estaba muy preocupado por quedarme sin nombres de variables de un carácter. Sugerencias de golf bienvenidas. Pruébalo en línea!
Estoy codificando con el alfabeto latino en mayúsculas con caracteres adicionales
.
y#
, usando la indexación 0 y0123456789
al convertirg
at
. Mi tablero de damas está en un formato similar al siguiente ejemplo:Editar: -63 bytes gracias a la sugerencia de TuukkaX de acortar algunas de las funciones de uso frecuente con variables de una letra. -12 bytes de hacer
a, g, t
más compacto.Editar: -24 bytes de creación eliminando nombres de variables para claves intermedias que solo se usan una vez, a saber
a, g, s, S, k, K
.Editar: -74 bytes desde la consolidación
H(), T() and C()
.Editar: -1 byte gracias a Nick A por su sugerencia de cambiar
ord(s[i])+ord(s[i+1])
asum(map(ord,s[i:i+2]))
. -2 bytes de cambiar 2+=[a]
llamadas a+=a,
. -13 bytes de cambiar cómo seG()
encuentra el índice del mínimo des
. -2 bytes de cambiary=(y+1)%v
ay=-~y%v
. -15 bytes desde la asignaciónk.index()
aK
. -4 bytes desde la asignación10
aW
. -5 bytes desde la asignación1-I(d[-1])
alX
interiorV
. -3 bytes de reescrituraC()
del bucle principal. -2 bytes de reorganizaciónT()
.No golfista:
fuente
ord(seq[i])+ord(seq[i+1])
asum(map(ord,seq[i:i+2]))
guardar 1 personaje, creo.C,
288027692766276227432741273926992458 bytesDios mío. Este es el programa más largo que he tenido para jugar golf. Este es también el primero en el que realmente me quedé sin nombres de variables de un solo carácter para el alcance global y, por lo tanto, tuve que pasar a usar algunos de 2 caracteres (el hecho de que aparentemente no puedo redeclarar variables no ayuda). Por lo tanto, los consejos de golf son muy apreciados.
Sin golf
Compila sin ninguna advertencia, a diferencia de la versión de golf. Los cambios menores realizados en la versión de golf no se reflejarán en esta versión sin golf.
Notas
Esto utiliza un tablero similar al siguiente para codificar el mensaje:
Esto supone que todas las cadenas aplicables se dan en mayúsculas. El mensaje también debe tener todos los signos de puntuación, excepto los períodos eliminados y todos los números demarcados por
#
s, mientras que la frase clave debe tener todos los signos de puntuación eliminados.El mensaje codificado resultante se envía a STDOUT como una cadena de grupos de cinco dígitos separados por espacios.
El mensaje de entrada debe estar en inglés.
Hubiera combinado algunas de las funciones que usé, pero luego tendría que recurrir al uso de más nombres de variables de dos letras, haciendo que el programa final sea más largo de lo que sería con algunas funciones más.
Actualmente, esto no supone que la palabra clave (al menos en inglés) siempre contendrá el mismo conjunto de letras, y lo compensa eliminando duplicados, manipulando el tablero de ajedrez, etc. Esta capacidad aparentemente no es requerida por OP, así que actualmente estoy jugando al golf con los bytes adicionales e innecesarios que está ocupando.Actualizado para la versión de golf.fuente
JavaScript (ES6),
946938953 bytesVi durante el fin de semana que todavía no había una entrada de JS para esto, así que aquí está mi intento (de último minuto). ¡Implementar y jugar golf fue tan loco como divertido!
Fragmento de demostración
Mostrar fragmento de código
Editar: -8 bytes
Se dio cuenta de que había paréntesis adicionales alrededor de la función
S,J,A,Q
Editar: +15 bytes
Se actualizó la lógica de cómo
message id
se coloca en el mensaje final (ahora 1 indexado y 0 no lo incluye en la salida).Sin golf
Notas
Esto utiliza un tablero similar al siguiente para codificar el mensaje:
Todas las cadenas se dan en mayúsculas. El mensaje es latín alfanumérico (más
.
y#
) y debe eliminarse toda la puntuación (excepto los puntos). Todos los números ya deberían estar marcados con#
s. La frase clave debe tener todos los signos de puntuación / espacios eliminados.El mensaje resultante se devuelve como una matriz de cadenas de 5 dígitos.
Mejoras
Siento que hay una manera de abusar de "Todos los idiomas" para guardar algunos bytes. Si tuviera más tiempo, volvería a configurar esto para asumir que el idioma era algo como el hawaiano, que solo tiene 12 letras.
Cualquier sugerencia de golf es siempre bienvenida.
fuente
message identifier
parece estar7
lejos del final en lugar de6
. Además, en su versión sin golf, lo mismoId
parece estar6
lejos del principio en lugar del final.1
significa el final, ¿dónde diría quemessage identifier
debería irse a0
? Puedo cambiarlo, solo necesito saberlo.0
lamessage identifier
debe omitirse de la salida.Clojure,
11971212 bytesOugh, estoy agotado.
Actualización: se agregó la ubicación de división aleatoria requerida del mensaje, la versión no protegida utiliza la misma ubicación que el ejemplo dado para que el algoritmo se pueda verificar fácilmente.
Entradas de muestra y caso de prueba:
Sin golf:
Tiene una implementación alternativa en el tablero de ajedrez
B
que es la misma que en la definición de tarea. Pero el envío utiliza otro en el que los alfabetos no utilizados primero llenan la segunda fila y luego la tercera en lugar de llenar columna por columna.fuente
coords
se genera dos veces, primero generando la forma triangular y luego rellenando las coordenadas que faltaban. Además, el "relleno hasta la longitud de la multiplicación de N" podría tener una solución más elegante que la concatenación de elementos N - 1 y la división en longitudes de N.(split-at 49 mymsg)
, 49 debería ser algo(rand-int(count mymsg))
así como la respuesta correcta sería un poco más de 1200 bytes. zzz