Löse eine Diagonal Burrows-Wheeler-Transformation


11

Einführung

In dieser Herausforderung lösen Sie diagonale Burrows-Wheeler-Transformationen. Hier ist ein allgemeiner Überblick darüber, was eine diagonale Burrows-Wheeler-Transformation ist. Um eine Nachricht zu codieren, müssen Sie zuerst sicherstellen, dass sie ungerade ist (dh 5, 7, 9 usw.). Dann sind Sie ein Gitter bilden, ndurch n, wobei ndie Länge der Nachricht ist. Die erste Zeile ist die ursprüngliche Nachricht. Jede Zeile danach ist die Zeile darüber, hat jedoch 1 Zeichen nach links verschoben, wobei sich das erste Zeichen nach hinten bewegt. Beispielsweise:

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

Dann nehmen Sie jeden Buchstaben in der Diagonale von NW nach SE und fügen ihn in eine neue Zeichenfolge ein:

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

Ihre verschlüsselte Nachricht lautet HloWrdel ol. Um zu dekodieren, nehmen Sie zuerst die Länge der codierten Nachricht, addieren Sie 1 und dividieren Sie durch 2. Rufen Sie diese Nummer an x. Jetzt, da wir wissen x, beginnend mit dem ersten Buchstaben, ist jeder Buchstabe xnach dem letzten eine Schleife. Beispielsweise:

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

Ordnen Sie jetzt einfach die Buchstaben in der richtigen Reihenfolge um Hello World!

Herausforderung

Ihre Herausforderung besteht darin, entweder zwei Programme, Funktionen oder jeweils eines zu schreiben. Beide müssen jedoch dieselbe Sprache verwenden. Das erste Programm akzeptiert eine Zeichenfolge als Eingabe über STDIN, Programmargumente oder Funktionsparameter und codiert sie mit dieser Methode. Das zweite Programm akzeptiert eine Zeichenfolge als Eingabe über STDIN, Programmargumente oder Funktionsparameter und decodiert sie mit dieser Methode.

Bedarf

Erstes Programm / Funktion

  • Eine einzelne Zeichenfolgeneingabe mit einer der oben aufgeführten Methoden.
  • Die Zeichenfolge muss mit einem diagonalen Burrows-Wheeler-Transformationsstil codiert werden.

Zweites Programm / Funktion

  • Eine einzelne Zeichenfolgeneingabe mit einer der oben aufgeführten Methoden.
  • Die Zeichenfolge muss mit einem diagonalen Burrows-Wheeler-Transformationsstil dekodiert werden.

Einschränkungen

  • Sie können keine integrierten oder externen Funktionen verwenden, die diese Aufgabe ausführen.
  • Standardlücken sind nicht erlaubt.
  • Beide Programme / Funktionen müssen in derselben Sprache sein.

Wertung

Dies ist Code Golf, also gewinnt das kürzeste Programm in Bytes .

Wenn ich weitere Informationen hinzufügen muss, hinterlasse einen Kommentar!


2
Müssen wir eine Eingabezeichenfolge mit gerader Länge in eine ungerade Länge konvertieren?
Optimierer

5
Dies ist keine Burrows-Wheeler-Transformation.
FUZxxl

3
Eine Burrows-Wheeler-Transformation unterscheidet sich darin, dass das Array aller Rotationen lexikografisch sortiert wird, bevor Sie die letzten Elemente übernehmen.
FUZxxl

@Optimizer ist nicht notwendig.
GamrCorps

Antworten:


12

CJam, (4 + 8 =) 12 Bytes

Kodierungsprogramm:

q2/z

Probieren Sie es hier online aus

Dekodierungsprogramm:

q_,2/)/z

Probieren Sie es hier online aus

Wie (oder besser, warum) arbeiten sie :

Die Diagonal Burrows-Wheeler-Transformation ist im Grunde jedes andere Zeichen der Zeichenfolge, mit Umbruch vom Ende. Wenn wir den String als 2D-Matrix aus 2 Spalten behandeln, läuft es einfach darauf hinaus, die Transformation der Matrix durchzuführen. Beispiel:

Hello World

Wird als 2D-Matrix als dargestellt

He
ll
o 
Wo
rl
d

Wenn Sie es jetzt einfach spaltenweise lesen, geben Sie:

HloWrdel ol

Welches ist die Burrows-Wheeler-Transformation.

Die Dekodierung erfolgt einfach in umgekehrter Reihenfolge. Schreiben Sie die Zeichenfolge als zweizeilige 2D-Matrix und lesen Sie spaltenweise.

Code-Erweiterung :

Encoder:

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

Decoder:

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 Bytes

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

Everschlüsselt und Dentschlüsselt. Ich zähle nicht das E=und D=für die Punktzahl.

Bei der Entschlüsselung wird jedes nZeichen umbrochen, wobei ndie halbe Länge der Zeichenfolge aufgerundet wird. Der Grund, warum dies invertiert wird, ist, dass 2und nmodulo die Länge der Zeichenfolge invers sind, so dass jedes nZeichen invertiert wird , wobei jedes zweite Zeichen invertiert wird 2.

Wenn die Verwendung einer einzelnen Funktion zulässig wäre, könnte ich 44 Bytes ausführen

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

Das verschlüsselt wann bist Falseund entschlüsselt wann bist True. Der Ausdruck 1+len(x)**b>>bist gleich [2,len(x)/2+1][b].


4

J, 10 + 10 = 20

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

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

(Umliegende Klammern werden nicht in die Punktzahl einbezogen, da sie nicht Teil der Funktionsdefinition sind.)

Vielen Dank für FUZxxl für eine 3-Byte-Verbesserung.

Nun wird schön gezeigt, dass die beiden Funktionen umgekehrt sind, da die erste Zeichen Zeichen von Positionen nimmt, die durch die Liste definiert sind, #|2*i.@#und die zweite Funktion die Zeichen unter Verwendung derselben Liste wie die Reihenfolge zurückordnet.

Probieren Sie es hier online aus.


Der erste kann auch in 10 Zeichen ausgeführt werden : {~#|2*i.@#.
FUZxxl

@FUZxxl Danke, aktualisiert. Nun wird die Beziehung zwischen den beiden Funktionen sehr gut dargestellt.
Randomra

3

Pyth - 5 + 11 = 16 Bytes

Ich habe ein Muster bemerkt! ~ Tanzt fröhlich ~ Die Transformation durchläuft einfach nur die Saite und wählt alle anderen Elemente aus. Es funktioniert nur ungerade, da es sonst nie die Hälfte der Elemente bekommen würde. Dies entspricht dem Drehen einer 2-breiten Matrix.

Encoder:

%2*2z

Pythons Step Slicing dreht sich nicht um, also habe ich die Zeichenfolge wiederholt.

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

Decoder:

K/hlz2%K*Kz

Wieder kein Wrap-Around zum Step-Slicing.

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

@FryAmTheEggman Ich bin mir ziemlich sicher, dass es nur eine Zeichenfolge mit ungerader Länge nehmen soll. Es war am Anfang der Beschreibung.
Maltysen

Ups, Entschuldigung. : S
FryAmTheEggman

2

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

Die zusätzlichen +1 in der Punktzahl gelten für die Option -r für sed. Eingabezeichenfolgen mit ungerader Länge werden angenommen.

Encoder:

s/.*/&&/
s/(.)./\1/g
  • Verdoppeln Sie die Eingabezeichenfolge
  • Löschen Sie jedes ungerade Zeichen (ab 1)

Decoder:

Der Decoder wird :als temporäres Markierungszeichen verwendet. Wenn es also in der Eingabezeichenfolge angezeigt wird, erhalten Sie ein undefiniertes Verhalten. Wenn die Eingabezeichenfolge auf 95 ASCII-Zeichen beschränkt ist, können diese Markierungen durch etwas außerhalb des ASCII-Bereichs (z. B. BEL 0x7) ersetzt werden, um dies zu beheben.

s/.*/:&:/
:l;s/:(.)(.+)(.):/\1:\2:\3/;tl
s/:(.*)/\1:/
:m;s/(.)(.*):(.?)(.*):(.*)/\2:\4:\5\1\3/;tm
s/://g
  • Setzen Sie :Markierungen am Anfang und Ende der Eingabezeichenfolge
  • Mische das erste :Vorwärts- und das zweite :Rückwärtszeichen nacheinander, bis sich die :Markierungen auf beiden Seiten des mittleren Zeichens befinden
  • Entfernen Sie die erste :und fügen Sie :am Ende eine weitere hinzu , wobei "A: B:" übrig bleibt, wobei A die Zeichenfolge ist, die aus ungeraden Zeichen aus der Klartexteingabe besteht, und B die Zeichenfolge ist, die aus den geraden Zeichen besteht
  • Riffeln Sie die Zeichen von A und B nach dem letzten :zusammen, um die Klartexteingabe wieder zusammenzusetzen
  • Entfernen Sie die restlichen :Markierungen

2

JavaScript ES6, 41 + 49 = 90 Bytes

Encoder

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

Decoder

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

Da es sich um anonyme Funktionen handelt, zähle ich nur den Code in Klammern, da dies die gesamte Funktionsdefinition ist. Probieren Sie es mit dem folgenden Snippet aus: (geändert, um ES5 zu verwenden)


Wie wäre es damit : [t=>t.replace(/./g,(_,o)=>t[o*2%t.length]),t=>t.replace(/./g,(_,o)=>t[(1+(l=t.length))/2*o%l])]? Du benutzt es wie [...][0]('encode string')und [...][1]('decode string'). Es gibt nichts zu sagen, dass dies nicht möglich ist! Und Sie sparen 1 Byte.
Ismael Miguel

Danke, aber es heißt, 2 Funktionen zu schreiben, und ich glaube nicht, dass dies zählen würde.
NinjaBearMonkey

Das sind noch 2 Funktionen. Die Regeln geben keine Namen oder Möglichkeiten für den Zugriff auf die Funktionen an. Es heißt nur, dass Sie 2 Funktionen verwenden müssen.
Ismael Miguel

1
@IsmaelMiguel Jetzt, wo ich darüber nachdenke, denke ich, dass anonyme Funktionen von sich aus erlaubt sind. Wenn ich das verwende, spare ich noch mehr Bytes.
NinjaBearMonkey

Ich bin froh, dass Sie die Anzahl der Bytes verringert haben.
Ismael Miguel
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.