แก้ปัญหาการเปลี่ยนรูป Burrows-Wheeler


11

บทนำ

ในการท้าทายนี้คุณจะได้รับการแก้ไข Burrows-Wheeler ในแนวทแยง นี่คือภาพรวมทั่วไปของการเปลี่ยนรูป Burrows-Wheeler ในแนวทแยง ในการเข้ารหัสข้อความคุณต้องรับประกันว่าข้อความนั้นยาวแปลก (เช่น 5, 7, 9 ฯลฯ ) จากนั้นคุณสร้างกริดnโดยnที่nความยาวของข้อความอยู่ที่ไหน แถวแรกคือข้อความต้นฉบับ แต่ละแถวหลังจากนั้นคือแถวด้านบน แต่เลื่อนไปทางซ้าย 1 อักขระโดยที่อักขระตัวแรกเลื่อนไปทางด้านหลัง ตัวอย่างเช่น:

Hello World
ello WorldH
llo WorldHe
lo WorldHel
o WorldHell
 WorldHello
WorldHello 
orldHello W
rldHello Wo
ldHello Wor
dHello Worl

จากนั้นคุณนำตัวอักษรแต่ละตัวไปตามแนวทแยงมุมของ NW ถึง SE และใส่ลงในสตริงใหม่:

Hello World  H
ello WorldH  l
llo WorldHe  o
lo WorldHel  W
o WorldHell  r
 WorldHello  d
WorldHello   e
orldHello W  l
rldHello Wo  (space)
ldHello Wor  o
dHello Worl  l

HloWrdel olข้อความที่เข้ารหัสของคุณคือ หากต้องการถอดรหัสอันดับแรกให้ใช้ความยาวของข้อความที่เข้ารหัสเพิ่ม 1 และหารด้วย 2 ให้โทรไปยังหมายเลขxนี้ ตอนนี้เรารู้xแล้วว่าเริ่มจากตัวอักษรตัวแรกตัวอักษรแต่ละตัวจะอยู่xหลังตัวอักษรสุดท้ายวนไปรอบ ๆ ตัวอย่างเช่น:

H   l   o   W   r   d   e   l     o   l
1   

Then...

H   l   o   W   r   d   e   l     o   l
1                       2

And again...

H   l   o   W   r   d   e   l     o   l
1   3                   2

Until you get...

H   l   o   W   r   d   e   l       o   l
1   3   5   7   9  11   2   4   6   8  10

ตอนนี้เพียงแค่จัดเรียงตัวอักษรในลำดับที่ถูกต้องเพื่อให้ได้Hello World!

ท้าทาย

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

ความต้องการ

โปรแกรม / ฟังก์ชั่นแรก

  • อินพุตสตริงเดี่ยวโดยใช้วิธีการใด ๆ ที่ระบุไว้ข้างต้น
  • ต้องเข้ารหัสสตริงโดยใช้รูปแบบการแปลง Burrows-Wheeler ในแนวทแยง

โปรแกรม / ฟังก์ชั่นที่สอง

  • อินพุตสตริงเดี่ยวโดยใช้วิธีการใด ๆ ที่ระบุไว้ข้างต้น
  • ต้องถอดรหัสสตริงโดยใช้รูปแบบการแปลง Burrows-Wheeler ในแนวทแยง

ข้อ จำกัด

  • คุณไม่สามารถใช้ฟังก์ชันในตัวหรือภายนอกที่ทำงานนี้ให้สำเร็จ
  • ไม่อนุญาตช่องโหว่มาตรฐาน
  • โปรแกรม / ฟังก์ชั่นทั้งสองจะต้องเป็นภาษาเดียวกัน

เกณฑ์การให้คะแนน

นี่คือรหัสกอล์ฟดังนั้นโปรแกรมที่สั้นที่สุดในหน่วยไบต์ชนะ

หากฉันต้องการเพิ่มข้อมูลเพิ่มเติมแสดงความคิดเห็น!


2
เราต้องแปลงสตริงอินพุตความยาวเป็นความยาวคี่หรือไม่
เครื่องมือเพิ่มประสิทธิภาพ

5
นี่ไม่ใช่ transoformation Burrows-Wheeler
FUZxxl

3
การแปลง Burrows-Wheeler นั้นแตกต่างกันไปเนื่องจากอาร์เรย์ของการหมุนทั้งหมดถูกจัดเรียงแบบพจนานุกรมก่อนที่คุณจะใช้รายการสุดท้าย
FUZxxl

@Optimizer ไม่จำเป็น
GamrCorps

คำตอบ:


12

CJam, (4 + 8 =) 12 ไบต์

โปรแกรมการเข้ารหัส:

q2/z

ลองออนไลน์ได้ที่นี่

โปรแกรมถอดรหัส:

q_,2/)/z

ลองออนไลน์ได้ที่นี่

พวกเขาทำงานอย่างไร (หรือมากกว่านั้น) :

การแปลง Dirow Burrows-Wheeler นั้นเป็นลักษณะของสตริงอื่น ๆ โดยมีการพันจากท้าย ถ้าเราถือว่า String เป็นเมทริกซ์ 2 มิติของ 2 คอลัมน์มันจะทำให้การแปลงของเมทริกซ์นั้นง่ายขึ้น ตัวอย่าง:

Hello World

แสดงเป็นเมทริกซ์ 2D เป็น

He
ll
o 
Wo
rl
d

ตอนนี้อ่านคอลัมน์อย่างชาญฉลาดให้:

HloWrdel ol

ซึ่งการแปลง Burrows-Wheeler

การถอดรหัสกลับด้านกระบวนการเขียนสตริงเป็นเมทริกซ์ 2D 2 แถวและอ่านคอลัมน์อย่างชาญฉลาด

การขยายรหัส :

Encoder:

q          "Read the input";
 2/        "divide it into sub arrays of 2 characters";
   z       "Take transform";

ถอดรหัส:

q_,        "Read the input, take copy and get length of copy";
   2/      "Divide the length by 2";
     )/    "Increment and split the input into two rows";
       z   "Take transform";

7

Python 2, 61 ไบต์

E=lambda x:x[::2]+x[1::2]
D=lambda y:(-~len(y)/2*y)[::len(y)/2+1]

Eเข้ารหัสและDถอดรหัส ฉันไม่ได้นับE=และD=สำหรับคะแนน

การถอดรหัสใช้การnห่อหุ้มอักขระทุกรอบโดยที่nครึ่งหนึ่งของความยาวสตริงจะวนขึ้น เหตุผลที่สิ่งนี้กลับเป็นคือ2และnเป็นโมดูโลของความยาวของสตริงดังนั้นการใช้nอักขระทุกตัวกลับด้านจะใช้ทุก2

ถ้าอนุญาตให้ใช้ฟังก์ชั่นเดียวฉันสามารถทำได้ 44 ไบต์

def F(x,b):n=1+len(x)**b>>b;return(n*x)[::n]

เข้ารหัสเมื่อbเป็นFalseและถอดรหัสเมื่อเป็นb Trueการแสดงออกจะมีค่าเท่ากับ1+len(x)**b>>b[2,len(x)/2+1][b]


4

J, 10 + 10 = 20

   ({~#|2*i.@#) 'Hello World'
HloWrdel ol

   (/:#|2*i.@#) 'HloWrdel ol'
Hello World

(การจัดฟันโดยรอบจะไม่ถูกนับเป็นคะแนนเนื่องจากไม่ได้เป็นส่วนหนึ่งของการกำหนดฟังก์ชัน)

ขอบคุณสำหรับFUZxxlสำหรับการปรับปรุง 3 ไบต์

ตอนนี้มันแสดงให้เห็นอย่างชัดเจนว่าทั้งสองฟังก์ชั่นเป็นผกผันเนื่องจากตัวแรกใช้อักขระจากตำแหน่งที่กำหนดโดยรายการ#|2*i.@#และฟังก์ชั่นที่สองจัดเรียงอักขระกลับโดยใช้รายการเดียวกับการเรียงลำดับ

ลองออนไลน์ได้ที่นี่


คนแรกที่สามารถทำได้ใน 10 {~#|2*i.@#ตัวอักษรเช่นกัน:
FUZxxl

@FUZxxl ขอบคุณอัปเดตแล้ว ตอนนี้ความสัมพันธ์ระหว่างทั้งสองฟังก์ชั่นก็แสดงให้เห็นอย่างชัดเจน
randomra

3

Pyth - 5 + 11 = 16 ไบต์

ฉันสังเกตเห็นรูปแบบ! ~ การเต้นที่มีความสุข ~ การแปลงร่างเป็นเพียงการวนลูปผ่านสายเพื่อเลือกองค์ประกอบอื่น ๆ มันใช้งานได้กับคี่เท่านั้นเพราะไม่เช่นนั้นมันจะไม่รับครึ่งหนึ่งขององค์ประกอบ นี่เท่ากับการหมุนเมทริกซ์มุมกว้าง 2 ตัว

Encoder:

%2*2z

การแบ่งขั้นตอนของ Python ไม่วนซ้ำดังนั้นฉันจึงทำซ้ำสตริง

%2      Take every other elements
 *2z    Double input string

ถอดรหัส:

K/hlz2%K*Kz

ไม่มีการพันรอบสำหรับการหั่นแบบเป็นขั้นตอน

K/hlz2       K=length of (input+1)/2
%K           Every kth element
 *Kz         From K*the input

@FryAmTheEggman ฉันค่อนข้างแน่ใจว่ามันควรจะใช้สตริงความยาวคี่เท่านั้น มันเป็นจุดเริ่มต้นของคำอธิบาย
Maltysen

อ๊ะขอโทษ : S
FryAmTheEggman

2

GNU sed -r, (20 + 104 + 1) = 125

+1 เพิ่มเติมในคะแนนสำหรับตัวเลือก -r เพื่อ sed จะถือว่าสตริงอินพุตที่มีความยาวแปลก

Encoder:

s/.*/&&/
s/(.)./\1/g
  • เพิ่มสตริงอินพุตเป็นสองเท่า
  • ดร็อปอักขระทุกตัวที่นับจาก 1

ถอดรหัส:

ตัวถอดรหัสใช้:เป็นอักขระเครื่องหมายชั่วคราวดังนั้นหากปรากฏในสตริงอินพุตคุณจะได้รับพฤติกรรมที่ไม่ได้กำหนด หากสตริงอินพุตถูก จำกัด ไว้ที่ 95 ASCII อักขระเครื่องหมายเหล่านี้สามารถถูกแทนที่ด้วยบางสิ่งที่อยู่นอกช่วง ASCII (เช่น BEL 0x7) เพื่อแก้ไขปัญหานี้

s/.*/:&:/
:l;s/:(.)(.+)(.):/\1:\2:\3/;tl
s/:(.*)/\1:/
:m;s/(.)(.*):(.?)(.*):(.*)/\2:\4:\5\1\3/;tm
s/://g
  • ใส่:เครื่องหมายที่จุดเริ่มต้นและจุดสิ้นสุดของสายป้อน
  • สุ่ม:ไปข้างหน้าและ:ข้างหลังหนึ่งตัวอักษรทีละตัวจนกว่า:เครื่องหมายจะอยู่ด้านข้างของตัวละครกลาง
  • ลบอันแรก:และเพิ่มอีกอัน:ที่ปลาย "A: B:" โดยที่ A คือสตริงที่ประกอบด้วยอักขระแปลก ๆ จากอินพุตข้อความธรรมดาและ B คือสตริงที่ประกอบด้วยอักขระคู่
  • กระเพื่อมตัวละครของ A และ B เข้าด้วยกันหลังจากครั้งสุดท้าย:เพื่อรวมเข้าอีกข้อความธรรมดา
  • ลบ:เครื่องหมายที่เหลืออยู่

2

JavaScript ES6, 41 + 49 = 90 ไบต์

Encoder

(t=>t.replace(/./g,(_,o)=>t[o*2%t.length]))('Hello World')

ถอดรหัส

(t=>t.replace(/./g,(_,o)=>t[-~(l=t.length)/2*o%l]))('HloWrdel ol')

นี่คือฟังก์ชั่นที่ไม่ระบุชื่อดังนั้นฉันจะนับโค้ดภายในวงเล็บเท่านั้นเพราะนั่นคือนิยามฟังก์ชั่นทั้งหมด ลองใช้ตัวอย่างข้อมูลด้านล่าง: (แก้ไขเพื่อใช้ ES5)


วิธีการเกี่ยวกับเรื่องนี้: [t=>t.replace(/./g,(_,o)=>t[o*2%t.length]),t=>t.replace(/./g,(_,o)=>t[(1+(l=t.length))/2*o%l])]? คุณสามารถใช้มันเหมือนและ[...][0]('encode string') [...][1]('decode string')ไม่มีอะไรจะบอกว่ามันทำไม่ได้! และคุณประหยัดได้ 1 ไบต์
Ismael Miguel

ขอบคุณบุมันบอกว่าจะเขียน 2 ฟังก์ชั่นและฉันไม่คิดว่ามันจะนับ
NinjaBearMonkey

ยังคงมีอยู่ 2 ฟังก์ชั่น กฎไม่ได้ระบุชื่อหรือวิธีการเข้าถึงฟังก์ชั่น มันบอกแค่ว่าคุณต้องใช้ 2 ฟังก์ชั่น
Ismael Miguel

1
@IsmaelMiguel ตอนนี้ฉันคิดเกี่ยวกับมันฉันคิดว่าฟังก์ชั่นที่ไม่ระบุชื่อได้รับอนุญาตจากตัวเองดังนั้นการใช้ที่ช่วยฉันได้มากขึ้นไบต์
NinjaBearMonkey

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