凯撒的转变


13

描述

凯撒移位(Caesar Shift)是一种非常简单的单字母密码,其中每个字母都被替换为字母中的一个字母。例:

Hello world! -> IFMMP XPSME!

IBSLR, EGUFV!是实际挑战的输出,这是移动1的示例。)

如您所见,空格和标点符号保持不协调。但是,为防止猜测消息,所有字母均大写。通过将字母向后移,可以解密该消息,很方便,但是真的很容易被不知道该消息含义的其他人解密。

因此,我们将通过使用一种高级形式的密码来帮助Caesar:Self-shifting Caesar Shift

挑战

您的任务是编写一个程序或函数,给定要加密的字符串,然后输出与输入相对应的加密字符串。先进的Caesar Shift的工作方式如下:

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答案转ZA
Xcoder先生

6
请测试用例。另外,哪些字符会被完全跳过?对他们来说,这意味着什么?是否将它们完全删除,还是必须保留在输出中?
路易斯·门多

1
@Giuseppe看到测试用例的最高答案,我认为它们已经被OP验证为正确,否则他们将使用低票。
Magic Octopus Urn

2
您的意思是像话RELIEFRELIES这两个加密器相同的结果SRSFAG
Anders Kaseorg '17

Answers:


5

05AB1E28 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个字母,因此非常容易误导。
Emigna '17

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

Perl,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倍-(x-1)。但是:我更改了第一个字母!因此,我必须纠正该错误,因此+!$_,它将纠正位置0减去一个过多的错误(仅当情况下$$不是undef)。然后uc chr,我们从计算出的ASCII值中获得一个大写字母。

map{ ... } $#a-2- $#a是访问最后一个数组元素的位置。由于我要添加一个$#a-1,但由于需要忽略输入中的换行符,因此为$#a-2

这与第一个字母连接在一起,我们完成了:)


这似乎在处理围绕字母和非字母字符的偏移量方面存在一些问题。 在线尝试!
Xcali

1

Perl 5中 -F73个 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在线尝试


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.