# Una máquina de simulación de estilo enigma en Python 3 -- python campo con python-3.x campo con enigma-machine camp codereview Relacionados El problema

## An enigma style simulation machine in Python 3

6

### problema

Español

Este código hizo algunos descansos en mi tiempo libre. Sin embargo, hay algunas alteraciones a la máquina original que muestra esta simulación, uno siendo el alfabeto, otro es la cantidad de rotores.

` ` from random import * import msvcrt import os from os import walk english = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',',','.','?','-','+','=','1','2','3','4','5','6','7','8','9','0',' ',''','"','!'] def diskgen(alphabet):     #DISK GENERATION     disk_avail = []     disk_direc = []     disk_map = []     for num in range (0,len(alphabet)):         disk_avail.append(num)         disk_direc.append(num)     #Begin mapping     while len(disk_direc) > 0:         choose_ep = randint(0,len(disk_avail)-1)         exit_position = disk_avail[choose_ep]         disk_map.append(exit_position)         del disk_avail[choose_ep]         del disk_direc[0]     for pos in range (0,len(alphabet)):         disk_map[pos] = disk_map[pos] - pos     return disk_map def reflector(alphabet):     reflect_avail = []     reflect_map = []     for num in range (0,len(alphabet)):         reflect_avail.append(num)         reflect_map.append('x')     if len(reflect_avail)%2 == 0:         while len(reflect_avail) > 0:             from_num = reflect_avail[0]             to_pos = randint(1,len(reflect_avail)-1)             fin_num = reflect_avail[to_pos]             reflect_map[from_num] = fin_num             reflect_map[fin_num] = from_num             del reflect_avail[0]             del reflect_avail[to_pos-1]         for pos in range (0,len(alphabet)):             reflect_map[pos] = reflect_map[pos] - pos         return reflect_map def rotate(selected_disk):     new_disk = []     new_disk.append(selected_disk[len(selected_disk)-1])     for pos in range (0,len(selected_disk)-1):         new_disk.append(selected_disk[pos])     return new_disk  def code(reflector,letter,language,disk1,disk2,disk3,disk4):     language_map = {}     for x in range (0,len(language)):         language_map.update({language[x]:x})     ltnumb = language_map[letter]     disk1_scramble = (disk1[ltnumb] + ltnumb + len(disk1))%len(disk1)     disk2_scramble = (disk2[disk1_scramble] + disk1_scramble + len(disk2))%len(disk2)     disk3_scramble = (disk3[disk2_scramble] + disk2_scramble + len(disk3))%len(disk3)     disk4_scramble = (disk4[disk3_scramble] + disk3_scramble + len(disk4))%len(disk4)     rfb = (reflector[disk4_scramble] + disk4_scramble + len(reflector))%len(reflector)     for x in range (0,len(disk4)):         if (disk4[x]+x+len(disk4))%len(disk4) == rfb:             disk4_reverse = x             break     for x in range (0,len(disk3)):         if (disk3[x]+x+len(disk3))%len(disk3) == disk4_reverse:             disk3_reverse = x             break     for x in range (0,len(disk2)):         if (disk2[x]+x+len(disk2))%len(disk2) == disk3_reverse:             disk2_reverse = x             break     for x in range (0,len(disk1)):         if (disk1[x]+x+len(disk1))%len(disk1) == disk2_reverse:             eletter = language[x]             break     return eletter  #------------------------------------------------------------------------ cwd = os.getcwd() print(cwd) if not os.path.exists(cwd+'\rotor'):     os.mkdir(cwd+'\rotor') f = [] for (dirpath, dirnames, filenames) in walk(cwd+'\rotor'):     f.extend(filenames) files = [] for fname in f:     if fname.endswith('.rotor'):         files.append(fname.replace('.rotor','')) start_selection = input('[1] New Setting [2] Reload Setting from file ') if start_selection == '2':     print(files)     for num in range (len(files)):         print('['+str(num)+'] '+files[num])     f_choose = int(input())     with open (cwd+'\rotor\'+files[f_choose]+'.rotor','r') as f:         information = eval(f.read()) elif start_selection == '1':     d1 = diskgen(english)     d2 = diskgen(english)     d3 = diskgen(english)     d4 = diskgen(english)     rf = reflector(english)     d1rc = 0     d2rc = 0     d3rc = 0     d4rc = 0     rfrc = 0     raw_type = ''     enc_type = ''     information = [d1,d2,d3,d4,rf,d1rc,d2rc,d3rc,d4rc,rfrc,raw_type,enc_type]     wtf = input('Write to file? [y/n]: ')     if (wtf == 'y') or (wtf == 'Y'):         while True:             name = input('NAME: ')             os.system('cls')             if not os.path.isfile(cwd+'\rotor\'+name+'.rotor'):                 newf = open(cwd+'\rotor\'+name+'.rotor','w')                 break             if os.path.isfile(cwd+'\rotor\'+name+'.rotor'):                 proceed = input('File already exists, overwrite? [1] Yes [2] No ')                 if proceed == '1':                     newf = open(cwd+'\rotor\'+name+'.rotor','w')                     break         newf.write(str(information))         newf.close() os.system('cls') d1 = information[0] d2 = information[1] d3 = information[2] d4 = information[3] rf = information[4] d1rc = information[5] d2rc = information[6] d3rc = information[7] d4rc = information[8] rfrc = information[9] raw_type = input('Plaintext: ') enc_type = information[11] word_address = 0 while word_address < len(raw_type):     print(raw_type+' '+enc_type)     letter = raw_type[word_address]     os.system('cls')     try:         encoded_letter = code(rf,letter,english,d1,d2,d3,d4)         enc_type += encoded_letter     except:         continue     decoded_letter = code(rf,encoded_letter,english,d1,d2,d3,d4)     d1 = rotate(d1)     d1rc += 1     if d1rc == len(d1):         d1rc = 0         d2 = rotate(d2)         d2rc += 1         if d2rc == len(d2):             d2rc = 0             d3 = rotate(d3)             d3rc += 1             if d3rc == len(d3):                 d4 = rotate(d4)                 d3rc = 0                 d4rc += 1                 if d4rc == len(d4):                     d4rc = 0                     rf = rotate(rf)                     rfrc += 1     word_address += 1 print(raw_type+' '+enc_type) input()   ``

Si usted va a ejecutar esto, le resultará lento (por favor, ejecute en la consola, no shell). Tiene la capacidad de generar discos y rotores válidos si lo necesita, o guarde una configuración de rotor a un archivo.

Hay solo una corazonada (aparte de la codificación perezosa en las partes), que es que la visualización del texto del código es lento. Como puede ver, utiliza el ` 99887766655443311 99887766555443322 . `

Para hacer la plataforma de código de código, puedo usar algo como:

` ` import os def cls():     os.system('cls' if os.name=='nt' else 'clear') cls()   ``

Me gustaría consejos para darme una mejor dirección en cómo mejorar esto. ¿Hay alguna falla obvia que me haya perdido en todas mis pruebas?

Me doy cuenta de que esta no es una buena herramienta criptográfica en el día y la edad de hoy. Se supone que esto es más educativo.

¿En qué formas puede optimizarse mejor y de qué manera puedo estallar errores no obvios en el código?

Original en ingles

This code made a few breaks back in my spare time. There are, however, a few alterations to the original machine that this simulation shows, one being the alphabet, another being the amount of rotors.

``from random import * import msvcrt import os from os import walk english = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',',','.','?','-','+','=','1','2','3','4','5','6','7','8','9','0',' ','\'','"','!'] def diskgen(alphabet):     #DISK GENERATION     disk_avail = []     disk_direc = []     disk_map = []     for num in range (0,len(alphabet)):         disk_avail.append(num)         disk_direc.append(num)     #Begin mapping     while len(disk_direc) > 0:         choose_ep = randint(0,len(disk_avail)-1)         exit_position = disk_avail[choose_ep]         disk_map.append(exit_position)         del disk_avail[choose_ep]         del disk_direc[0]     for pos in range (0,len(alphabet)):         disk_map[pos] = disk_map[pos] - pos     return disk_map def reflector(alphabet):     reflect_avail = []     reflect_map = []     for num in range (0,len(alphabet)):         reflect_avail.append(num)         reflect_map.append('x')     if len(reflect_avail)%2 == 0:         while len(reflect_avail) > 0:             from_num = reflect_avail[0]             to_pos = randint(1,len(reflect_avail)-1)             fin_num = reflect_avail[to_pos]             reflect_map[from_num] = fin_num             reflect_map[fin_num] = from_num             del reflect_avail[0]             del reflect_avail[to_pos-1]         for pos in range (0,len(alphabet)):             reflect_map[pos] = reflect_map[pos] - pos         return reflect_map def rotate(selected_disk):     new_disk = []     new_disk.append(selected_disk[len(selected_disk)-1])     for pos in range (0,len(selected_disk)-1):         new_disk.append(selected_disk[pos])     return new_disk  def code(reflector,letter,language,disk1,disk2,disk3,disk4):     language_map = {}     for x in range (0,len(language)):         language_map.update({language[x]:x})     ltnumb = language_map[letter]     disk1_scramble = (disk1[ltnumb] + ltnumb + len(disk1))%len(disk1)     disk2_scramble = (disk2[disk1_scramble] + disk1_scramble + len(disk2))%len(disk2)     disk3_scramble = (disk3[disk2_scramble] + disk2_scramble + len(disk3))%len(disk3)     disk4_scramble = (disk4[disk3_scramble] + disk3_scramble + len(disk4))%len(disk4)     rfb = (reflector[disk4_scramble] + disk4_scramble + len(reflector))%len(reflector)     for x in range (0,len(disk4)):         if (disk4[x]+x+len(disk4))%len(disk4) == rfb:             disk4_reverse = x             break     for x in range (0,len(disk3)):         if (disk3[x]+x+len(disk3))%len(disk3) == disk4_reverse:             disk3_reverse = x             break     for x in range (0,len(disk2)):         if (disk2[x]+x+len(disk2))%len(disk2) == disk3_reverse:             disk2_reverse = x             break     for x in range (0,len(disk1)):         if (disk1[x]+x+len(disk1))%len(disk1) == disk2_reverse:             eletter = language[x]             break     return eletter  #------------------------------------------------------------------------ cwd = os.getcwd() print(cwd) if not os.path.exists(cwd+'\\rotor'):     os.mkdir(cwd+'\\rotor') f = [] for (dirpath, dirnames, filenames) in walk(cwd+'\\rotor'):     f.extend(filenames) files = [] for fname in f:     if fname.endswith('.rotor'):         files.append(fname.replace('.rotor','')) start_selection = input('[1]\tNew Setting\n[2]\tReload Setting from file\n') if start_selection == '2':     print(files)     for num in range (len(files)):         print('['+str(num)+']\t'+files[num])     f_choose = int(input())     with open (cwd+'\\rotor\\'+files[f_choose]+'.rotor','r') as f:         information = eval(f.read()) elif start_selection == '1':     d1 = diskgen(english)     d2 = diskgen(english)     d3 = diskgen(english)     d4 = diskgen(english)     rf = reflector(english)     d1rc = 0     d2rc = 0     d3rc = 0     d4rc = 0     rfrc = 0     raw_type = ''     enc_type = ''     information = [d1,d2,d3,d4,rf,d1rc,d2rc,d3rc,d4rc,rfrc,raw_type,enc_type]     wtf = input('Write to file? [y/n]: ')     if (wtf == 'y') or (wtf == 'Y'):         while True:             name = input('NAME: ')             os.system('cls')             if not os.path.isfile(cwd+'\\rotor\\'+name+'.rotor'):                 newf = open(cwd+'\\rotor\\'+name+'.rotor','w')                 break             if os.path.isfile(cwd+'\\rotor\\'+name+'.rotor'):                 proceed = input('File already exists, overwrite?\n[1]\tYes\n[2]\tNo\n')                 if proceed == '1':                     newf = open(cwd+'\\rotor\\'+name+'.rotor','w')                     break         newf.write(str(information))         newf.close() os.system('cls') d1 = information[0] d2 = information[1] d3 = information[2] d4 = information[3] rf = information[4] d1rc = information[5] d2rc = information[6] d3rc = information[7] d4rc = information[8] rfrc = information[9] raw_type = input('Plaintext: ') enc_type = information[11] word_address = 0 while word_address < len(raw_type):     print(raw_type+'\n'+enc_type)     letter = raw_type[word_address]     os.system('cls')     try:         encoded_letter = code(rf,letter,english,d1,d2,d3,d4)         enc_type += encoded_letter     except:         continue     decoded_letter = code(rf,encoded_letter,english,d1,d2,d3,d4)     d1 = rotate(d1)     d1rc += 1     if d1rc == len(d1):         d1rc = 0         d2 = rotate(d2)         d2rc += 1         if d2rc == len(d2):             d2rc = 0             d3 = rotate(d3)             d3rc += 1             if d3rc == len(d3):                 d4 = rotate(d4)                 d3rc = 0                 d4rc += 1                 if d4rc == len(d4):                     d4rc = 0                     rf = rotate(rf)                     rfrc += 1     word_address += 1 print(raw_type+'\n'+enc_type) input() ``

If you happen to run this you'd find this to be slow (please run in console, not shell). It has the ability to generate valid disks and rotors if you need it, or save a rotor setting to a file.

There is just one hunch (apart from lazy coding at parts), which is that the displaying of the code text is slow. As you can see, it uses repeated `print`s and `cls`.

To make the code cross platform, I can use something like:

``import os def cls():     os.system('cls' if os.name=='nt' else 'clear') cls() ``

I would like tips to give me better direction in how to better do this. Are there any obvious flaws that I have missed in all my testing?

I realise that this is not a good cryptographic tool in today's day and age. This is supposed to be more educational.

In which ways can this be better optimised and in which ways can I stamp out not obvious errors in the code?

## Lista de respuestas

3

La mejor respuesta

Aquí hay algunas cosas relacionadas con el rendimiento y la calidad del código en general:

• ¡Qué función 9988777665544339 99887766655443310 funciona, no depende de la entrada del usuario y se puede precargar para evitar perder tiempo durante el tiempo de ejecución. Crea los mapas de disco y reflector de antemano.
• Para multiplicar las asignaciones de disco, use ` 12351 ` en lugar de regenerar el mapeo
• El código de rotación se puede mejorar mediante el uso de la cortada, también puede ser más rápido:

` ` 12352  ``
• NOTA El uso de la indexación negativa y la inclinación de la lista (puede aplicar estas cosas en otras partes del código: no solo hará que el código sea más conciso y legible, sino que puede proporcionar refuerzos de rendimiento)

• Puede hacer uso de ` 12353 ` y ` 12354 ` para pasar alrededor de múltiples argumentos

• Hacer uso de Desembalaje , por ejemplo Puede mejorar la forma en que analiza la lista ` 12355 ` (dividido a múltiples rebanadas para la legibilidad):

` ` 12356  ``
• Use Lista y explicaciones diccionario

• Ponga la lógica del programa principal en la ` 12357 ` < / a>
• Extrae la parte de entrada del usuario en una función separada
• El ` 12358 se puede definir como una concatenación de conjuntos de conjuntos de caracteres disponibles en el módulo 12359 : `

` ` 12340 ` `

Organización de código, el código realmente solicita una clase (, por supuesto, usted no T tiene que escribir clases ), digamos, ` 12341 ` en el que, el método constructor será responsable de inicializar los discos y los reflectores, los discos serían variables de instancia, simplemente los accedería a través de ellos. Código> 12342 en lugar de pasar por debajo del método al método. La lógica de rotación al final del programa también debe extraerse y ser parte de esta clase.

Here are some things related to performance and the code quality in general:

• what the `diskgen()` and `reflector()` functions do, does not really depend on the user's input and can be pre-computed to avoid wasting time during the runtime. Create the disk and reflector maps beforehand.
• to multiply the disk mappings, use `copy.deepcopy()` instead of regenerating the mapping
• the rotation code can be improved by using slicing - might also be faster:

``def rotate(disk):     return [disk[-1]] + disk[:-1] ``
• note the use of negative indexing and list slicing (you can apply these things in other parts of the code - it would not only make the code more concise and readable, but may provide performance boosts)

• you can make use of `*args` and `**kwargs` to pass around multiple arguments

• make use of unpacking, e.g. you can improve the way you parse the `information` list (splited to multiple slices for readability):

``d1, d2, d3, d4 = information[:4] rf = information[4] d1rc, d2rc, d3rc, d4rc = information[5:9] rfrc = information[9] ``
• use list and dictionary comprehensions

• put the main program logic to under the `if __name__ == '__main__':`
• extract the user input part into a separate function
• the `english` list can be defined as a concatenation of sets of characters available in the `string` module:

``In [1]: import string  In [2]: string.ascii_letters Out[2]: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ``

Code organization-wise, the code really asks for a class (of course, you don't have to write classes), say, `Machine` in which, the constructor method will be responsible for initializing disks and reflectors, the disks would be instance variables - you would simply access them via `self.diskN` instead of passing around from method to method. The rotation logic at the end of the program should also be extracted and be a part of this class.

6  Una máquina de simulación de estilo enigma en Python 3  ( An enigma style simulation machine in python 3 )
Este código hizo algunos descansos en mi tiempo libre. Sin embargo, hay algunas alteraciones a la máquina original que muestra esta simulación, uno siendo el ...

12  Simulación de la máquina enigma  ( Enigma machine simulation )
Este es un simulador de máquina enigma escrito en Java: enigma.java Number0 rotor.java Number1 lenderotor.java Number2 medrotor.jav...

7  Simulación de la máquina enigma en Python  ( Enigma machine simulation in python )
Fondo y Ejemplo Este código simula el enigma Machine , menos el plugboard. Aquí hay algún código de prueba que ilustra cómo la construcción y el uso de la ...

19  Simulador de la máquina enigma: mejora del rendimiento de algoritmo recursivo  ( Enigma machine simulator improving recursive algorithm performance )
Soy nuevo en Haskell y estoy confundido por por qué mi código parece preformar tan mal y preguntarse si hay algo que no he comprendido la filosofía de codific...

12  Rendimiento del simulador de enigma  ( Enigma simulator performance )
Aquí está mi implementación de una máquina de enigma de 3 rotor simple en C ++: #include <iostream> #include <cstring> using namespace std; char alpha[] =...

4  La máquina enigma (CLI) en Java  ( The enigma machine cli in java )
Hace unos días comencé a trabajar en mi primer proyecto que es más grande que cualquier otro que haya intentado antes. El propósito de esto fue aprender a un ...