Сдвиги Цезаря Сдвиги


13

Описание

Сдвиг Цезаря - это очень простой моноалфавитный шифр, в котором каждая буква заменяется буквой после алфавита. Пример:

Hello world! -> IFMMP XPSME!

( IBSLR, EGUFV!это выход для реальной задачи, это был пример сдвига на 1.)

Как видите, интервалы и знаки препинания остаются ненастроенными. Однако, чтобы предотвратить угадывание сообщения, все буквы пишутся с большой буквы. Перемещая буквы назад, сообщение было расшифровано, удобно, но также очень легко расшифровывалось другими людьми, которые, как предполагается, не знают, что означает сообщение.

Итак, мы немного поможем Цезарю, используя усовершенствованную форму его шифра: Само-сдвигающийся Цезарь-Сдвиг !

Вызов

Ваша задача - написать программу или функцию, которая при наличии строки для шифрования выводит зашифрованную строку, соответствующую вводу. Продвинутый Цезарь Сдвиг работает так:

1. Compute letter differences of all adjacent letters: 
    1.1. Letter difference is computed like this:

         Position of 2nd letter in the alphabet
        -Position of 1st letter in the alphabet
        =======================================
                              Letter difference

    1.2. Example input: Hello
         H - e|e -  l|l  -  l|l  -  o
         7 - 5|5 - 12|12 - 12|12 - 15 Letter differences: 3; -7; 0; -3
            =3|   =-7|     =0|    =-3

2. Assign the letters continously a letter difference from the list,
   starting at the second letter and inverting the differences:
    2.1. 2nd letter: first difference, 3rd letter: second difference, etc.

    2.2. The first letter is assigned a 1.

    2.3. Example input: Hello with differences 3; -7; 0; -3

         Letter || Value
         =======||======
            H   ||   1
            E   ||  -3
            L   ||   7
            L   ||   0
            O   ||   3

3. Shift the letters by the value x they have been assigned:
    3.1. In case of a positive x, the letter is shifted x letters to the right.
    3.2. In case of a negative x, the letter is shifted |x| letters to the left.
    3.3. In case of x = 0, the letter is not shifted.

    3.4. If the shift would surpass the limits of the alphabet, it gets wrapped around
         Example: Y + Shift of 2 --> A

    3.5. Example input: See the table under 2.3.

                ||       || Shifted
         Letter || Value || Letter
         =======||=======||=========
            H   ||   1   ||    I
            E   ||  -3   ||    B     Program output:
            L   ||   7   ||    S     IBSLR
            L   ||   0   ||    L
            O   ||   3   ||    R

В этом процессе пропускаются пробелы и другие специальные символы, такие как знаки препинания. Гарантируется, что вашей программе будет задана строка, содержащая только печатные символы ASCII. Вывод вашей функции / программы должен быть только в верхнем регистре.

Это , поэтому применяются стандартные лазейки, и пусть победит кратчайший ответ в байтах!


2
Не так ли E -3?
Утренняя монахиня

3
Что если разность букв выводит букву из алфавита? Как ZEN, например. Zсмещено на 1 это ... A? (как примечание, ответ 05AB1E превращается Zв A)
г-н Xcoder

6
Тестовые случаи, пожалуйста. Кроме того, какие символы пропускаются точно? И что это значит для них быть пропущенным? Они удалены полностью или они должны остаться в выходных данных?
Луис Мендо

1
@Giuseppe видят ответы для тестовых случаев с подтвержденными голосами, они были подтверждены OP как правильные, я бы предположил, или у них будут отрицательные голоса.
Волшебная Осьминог Urn

2
Вы имели в виду такие слова, как RELIEFи RELIESоба для шифрования с тем же результатом SRSFAG?
Андерс Касеорг

Ответы:


5

05AB1E , 28 27 24 байта

láÇ¥R`XIlvyaiAyk+Aèëy}u?

Попробуйте онлайн!

объяснение

l                          # convert input to lower case
 á                         # keep only letters
  ǥ                       # compute deltas of character codes
    R`                     # reverse and push separated to stack
      X                    # push 1
       Ilv                 # for each char y in lower case input
          yai              # if y is a letter
             Ayk           # get the index of y in the alphabet
                +          # add the next delta
                 Aè        # index into the alphabet with this
            ëy             # else push y
              }            # end if
            u?             # print as upper case

Мы оба получим IBSLR, EGUFV!для Hello, World!, это правильно? OP только испортил этот пример?
Волшебная Урна Осьминога

1
@MagicOctopusUrn: его пример в начале просто показывает, что такое сдвиг. Он просто сдвигается на 1 букву, поэтому вводит в заблуждение.
Эминья

4

Python 3 , 100 байт

b=0
for c in map(ord,input().upper()):
 if 64<c<91:b,c=c,(c+c-(b or~-c)-65)%26+65
 print(end=chr(c))

Попробуйте онлайн!

bотслеживает код последней буквы ASCII или изначально равен нулю; формула c+c-(b or~-x)означает, что буква с кодом ASCII cсдвигается на c-bif, если bона не равна нулю, иc-(c-1) == +1 if bна ноль (для самой первой буквы).

bникогда не станет равным нулю, так как строка гарантированно состоит из печати символов ASCII.

Наконец, 64<c<91проверяет,c является ли ASCII буквой в верхнем регистре, и (…-65)%26+65переносит все обратно вA-Z диапазон.

ovs спас байт. Благодарность!





1

MATL , 27 байт

tXkt1Y2mXH)tlwdh+64-lY2w)H(

Попробуйте онлайн!

Я думаю, что это самое короткое, что я могу получить, но есть много разных вариантов, поскольку существует многократное повторное использование «переменных» (есть 3 t(дублирование) и 2 w(обмен) операции, Hиспользуется буфер обмена и даже тогда есть еще дубликат 1Y2...). К сожалению, я не мог сохранить байты с помощью автоматическогоM буфера обмена.

Более половины программы посвящено тому, чтобы сделать ее заглавной и игнорировать не алфавитные символы - только шифр не более 13 байтов ( попробуйте онлайн! )


1

Perl, 90 89

Хотя языки, не относящиеся к Codegolf, редко бывают конкурентоспособными, мы можем опуститься ниже 100;)

@a=split//,<>;say uc(++$a[0]).join'',map{uc chr(2*ord($a[$_+1])-ord($a[$_])+!$_)}0..$#a-1

Я решил раскрутить это:

@a = split//,<>; Принимает данные из STDIN, сохраняет список символов (с новой строкой!) В @a.

say uc(++$a[0])вывод первой заглавной буквы со смещением на 1. Оказывается, вы можете увеличивать букву в perl, если используете префикс ++. Это мутатор ofc.

2*ord($a[$_+1])-ord($a[$_])+!$_Нас просят взять символ в x и добавить разницу + (x- (x-1)). Ну, это 2x - (x-1). Однако: я изменил первую букву! Таким образом, я должен исправить эту ошибку, следовательно +!$_, это исправит то, что вычел слишком много в позиции 0 (только случай! $ _ Не undef). Затем мы uc chrполучим заглавную букву из рассчитанного значения ASCII.

map{ ... } $#a-2- $#aэто позиция для доступа к последнему элементу массива. Так как я добавляю один, который я хочу $#a-1, но так как перевод строки из ввода должен игнорироваться, это так $#a-2.

Это связано с первым письмом, и мы сделали :)


Это, кажется, имеет некоторые проблемы, связанные со смещениями, которые охватывают алфавит, и с неалфавитными символами. Попробуйте онлайн!
Xcali

1

Perl 5 -F , 73 77 74 байта

/\w/&&($_=chr 65+(2*($n=ord uc)-65-($!||-1+ord uc))%26)&($!=$n)for@F;say@F

Попробуйте онлайн!


Это не полностью пропускает не буквы; это просто не конвертирует их. Я думаю, что Hello, World!должно привести IBSLR, EGUFV!, а не IBSLR, XGUFV!.
Тит

Ты прав. Исправлено еще 4 байта, чтобы сохранить предыдущую букву.
Xcali

1

PHP, 106 98 байт

довольно неприятно, что ... если бы не было так base_convertдолго (или ctype_alpha) ...
но я получил его под 100. доволен.

for(;$a=ord($c=$argn[$i++]);print ctype_alpha($c)?chr(65+($p?(25-$p+2*$p=$a)%26:$p=$a)):$c)$a&=31;

Запустите как трубу с -nRили попробуйте онлайн .


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