Cryptic Kicker //


12

Cryptic Kicker

วิธีการเข้ารหัสข้อความธรรมดา แต่ไม่ปลอดภัยคือการดัดแปลงตัวอักษรของตัวอักษร กล่าวอีกนัยหนึ่งตัวอักษรแต่ละตัวจะถูกแทนที่ด้วยตัวอักษรอื่นอย่างสม่ำเสมอ เพื่อให้แน่ใจว่าการเข้ารหัสสามารถย้อนกลับได้ไม่มีการเปลี่ยนตัวอักษรสองตัวด้วยตัวอักษรเดียวกัน งานของคุณคือถอดรหัสข้อความที่เข้ารหัสหลายบรรทัดโดยสมมติว่าแต่ละบรรทัดใช้ชุดการแทนที่ที่แตกต่างกันและคำทั้งหมดในข้อความที่ถอดรหัสมาจากพจนานุกรมของคำที่รู้จัก

อินพุต

ข้อมูลที่ป้อนประกอบด้วยคำตัวพิมพ์เล็กตามลำดับตัวอักษร คำเหล่านี้ประกอบด้วยพจนานุกรมของคำที่อาจปรากฏในข้อความถอดรหัส การติดตามพจนานุกรมจะมีอินพุตหลายบรรทัด แต่ละบรรทัดถูกเข้ารหัสตามที่อธิบายไว้ข้างต้น

พจนานุกรมไม่เกิน 1,000 คำ คำไม่เกิน 16 ตัวอักษร บรรทัดที่เข้ารหัสลับมีตัวอักษรตัวพิมพ์เล็กและช่องว่างเท่านั้นและมีความยาวไม่เกิน 80 อักขระ

เอาท์พุต

ถอดรหัสแต่ละบรรทัดและพิมพ์ไปยังเอาต์พุตมาตรฐาน หากมีหลายวิธีการแก้ปัญหาใด ๆ ที่จะทำ หากไม่มีวิธีแก้ไขให้แทนที่ตัวอักษรทุกตัวด้วยเครื่องหมายดอกจัน

ตัวอย่างอินพุต

and dick jane puff spot yertle

bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd

ตัวอย่างผลลัพธ์

dick and jane and puff and spot and yertle
**** *** **** *** **** *** **** *** ******

นี่คือทางออกของ โปรดทราบว่าฉันไม่ใช่ม้าที่วิ่งแข่งกับไบต์ที่สั้นที่สุด/โปรแกรมเมอร์แข่งขัน ฉันชอบปริศนา!

( ที่มา )


1
โปรดผ่อนคลาย> ใส่ <ข้อ จำกัด ของสิ่งที่ใช้ได้กับแต่ละภาษา ตัวอย่างเช่นหลายภาษาจะเกลียดและไม่พอใจที่รูปแบบเริ่มต้นด้วย 6 ฉันขอแนะนำให้ปล่อยรูปแบบโดยไม่ระบุโดยเฉพาะและพูดเพียงว่าอินพุตเป็นรายการคำและรายการบรรทัดที่เข้ารหัส
orlp

โอเคคุณไปแล้ว!
Dhruv Ramani

1
มีข้อ จำกัด รันไทม์สำหรับสิ่งนี้หรือไม่? ฉันสามารถทำซ้ำชุดการแทนที่ที่เป็นไปได้ทั้งหมดจนกว่าจะมีหนึ่งงาน (ซึ่งน่าจะใช้เวลาหลายปีกว่าจะเสร็จสิ้น)
Nathan Merrill

@NathanMerrill ทำอย่างนั้นและถ้ามันต้องใช้เวลาหลายปีแค่พิมพ์ลงในรูปดาว วิหารมันไม่ซ้ำกันโปรดอ่านคำถามอย่างถูกต้อง
Dhruv Ramani

เราสามารถส่งออกคำหรือเราต้องเข้าร่วมได้หรือไม่
Downgoat

คำตอบ:


3

Python 3, 423 ไบต์

import sys,re
S=re.sub
D,*L=sys.stdin.read().split('\n')
def f(W,M=[],V="",r=0):
 if len({d for(s,d)in M})==len(M):
  if[]==W:return V.lower()
  for d in D.split():p='([a-z])(?%s.*\\1)';m=re.match(S(p%'=',')\\1=P?(',S(p%'!',').>\\1<P?(',W[0].translate(dict(M))[::-1]))[::-1]+'$',d.upper());r=r or m and f(W[1:],M+[(ord(s),m.group(s))for s in m.groupdict()],V+d+" ")
  return r
for l in L:print(f(l.split())or S('\w','*',l))

อ่านอินพุตจาก STDIN และเขียนเอาต์พุตไปยัง STDOUT โดยใช้รูปแบบเดียวกันกับอินพุต / เอาต์พุตตัวอย่าง

คำอธิบาย

สำหรับแต่ละบรรทัดของ ciphertext เราดำเนินการตามขั้นตอนต่อไปนี้:

เราเก็บแผนที่, M , ของการแปลงตัวอักษรทั้งหมดที่เราได้สร้างไว้แล้ว (ซึ่งตอนแรกว่างเปล่า) เราทำในลักษณะที่ตัวอักษรต้นฉบับเป็นตัวพิมพ์เล็กทั้งหมดและตัวอักษรปลายทางเป็นตัวพิมพ์ใหญ่ทั้งหมด

เราประมวลผลคำศัพท์ในไซเฟอร์เท็กซ์ตามลำดับ สำหรับแต่ละคำเราจะพบคำทั้งหมดในพจนานุกรมที่อาจตรงกันดังนี้:

สมมติว่าคำพูดของเรา, Wเป็นglpplppljjlและMj -> Pมีกฎ ครั้งแรกที่เราแปลงWใช้กฎที่มีอยู่ในเอ็มglpplpplPPlที่ได้รับ จากนั้นเราเปลี่ยนwให้เป็น regex แบบ python ที่มีรสชาติดังต่อไปนี้:

(?P<g>.)(?P<l>.)(?P<p>.)(?P=p)(?P=l)(?P=p)(?P=p)(?P=l)PP(?P=l)

กฎของการเปลี่ยนแปลงมีดังนี้:

  • เกิดขึ้นครั้งแรกของแต่ละตัวอักษรตัวพิมพ์เล็กx, จะถูกแทนที่ด้วย สิ่งนี้กำหนดกลุ่มการจับกุมที่มีชื่อซึ่งเรียกว่าซึ่งตรงกับ cahracter เดี่ยว(?P<x>.)x
  • ทุกคนที่เกิดขึ้นตามมาแต่ละตัวอักษรตัวพิมพ์เล็กx, จะถูกแทนที่ด้วย นี่คือ backreference ตัวละคร previsouly จับโดยใช้ชื่อกลุ่มที่(?P=x)x

เราดำเนินการเปลี่ยนแปลงครั้งนี้โดยการกลับWแล้วใช้แทน regex สองต่อไปนี้:

s/([a-z])(?!.*\1)/)>\1<P?(/
s/([a-z])(?=.*\1)/)\1=P?(/

แล้วกลับผลลัพธ์ โปรดทราบว่าอักขระที่แปลงโดยMก่อนหน้านี้จะปรากฏเป็นตัวพิมพ์ใหญ่ดังนั้นจึงยังคงไม่เปลี่ยนแปลง

เราจับคู่ regex ที่ได้กับคำในพจนานุกรมแต่ละคำโดยที่คำในพจนานุกรมปรากฏเป็นตัวพิมพ์ใหญ่ ยกตัวอย่างเช่น regex MISSISSIPPIดังกล่าวข้างต้นจะตรงกับคำว่า หากเราพบการแข่งขันที่เราแยกการเปลี่ยนแปลงกฎใหม่จากมันและเพิ่มให้M กฎการแปลงโฉมใหม่เป็นเพียงตัวละครที่ถูกจับโดยกลุ่มจับแต่ละกลุ่ม ใน regex ข้างต้นกลุ่มgไม้ขีดไฟMกลุ่มที่lแข่งขันIและกลุ่มที่pตรงกับที่ให้เรากฎS g -> M, l -> I, p -> Sเราต้องตรวจสอบให้แน่ใจว่ากฎที่ได้นั้นสอดคล้องกันนั่นคือไม่มีตัวอักษรต้นทางสองตัวที่จับคู่กับตัวอักษรปลายทางเดียวกัน มิฉะนั้นเราจะปฏิเสธการแข่งขัน

จากนั้นเราจะดำเนินการกับคำถัดไปโดยใช้กฎการแปลงเพิ่มเติม หากเราสามารถจับคู่คำ ciphertext ทั้งหมดโดยใช้กระบวนการนี้เราได้ถอดรหัสข้อความ หากเราไม่สามารถจับคู่คำกับคำในพจนานุกรมใด ๆ เราจะย้อนกลับและพยายามจับคู่คำก่อนหน้ากับคำในพจนานุกรมที่แตกต่างกัน หากกระบวนการนี้ล้มเหลวจะไม่มีวิธีแก้ไขและเราจะพิมพ์แถวของเครื่องหมายดอกจัน


2

CJam, 62 56 ไบต์

qN%Sf/(f{\:C,m*{C..+`Sa`m2/Q|z_''f-Qf|=},C:,'*f*a+0=S*N}

ค่อนข้างช้าและหน่วยความจำหิว แต่ทำงานสำหรับกรณีทดสอบกับล่าม Java

ตัวอย่างการวิ่ง

$ cat input; echo
and dick jane puff spot yertle

bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd
$ time cjam kicker.cjam < input
dick and jane and puff and spot and yertle
**** *** **** *** **** *** **** *** ******

real    5m19.817s
user    6m41.740s
sys     0m1.611s
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.