เลื่อน Caesars เลื่อน


13

ลักษณะ

Caesar Shift เป็นรหัสตัวเลขแบบ monoalphabetic ที่ง่ายมากโดยที่ตัวอักษรแต่ละตัวจะถูกแทนที่ด้วยตัวอักษรหนึ่งตัวตามด้วยตัวอักษร ตัวอย่าง:

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เหรอ
Leun Nun

3
เกิดอะไรขึ้นถ้าความแตกต่างของตัวอักษรนำตัวอักษรออกมาจากตัวอักษร? เช่นZENยกตัวอย่างเช่น Zเลื่อนโดย 1 คือ ... A? (ตามด้านข้างคำตอบของ 05AB1E จะเปลี่ยนZเป็นA)
Mr. Xcoder

6
กรณีทดสอบโปรด นอกจากนี้ตัวละครใดที่ถูกข้ามอย่างแน่นอน? และหมายความว่าอย่างไรสำหรับพวกเขาที่จะถูกข้าม? พวกเขาถูกลบออกไปพร้อมกันหรือพวกเขาจะต้องอยู่ในเอาท์พุท?
Luis Mendo

1
@Giuseppe ดูคำตอบที่เพิ่มขึ้นสำหรับกรณีทดสอบพวกเขาได้รับการตรวจสอบความถูกต้องโดย OP ว่าถูกต้องฉันจะสมมติหรือพวกเขามี downvotes
Magic Octopus Urn

2
คุณหมายถึงคำที่ชอบRELIEFและRELIESเพื่อเข้ารหัสทั้งผลลัพธ์เดียวกันSRSFAGหรือไม่
Anders Kaseorg

คำตอบ:


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 ทำเช่นนั้นสับสนหรือไม่
Magic Octopus Urn

1
@MagicOctopusUrn: ตัวอย่างของเขาในตอนแรกแสดงให้เห็นว่าการเปลี่ยนแปลงเป็นอย่างไร มันแค่เลื่อนตัวอักษร 1 ฉบับดังนั้นมันอาจทำให้เข้าใจผิดได้
Emigna

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(การทำซ้ำ)) และwการดำเนินงาน2 (สลับ) คลิปบอร์ด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 ถ้าคุณใช้คำนำหน้า ++ นี่คือ mutator 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หรือลองออนไลน์


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.