Przesunięcie zmian Caesars

13

Opis

Przesunięcie Cezara jest bardzo prostym szyfrem monoalfabetycznym, w którym każda litera jest zastępowana kolejną literą w alfabecie. Przykład:

Hello world! -> IFMMP XPSME!

( IBSLR, EGUFV!jest wynikiem rzeczywistego wyzwania, był to przykład przesunięcia o 1)

Jak widać, odstępy i interpunkcja pozostają nienaruszone. Aby jednak nie zgadywać wiadomości, wszystkie litery są pisane wielkimi literami. Przesuwając litery z powrotem, wiadomość została odszyfrowana, wygodna, ale także bardzo łatwa do odczytania przez inne osoby, które powinny nie wiedzieć, co oznacza wiadomość.

Pomożemy więc trochę Cezarowi, wykorzystując zaawansowaną formę jego szyfru: Samokierującą się zmianę Cezara !

Wyzwanie

Twoim zadaniem jest napisanie programu lub funkcji, która podając ciąg encipherowi, wyprowadza zaszyfrowany ciąg odpowiadający wejściu. Zaawansowana zmiana Cezara działa w następujący sposób:

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

W tym procesie pomijane są spacje i inne specjalne symbole, takie jak interpunkcja. Gwarantujemy, że program otrzyma ciąg znaków zawierający tylko drukowalne znaki ASCII. Dane wyjściowe funkcji / programu muszą być pisane tylko wielkimi literami.

To jest , więc obowiązują standardowe luki i może wygrać najkrótsza odpowiedź w bajtach!

racer290
źródło
2
Nie E -3jest
Leaky Nun
3
Co się stanie, jeśli różnica liter wydobywa literę z alfabetu? Jak ZEN, na przykład. Zprzesunięty o 1 to ... A? (na marginesie, odpowiedź 05AB1E zmienia się Zw A)
Pan Xcoder
6
Przypadki testowe proszę. Które postacie są dokładnie pomijane? A co to znaczy, że zostaną pominięte? Czy są całkowicie usuwane, czy też muszą pozostać na wyjściu?
Luis Mendo,
1
@Giuseppe widzi uprzywilejowane odpowiedzi dla przypadków testowych, zostały one zatwierdzone przez OP jako poprawne, zakładam, lub miałyby negatywne opinie.
Magic Octopus Urn
2
Czy miałeś na myśli słowa takie jak RELIEFi RELIESoba, aby uzyskać ten sam wynik SRSFAG?
Anders Kaseorg,

Odpowiedzi:

5

05AB1E , 28 27 24 bajtów

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

Wypróbuj online!

Wyjaśnienie

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
Emigna
źródło
Oboje get IBSLR, EGUFV!za Hello, World!, czy to prawda? Czy OP po prostu zepsuło ten przykład?
Magic Octopus Urn
1
@MagicOctopusUrn: Jego przykład na początku pokazuje, czym jest zmiana. Przesuwa się tylko o 1 literę, więc jest dość mylące.
Emigna
4

Python 3 , 100 bajtów

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))

Wypróbuj online!

bśledzi kod ASCII ostatniej litery lub początkowo wynosi zero; formuła c+c-(b or~-x)oznacza, że ​​litera z kodem ASCII cjest przesuwana przez c-bif bjest niezerowe, a c-(c-1) == +1jeśli bwynosi zero (dla pierwszej litery).

bnigdy nie zmieni się ponownie na zero, ponieważ ciąg znaków składa się z drukowanych znaków ASCII.

Na koniec 64<c<91sprawdza, czy cjest to wielka litera ASCII i (…-65)%26+65zawija wszystko z powrotem do A-Zzakresu.

ovs zapisał bajt. Dzięki!

Lynn
źródło
1

ES6 (JavaScript), 138 bajtów:

s=>((s,a,f)=>((r=i=>s[i]&&(a[i]=String.fromCharCode((2*s[f](i)-(s[f](i-1)||71)-38)%26+64),r(i+1)))(0),a))(s.toUpperCase(),[],"charCodeAt")

http://jsbin.com/manurenasa/edit?console

Jonas Wilms
źródło
wydaje się, że nie pomija liter innych niż litery?
Tytus
1

MATL , 27 bajtów

tXkt1Y2mXH)tlwdh+64-lY2w)H(

Wypróbuj online!

Myślę, że jest to najkrótszy możliwy, ale istnieje wiele różnych odmian, ponieważ istnieje wiele możliwości ponownego użycia „zmiennych” (są 3 t(duplikacja) i 2 w(zamiana) operacji, Hużywany jest schowek i nawet wtedy jest jeszcze duplikat 1Y2...). Niestety nie udało mi się zapisać bajtów za pomocą automatycznego Mschowka.

Ponad połowa programu zajmuje się pisaniem wielkimi literami i ignorowaniem znaków niealfabetycznych - sam szyfr ma nie więcej niż 13 bajtów ( wypróbuj online! )

Sanchises
źródło
1

Perl, 90 89

Chociaż języki niekodowane są rzadko konkurencyjne, możemy zejść poniżej 100;)

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

Postanowiłem odholfować to:

@a = split//,<>; Pobiera dane ze STDIN, przechowuje listę znaków (z nową linią!) W @a.

say uc(++$a[0])wypisuje pierwszą literę przesuniętą o 1. Okazuje się, że możesz zwiększyć literę w perlu, jeśli używasz przedrostka ++. To jest mutator ofc.

2*ord($a[$_+1])-ord($a[$_])+!$_Jesteśmy proszeni o przyjęcie znaku na x i dodanie różnicy + (x- (x-1)). Cóż, to 2x - (x-1). Jednak: Zmieniłem pierwszą literę! Dlatego muszę skorygować ten błąd, +!$_który poprawi odjęcie o jeden za dużo na pozycji 0 (tylko przypadek! $ _ Nie jest undef). Następnie uc chrotrzymujemy wielką literę z obliczonej wartości ASCII.

map{ ... } $#a-2- $#aoznacza pozycję umożliwiającą dostęp do ostatniego elementu tablicy. Ponieważ dodaję jeden, chcę $#a-1, ale ponieważ nowy wiersz z danych wejściowych wymaga zignorowania, to jest $#a-2.

Jest to połączone z pierwszą literą i gotowe :)

bytepusher
źródło
Wydaje się, że ma to pewne problemy z przesunięciami otaczającymi alfabet i ze znakami niealfabetycznymi. Wypróbuj online!
Xcali
1

Perl 5 -F , 73 77 74 bajtów

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

Wypróbuj online!

Xcali
źródło
Nie pomija to całkowicie liter innych niż litery; po prostu ich nie konwertuje. Myślę, że Hello, World!powinno to skutkować IBSLR, EGUFV!, nie IBSLR, XGUFV!.
Tytus
Masz rację. Naprawiono 4 bajty więcej, aby zachować poprzednią literę.
Xcali
1

PHP, 106 98 bajtów

dość paskudny ten ... jeśli po prostu base_convertnie był tak długi (lub ctype_alpha) ...
ale mam go poniżej 100. jestem zadowolony.

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

Uruchom jako potok z -nRlub spróbuj online .

Tytus
źródło