Burrows, Wheeler และ Back


15

พื้นหลัง

Burrows-Wheeler เปลี่ยน (BWT) คือการเปลี่ยนแปลงแบบพลิกกลับของตัวละครของสตริงว่าผลลัพธ์ในการทำงานที่มีขนาดใหญ่ของตัวละครที่คล้ายกันสำหรับบางประเภทของสตริงเช่นข้อความธรรมดา มันถูกใช้สำหรับตัวอย่างเช่นในขั้นตอนวิธีการบีบอัด bzip2

BWT ถูกกำหนดดังนี้:

รับสตริงอินพุตเช่นcodegolfคำนวณการหมุนที่เป็นไปได้ทั้งหมดและเรียงลำดับตามคำศัพท์:

codegolf
degolfco
egolfcod
fcodegol
golfcode
lfcodego
odegolfc
olfcodeg

BWT ของสตริงcodegolfคือสตริงที่ประกอบด้วยอักขระตัวสุดท้ายของแต่ละสตริงตามลำดับนั่นคือคอลัมน์สุดท้ายของบล็อกด้านบน สำหรับcodegolfผลตอบแทนfodleocgนี้

ด้วยตัวเองการแปลงนี้ไม่สามารถย้อนกลับได้เนื่องจากสตริงcodegolfและgolfcodeผลลัพธ์ในสตริงเดียวกัน อย่างไรก็ตามถ้าเรารู้ว่าสตริงนั้นลงท้ายด้วย a fมีเพียงหนึ่ง preimage ที่เป็นไปได้

งาน

ใช้โปรแกรมหรือฟังก์ชั่นที่ไม่เกี่ยวข้องซึ่งอ่านสตริงเดี่ยวจาก STDIN หรือเป็นบรรทัดคำสั่งหรือฟังก์ชันอาร์กิวเมนต์แล้วพิมพ์หรือส่งคืน BWT หรืออินเวิร์สต์ของสตริงอินพุต

หากสตริงอินพุตไม่มีช่องว่างการส่งของคุณควรผนวกช่องว่างเดียวกับอินพุตและคำนวณ BWT

หากสตริงอินพุตมีช่องว่างอยู่แล้วควรคำนวณ preimage ของ BWT ที่มีช่องว่างต่อท้ายและตัดช่องว่างนั้น

ตัวอย่าง

INPUT:  ProgrammingPuzzles&CodeGolf
OUTPUT: fs&e grodllnomzomaiCrGgPePzu
INPUT:  fs&e grodllnomzomaiCrGgPePzu
OUTPUT: ProgrammingPuzzles&CodeGolf
INPUT:  bt4{2UK<({ZyJ>LqQQDL6!d,@:~L"#Da\6%EYp%y_{ed2GNmF"1<PkB3tFbyk@u0#^UZ<52-@bw@n%m5xge2w0HeoM#4zaT:OrI1I<|f#jy`V9tGZA5su*b7X:Xn%L|9MX@\2W_NwQ^)2Yc*1b7W<^iY2i2Kr[mB;,c>^}Z]>kT6_c(4}hIJAR~x^HW?l1+^5\VW'\)`h{6:TZ)^#lJyH|J2Jzn=V6cyp&eXo4]el1W`AQpHCCYpc;5Tu@$[P?)_a?-RV82[):[@94{*#!;m8k"LXT~5EYyD<z=n`Gfn/;%}did\fw+/AzVuz]7^N%vm1lJ)PK*-]H~I5ixZ1*Cn]k%dxiQ!UR48<U/fbT\P(!z5l<AefL=q"mx_%C:2=w3rrIL|nghm1i\;Ho7q+44D<74y/l/A)-R5zJx@(h8~KK1H6v/{N8nB)vPgI$\WI;%,DY<#fz>is"eB(/gvvP{7q*$M4@U,AhX=JmZ}L^%*uv=#L#S|4D#<
OUTPUT: <#Q6(LFksq*MD"=L0<f^*@I^;_6nknNp;pWPBc@<A^[JZ?\B{qKc1u%wq1dU%;2)?*nl+U(yvuwZl"KIl*mm5:dJi{\)8YewB+RM|4o7#9t(<~;^IzAmRL\{TVH<bb]{oV4mNh@|VCT6X)@I/Bc\!#YKZDl18WDIvXnzL2Jcz]PaWux[,4X-wk/Z`J<,/enkm%HC*44yQ,#%5mt2t`1p^0;y]gr~W1hrl|yI=zl2PKU~2~#Df"}>%Io$9^{G_:\[)v<viQqwAU--A#ka:b5X@<2!^=R`\zV7H\217hML:eiD2ECETxUG}{m2:$r'@aiT5$dzZ-4n)LQ+x7#<>xW)6yWny)_zD1*f @F_Yp,6!ei}%g"&{A]H|e/G\#Pxn/(}Ag`2x^1d>5#8]yP>/?e51#hv%;[NJ"X@fz8C=|XHeYyQY=77LOrK3i5b39s@T*V6u)v%gf2=bNJi~m5d4YJZ%jbc!<f5Au4J44hP/(_SLH<LZ^%4TH8:R
INPUT:  <#Q6(LFksq*MD"=L0<f^*@I^;_6nknNp;pWPBc@<A^[JZ?\B{qKc1u%wq1dU%;2)?*nl+U(yvuwZl"KIl*mm5:dJi{\)8YewB+RM|4o7#9t(<~;^IzAmRL\{TVH<bb]{oV4mNh@|VCT6X)@I/Bc\!#YKZDl18WDIvXnzL2Jcz]PaWux[,4X-wk/Z`J<,/enkm%HC*44yQ,#%5mt2t`1p^0;y]gr~W1hrl|yI=zl2PKU~2~#Df"}>%Io$9^{G_:\[)v<viQqwAU--A#ka:b5X@<2!^=R`\zV7H\217hML:eiD2ECETxUG}{m2:$r'@aiT5$dzZ-4n)LQ+x7#<>xW)6yWny)_zD1*f @F_Yp,6!ei}%g"&{A]H|e/G\#Pxn/(}Ag`2x^1d>5#8]yP>/?e51#hv%;[NJ"X@fz8C=|XHeYyQY=77LOrK3i5b39s@T*V6u)v%gf2=bNJi~m5d4YJZ%jbc!<f5Au4J44hP/(_SLH<LZ^%4TH8:R
OUTPUT: bt4{2UK<({ZyJ>LqQQDL6!d,@:~L"#Da\6%EYp%y_{ed2GNmF"1<PkB3tFbyk@u0#^UZ<52-@bw@n%m5xge2w0HeoM#4zaT:OrI1I<|f#jy`V9tGZA5su*b7X:Xn%L|9MX@\2W_NwQ^)2Yc*1b7W<^iY2i2Kr[mB;,c>^}Z]>kT6_c(4}hIJAR~x^HW?l1+^5\VW'\)`h{6:TZ)^#lJyH|J2Jzn=V6cyp&eXo4]el1W`AQpHCCYpc;5Tu@$[P?)_a?-RV82[):[@94{*#!;m8k"LXT~5EYyD<z=n`Gfn/;%}did\fw+/AzVuz]7^N%vm1lJ)PK*-]H~I5ixZ1*Cn]k%dxiQ!UR48<U/fbT\P(!z5l<AefL=q"mx_%C:2=w3rrIL|nghm1i\;Ho7q+44D<74y/l/A)-R5zJx@(h8~KK1H6v/{N8nB)vPgI$\WI;%,DY<#fz>is"eB(/gvvP{7q*$M4@U,AhX=JmZ}L^%*uv=#L#S|4D#<
INPUT:  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OUTPUT: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
INPUT:  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OUTPUT: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

กฎเพิ่มเติม

  • คุณไม่สามารถใช้โอเปอเรเตอร์ในตัวที่คำนวณ BWT (หรืออินเวอร์สของมัน) ของสตริงได้

  • คุณไม่สามารถใช้โอเปอเรเตอร์ในตัวที่กลับฟังก์ชัน

  • รหัสของคุณอาจพิมพ์บรรทัดขึ้นบรรทัดใหม่หากคุณเลือก STDOUT สำหรับเอาท์พุทแม้ว่าจะไม่รองรับการขึ้นบรรทัดใหม่ในอินพุต

  • รหัสของคุณจะต้องใช้งานได้กับอินพุตของอักขระ ASCII ที่พิมพ์ได้ 500 หรือน้อยกว่านั้น (0x20 ถึง 0x7E) รวมถึงพื้นที่หนึ่งส่วนใหญ่

  • สำหรับอินพุตที่เป็นไปได้ที่อธิบายไว้ข้างต้นรหัสของคุณจะต้องเสร็จสิ้นภายในสิบนาทีบนเครื่องของฉัน (Intel Core i7-3770, 16 GiB RAM) กรณีทดสอบสุดท้ายควรช้าที่สุดดังนั้นให้แน่ใจว่าคุณใช้เวลากับรหัสนั้น

    สำหรับภาษาและแนวทางส่วนใหญ่ควรง่ายต่อการปฏิบัติตามเวลาที่กำหนด กฎนี้มีขึ้น แต่เพียงผู้เดียวเพื่อป้องกันไม่ให้มีการใช้การแปลงใด ๆ ในฐานะผกผันของสัตว์เดรัจฉาน

  • บังคับใช้กฎกอล์ฟมาตรฐาน การส่งที่สั้นที่สุดในหน่วยไบต์ชนะ


"คุณไม่สามารถใช้โอเปอเรเตอร์ในตัวที่คว่ำฟังก์ชั่นได้" ฉันจะแปลกใจมากถ้าสิ่งนั้นมีอยู่จริง!
Hugh Allen

4
@HughAllen invเจมี
Dennis

มันอาจใช้งานได้กับฟังก์ชั่นเล็ก ๆ น้อย ๆ หรือบิวด์อิน แต่มันจะทำงานอย่างไรสำหรับฟังก์ชั่นที่ผู้ใช้กำหนดเอง? เอกสารนี้เป็น "inv" หรือไม่
Hugh Allen

@HughAllen: ฉันไม่รู้ J จริงๆ แต่นี่เป็นตัวอย่างของinvการทำงานกับฟังก์ชั่นที่ผู้ใช้กำหนด ฉันไม่แน่ใจว่าinvจะใช้งาน BWT ได้หรือไม่ แต่ปลอดภัยกว่าขออภัย
Dennis

ที่เกี่ยวข้องดูcodegolf.stackexchange.com/questions/4771/…สำหรับ bzip2 แบบเต็ม
Keith Randall

คำตอบ:


9

Pyth, 29 ไบต์

?tthu+VzSGzz}dzseMS.>L+z\ hlz

สาธิต. สายรัดทดสอบ

นี้แบ่งออกเป็นกลุ่มการเข้ารหัสและถอดรหัสตรงไปตรงมากับรหัสการตัดสินใจที่จะใช้กับประกอบไปด้วย

?tthu+VzSGzz}dzseMS.>L+z\ hlz
                                 Implicit:
                                 z = input()
                                 d = ' '

?           }dz                  If there is a space in the input,
    u     zz                     Update G to the result of the following,
                                 with G starting as z and repeating len(z) times:
     +V                          The vectorized sum of
       zSG                       z and sorted(G)
   h                             Take the first such result, which will consist of
                                 the first character of z followed by the
                                 first cyclic permuation of the pre-BWT string,
                                 which must start with ' '.
 tt                              Remove the first two characters and return.
                 L               Otherwise, left-map (map with the variable as the 
                                 left parameter and a constant as the right)
               .>                cyclic right shift
                  +z\            of z + ' '
                      hlz        over range(len(z)+1)
              S                  Sort the shifted strings,
            eM                   take their last charactes,
           s                     combine into one string and return.

6

CJam, 41 36 35 bytes

q:XS&LX,{X\.+$}*0=1>XS+_,,\fm<$zW>?

ทดสอบที่นี่

คำอธิบาย

q:X   e# Read STDIN and store it in X.
S&    e# Take the set intersection with " ". We'll use this as a truthy/falsy value to
      e# select the correct output later.

# Compute the iBWT:
LX,   e# Push an empty array, compute the length of X.
{     e# Run the following block that many times:
  X\  e# Push X and pull the other array on top.
  .+  e# Add the characters of X to the corresponding line of the other array,
      e# i.e. prepend X as a new column.
  $   e# Sort the rows.
}*
0=    e# Since we just sorted the rows, the first permutation of the output will be
      e# one starting with a space, followed by the string we actually want. So just
      e# pick the first permutation.
1>    e# Remove the leading space.

# Compute the BWT:
XS+   e# Push X and append a space.
_,    e# Get that string's length N.
,\    e# Turn it into a range [0 .. N-1], swap it with the string.
fm<   e# Map each value in the range to the string shifted left by that many characters.
$     e# Sort the permutations.
zW>   e# Transpose the grid and discard all lines but the last.

?     e# Choose between the iBWT and the BWT based on whether the input had a space.

2

Perl 5, 179

อีกหนึ่งไม่ดีเลยจากฉัน อาจมีบางอย่างที่จะได้รับในเกมนี้ แต่มันจะไม่แข่งขันกับภาษากอล์ฟที่สร้างขึ้นตามวัตถุประสงค์

$_=<>;@y=/./g;if(/ /){@x=sort@y;for(1..$#y){@x=sort map$y[$_].$x[$_],0..$#x}
say$x[0]=~/^ (.*)/}else{push@y," ";say map/(.)$/,sort map{$i=$_;join"",
map$y[($_+$i)%@y],0..$#y}0..$#y}

ยกเลิกแข็งแรงเล่นกอล์ฟ:

# Read input
$_ = <>;
# Get all the chars of the input
my @chars = /./g;

if (/ /) {
  # If there's a space, run the IBWT:
  # Make the first column of the table
  my @working = sort @chars;

  # For each remaining character
  for (1 .. $#chars) {
    # Add the input as a new column to the left of @working,
    # then sort @working again
    @working = sort map {
      $chars[$_] . $working[$_]
    } 0 .. $#working;
  }
  # Print the first element of @working (the one beginning with space), sans space
  say $working[0] =~ /^ (.*)/;
} else {
  # BWT
  # Add a space to the end of the string
  push @chars, " ";
  # Get all the rotations of the string and sort them
  @rows = sort map {
    my $offset = $_;
    join "", map {
      $chars[($_ + $offset) % @chars]
    } 0 .. $#chars
  } 0 .. $#chars;

  # Print all the last characters
  say map /(.)$/, @rows;
}

การปรับปรุงเล็กน้อยบางประการ: 1. หากคุณใช้-nสวิตช์ (โดยปกติจะนับเป็น 1 ไบต์) คุณไม่จำเป็นต้อง$_=<>;ใช้ 2. สามารถกลายเป็นfor(1..$#y){...} ... for 1..$#y3. $"ถูกกำหนดค่าเริ่มต้นให้" "และสั้นลงหนึ่งไบต์
Dennis

@Dennis โทรดี ผมมีงบหลายแห่งในforจุดหนึ่งเพื่อให้รูปแบบ postfix ก็ไม่ชนะ แต่เมื่อฉัน pared มันลงไปหนึ่งที่ฉันไม่ได้แจ้งให้ทราบล่วงหน้า :)
ฮอบส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.