Зміщення кесарів Зміна


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?
Leaky Nun

3
Що робити, якщо різниця літер виводить букву з алфавіту? Як ZEN, наприклад. Zзміщена на 1 - це ... A? (Як примітка боку, у відповідь 05AB1E витків Zв A)
г -

6
Тестові справи, будь ласка. Також, які персонажі пропускаються саме? І що для них означає пропустити? Чи їх видаляють взагалі, або вони залишаються у висновку?
Луїс Мендо

1
@Giuseppe дивіться відповіді, що підтверджені для тестових випадків, вони були підтверджені ОП як правильні, я вважаю, або вони мали б суттєві відгуки.
Чарівний восьминога Урна

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!, це правильно? ОП просто зіпсував цей приклад?
Magic Octopus Urn

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-bякщо bвона не дорівнює нулю, а c-(c-1) == +1якщо 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

Перл, 90 89

Хоча мови без кодового гольфу рідко є конкурентоспроможними, ми можемо опуститись нижче 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)). Ну це 2х - (х-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.