Реализуйте машину загадки


18

Машина Enigma - довольно сложная машина шифрования, используемая немцами и другими для шифрования своих сообщений. Ваша работа - реализовать эту машину *.

Шаг 1, Вращение

У нашей машины-загадки есть 3 слота для роторов и 5 доступных роторов для каждого из этих слотов. Каждый ротор имеет 26 различных возможных положений (от Aдо Z). Каждый ротор имеет предопределенное положение выемки :

Rotor  Notch
------------
1      Q
2      E
3      V
4      J
5      Z

При нажатии клавиш выполняются следующие шаги:

  1. Ротор в слоте 1 вращается
  2. Если ротор в слоте 1 движется мимо его выемки, то он вращает ротор в слоте 2.
  3. Если ротор в слоте 2 находится на своей выемке (но не просто перемещается туда), оба ротора 2 и 3 вращаются один раз.

Если мы используем роторы 1,3,5 , и они находятся в рабочем положении , P,U,Hто последовательность позиций: P,U,H> Q,U,H> R,V,H>S,W,I

Шаг 2, Замена

Каждый из роторов выполняет простую замену персонажа. Ниже приведена схема каждого из роторов в Aположении:

  ABCDEFGHIJKLMNOPQRSTUVWXYZ
  --------------------------
1 EKMFLGDQVZNTOWYHXUSPAIBRCJ
2 AJDKSIRUXBLHWTMCQGZNPYFVOE
3 BDFHJLCPRTXVZNYEIWGAKMUSQO
4 ESOVPZJAYQUIRHXLNFTGKDCMWB
5 VZBRGITYUPSDNHLXAWMJQOFECK
R YRUHQSLDPXNGOKMIEBFZCWVJAT

Ротор 1 в положении Т PAIBRCJEKMFLGDQVZNTOWYHXUS, который заменил бы букву Cна I.

После того, как три ротора выполнят замену, отражатель попадет (указано Rвыше). Он выполняет свою собственную замену, а затем отражает сигнал обратно через роторы. Затем роторы выполняют обратную замену в обратном порядке.

Обратные средства замены , что вместо ротора 1 заменяющих Aс E, она замещает EсA

Слоты заполнены роторами 1,2,3, все на своих местах A. Буква Qследует по пути Q>X>V>Mчерез роторы. Mотражает O, который затем следует обратному пути O>Z>S>S. Следовательно, Aзаменяется на S.

Ввод, вывод

Вы прошли:

  1. Список из 3 роторов (как целые числа)
  2. Список 3 стартовых позиций ротора (в виде букв)
  3. Строка, которая должна быть зашифрована.

Вы можете предположить, что ваш ввод будет правильным, и все символы будут заглавными буквами, без пробелов.

Вы должны вернуть зашифрованную строку.

При желании вы можете принять роторы, выемки и отражатели в качестве входных данных. Для тех, кто не может снять с байта 95 байтов, как95 = ceil(log2(26 letters ^(26*6 rotors +5 notches))/8 bytes)

Контрольные примеры

Rotor Position Input              Output
4,1,5 H,P,G    AAAAAAAAA          RPWKMBZLN
1,2,3 A,A,A    PROGRAMMINGPUZZLES RTFKHDOVZSXTRMVPFC
1,2,3 A,A,A    RTFKHDOVZSXTRMVPFC PROGRAMMINGPUZZLES
2,5,3 U,L,I    GIBDZNJLGXZ        UNCRACKABLE

Моя реализация может быть найдена на Github . Я проверил это, но у меня могут быть ошибки в моей реализации (что может означать, что мои тестовые примеры, скорее всего, неверны).

* Я пытался сделать это как можно точнее , но из-за различий между машинами у меня могут быть неправильные детали. Однако ваша задача - реализовать то, что я описал, даже если я неточен. Я не включаю плагин для простоты


1
Это правильная реализация алгоритма шифрования, используемого в Enigma I, M3 и M4. Все настройки присутствуют, также работают панель управления и переключатель Uhr: https://github.com/arduinoenigma/ArduinoEnigmaEngineAndUhr Это тот же механизм шифрования, который используется в Arduino Enigma Machine Simulator

Я думаю, что понимаю, но, похоже, это не работает правильно. Вот суть, объясняющая это gist.github.com/JJ-Atkinson/ddd3896fe10d85b3b584 .
Дж Аткин

В первом примере вы сказали «если мы используем роторы 1, 3 и 5», но я думаю, что это будут роторы 1, 2 и 5 (или что-то еще для последнего).
coredump

@coredump Исправлено
Натан Меррилл

Мое понимание того, как работают роторы, все еще неверно?
Дж Аткин

Ответы:


4

Python 3, 403 байта

Я думаю, что это работает правильно. Роторы перешли к нему:

def z(p,o,m,f,g,h):
 O=ord;b=lambda a:a[1:]+a[:1];d=lambda a:chr(a+O('A'));e=lambda a:O(a)-O('A');i=[list(g[i-1])for i in p];j=[f[i-1]for i in p];i=[x[e(y):]+x[:e(y)]for x,y in zip(i,o)];k=[]
 for l in m:
  if i[0][0]==j[0]:i[1]=b(i[1])
  elif i[1][0]==j[1]:i[1]=b(i[1]);i[2]=b(i[2])
  i[0]=b(i[0]);c=l
  for n in i:c=n[e(c)]
  c=h[e(c)]
  for n in reversed(i):c=d(n.index(c))
  k+=[c]
 return''.join(k)

fэто надрез, gроторы и hотражатель.

Ungolfed:

shift = lambda rotor: rotor[1:] + rotor[:1]
letter = lambda num: chr(num + ord('A'))
number = lambda chr: ord(chr) - ord('A')


def encode(rotors, rotorStart, message, defaultRotors, reflector, rotorNotchPositions):
    usedRotors = [list(defaultRotors[i - 1]) for i in rotors]
    notches = [rotorNotchPositions[i - 1] for i in rotors]
    usedRotors = [rotor[number(offset):] + rotor[:number(offset)] for rotor, offset in zip(usedRotors, rotorStart)]

    sub = []

    for char in message:
        # print([''.join(rotor) for rotor in usedRotors])
        if usedRotors[0][0] == notches[0]:
            usedRotors[1] = shift(usedRotors[1])
        elif usedRotors[1][0] == notches[1]:
            usedRotors[1] = shift(usedRotors[1])
            usedRotors[2] = shift(usedRotors[2])

        usedRotors[0] = shift(usedRotors[0])

        c = char
        for rotor in usedRotors:
            c = rotor[number(c)]
        c = reflector[number(c)]
        for rotor in reversed(usedRotors):
            c = letter(rotor.index(c))
        sub += [c]
        print([''.join(rotor) for rotor in usedRotors], char, c, message)

    return ''.join(sub)

rotorNotchPositions = 'QEVJZ'
*defaultRotors, reflector = [
    #ABCDEFGHIJKLMNOPQRSTUVWXYZ#
    "EKMFLGDQVZNTOWYHXUSPAIBRCJ",  # 1
    "AJDKSIRUXBLHWTMCQGZNPYFVOE",  # 2
    "BDFHJLCPRTXVZNYEIWGAKMUSQO",  # 3
    "ESOVPZJAYQUIRHXLNFTGKDCMWB",  # 4
    "VZBRGITYUPSDNHLXAWMJQOFECK",  # 5
    "YRUHQSLDPXNGOKMIEBFZCWVJAT"   # R
]

#             Rotor       Position        Input                 Output
assert encode((4, 1, 5), ('H', 'R', 'G'), 'AAAAAAAAA',
              defaultRotors, reflector, rotorNotchPositions) == 'PXSHJMMHR'
assert encode((1, 2, 3), ('A', 'A', 'A'), 'PROGRAMMINGPUZZLES',
              defaultRotors, reflector, rotorNotchPositions) == 'RTFKHDOCCDAHRJJDFC'
assert encode((1, 2, 3), ('A', 'A', 'A'), 'RTFKHDOVZSXTRMVPFC',
              defaultRotors, reflector, rotorNotchPositions) == 'PROGRAMRXGVGUVFCES'
assert encode((2, 5, 3), ('U', 'L', 'I'), 'GIBDZNJLGXZ',
              defaultRotors, reflector, rotorNotchPositions) == 'UNCRAUPSCTK'

Я думаю, что это работает, но он производит другой вывод, из-за чего (я думаю) ошибка в ссылочной импл.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.