Shift Caesars Shifts

13

Descrição

Um deslocamento de César é uma cifra monoalfabética muito simples, em que cada letra é substituída por uma depois do alfabeto. Exemplo:

Hello world! -> IFMMP XPSME!

( IBSLR, EGUFV!é o resultado do desafio real, esse foi um exemplo de mudança de 1).

Como você pode ver, o espaçamento e a pontuação permanecem inalterados. No entanto, para evitar adivinhar a mensagem, todas as letras são maiúsculas. Ao mudar as cartas de volta, a mensagem foi decifrada, conveniente, mas também muito fácil de decifrar por outras pessoas que deveriam não saber o que significa a mensagem.

Então, ajudaremos César um pouco usando uma forma avançada de sua cifra: a mudança de César com mudança automática !

Desafio

Sua tarefa é escrever um programa ou função que, dada uma cadeia de caracteres para codificar, produza a cadeia de caracteres criptografada correspondente à entrada. O avançado Caesar Shift funciona assim:

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

Espaços e outros símbolos especiais, como pontuação, são ignorados neste processo. É garantido que o seu programa receberá uma sequência contendo apenas caracteres ASCII imprimíveis. A saída da sua função / programa deve estar apenas em maiúsculas.

Isso é , então as brechas padrão se aplicam e pode vencer a resposta mais curta em bytes!

racer290
fonte
2
Não é E -3?
Freira vazando
3
E se a diferença de letras trouxer a letra do alfabeto? Como ZEN, por exemplo. Zdeslocado por 1 é ... A? (como uma nota lateral, os 05AB1E resposta voltas Zem A)
Mr. Xcoder
6
Casos de teste, por favor. Além disso, quais caracteres são ignorados exatamente? E o que significa que eles sejam ignorados? Eles são completamente removidos ou devem permanecer na saída?
Luis Mendo
1
@ Giuseppe vê as respostas aprovadas para os casos de teste, elas foram validadas pelo OP como corretas, eu suponho, ou teriam votos negativos.
Magic Octopus Urn
2
Você quis dizer palavras como RELIEFe RELIESpara ambas codificar para o mesmo resultado SRSFAG?
Anders Kaseorg 18/07

Respostas:

5

05AB1E , 28 27 24 bytes

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

Experimente online!

Explicação

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
fonte
Nós dois get IBSLR, EGUFV!para Hello, World!, isso é correto? O OP acabou de estragar esse exemplo?
Magic Octopus Urn
1
@MagicOctopusUrn: Seu exemplo no começo é apenas mostrar o que é uma mudança. Apenas muda 1 letra, o que é bastante enganador.
Emigna
4

Python 3 , 100 bytes

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

Experimente online!

bmantém registro do código ASCII da última letra ou é inicialmente zero; a fórmula c+c-(b or~-x)significa que uma letra com código ASCII cé deslocada c-bseb for diferente de zero e c-(c-1) == +1se bfor zero (para a primeira letra).

bnunca se tornará zero novamente, pois é garantido que a string consiste em caracteres ASCII imprimíveis .

Por fim, 64<c<91verifica se chá uma letra ASCII maiúscula e (…-65)%26+65coloca tudo de volta no A-Zintervalo.

ovs salvou um byte. Obrigado!

Lynn
fonte
100 bytes
ovs 18/07/19
1

ES6 (Javascript), 138 bytes:

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
fonte
não pula letras não, parece?
Titus
1

MATL , 27 bytes

tXkt1Y2mXH)tlwdh+64-lY2w)H(

Experimente online!

Eu acho que esse é o menor tempo possível, mas existem muitas variedades diferentes, pois há muita reutilização de 'variáveis' (existem 3 t(duplicação) e 2 w(troca) operações, a área de transferência Hé usada e mesmo assim ainda existe uma duplicata1Y2 ...). Infelizmente, não consegui salvar bytes com a Márea de transferência automática .

Mais da metade do programa é dedicado a torná-lo em maiúsculas e ignorando caracteres não alfabéticos - apenas a cifra não passa de 13 bytes ( Experimente on-line! )

Sanchises
fonte
1

Perl, 90 89

Embora as línguas não codegolfas raramente sejam competitivas, podemos ficar abaixo de 100;)

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

Eu decidi desgolfar isso:

@a = split//,<>; Recebe informações de STDIN, armazena a lista de caracteres (com nova linha!) Em @a.

say uc(++$a[0])primeira letra maiúscula de saída deslocada em 1. Acontece que você pode incrementar uma letra em perl se usar um prefixo ++. Este é um mutador ofc.

2*ord($a[$_+1])-ord($a[$_])+!$_Somos solicitados a pegar o caractere em x e adicionar a diferença + (x- (x-1)). Bem, isso é 2x - (x-1). No entanto: mudei a primeira letra! Portanto, eu tenho que corrigir esse erro, portanto +!$_, que corrigirá por ter subtraído um número demais na posição 0 (o único caso! $ _ Não é indefinido). Em seguida, uc chrobtemos uma letra maiúscula do valor ASCII calculado.

map{ ... } $#a-2- $#aé a posição para acessar o último elemento da matriz. Desde que eu estou adicionando um que eu quero$#a-1 , mas como a nova linha da entrada precisa ser ignorada, é isso $#a-2.

Isso é concatenado com a primeira letra e terminamos :)

bytepusher
fonte
Parece haver alguns problemas ao lidar com deslocamentos que envolvem o alfabeto e com caracteres não alfabéticos. Experimente online!
Xcali
1

Perl 5 -F , 73 77 74 bytes

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

Experimente online!

Xcali
fonte
Isso não pula totalmente as não letras; apenas não os converte. Eu acho que Hello, World!deveria resultar IBSLR, EGUFV!, não IBSLR, XGUFV!.
Titus
Você está certo. Corrigido com mais 4 bytes para preservar a letra anterior.
Xcali
1

PHP, 106 98 bytes

bastante desagradável ... se base_convertnão fosse tão longo (ou ctype_alpha) ...
mas fiquei com menos de 100. satisfeito.

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

Execute como pipe -nRou experimente online .

Titus
fonte