Eines der weniger bekannten Programmierparadigmen, das für das Code-Golfen eher geeignet zu sein scheint, ist das Overlapping Oriented Programming (OOP) *. Wenn Sie teilweise identischen Code schreiben, können viele Bytes gespeichert werden, indem Sie einfach identische Teile überlappen und sich merken, wo die beiden ursprünglichen Codezeilen beginnen. Ihre Aufgabe ist es zwei zu schreiben überlappende Programme oder Funktionen compress
und decompress
mit der folgenden Spezifikation:
* Im Seriencode wahrscheinlich nicht verwenden.
compress
compress
Nimmt zwei Zeichenfolgen in einem beliebigen Format und überlappt sie so weit wie möglich. Das heißt, eine Zeichenfolge s
mit minimaler Länge wird zurückgegeben, sodass beide Eingabezeichenfolgen Teilzeichenfolgen von sind s
. Außerdem wird eine Ausgabe zurückgegeben, die den Start- und den Endindex beider Zeichenfolgen identifiziert.
Beispiele: (Das genaue IO-Format liegt bei Ihnen)
compress("abcd", "deab") -> "deabcd" ((2,5),(0,3))
compress("abcd", "bc") -> "abcd" ((0,3),(1,2))
compress("abc", "def") -> "abcdef" ((0,2),(3,5)) or "defabc" ((3,5),(0,2))
decompress
decompress
berechnet die Umkehrfunktion von compress
, dh , wenn ein String und zwei Start- und Endindizes (in dem Format, in dem sie von Ihrem zurückgegeben werden compress
) angegeben werden, geben Sie die beiden ursprünglichen Strings zurück. Sie müssen nur gültige Eingaben verarbeiten. Die folgende Gleichheit für alle Saiten halten soll s1
, s2
:
(s1, s2) == decompress (compress (s1, s2))
Beispiele: (Umkehrung der compress
Beispiele)
decompress "deabcd" ((2,5),(0,3)) -> "abcd" "deab"
decompress "abcd" ((0,3),(1,2)) -> "abcd" "bc"
decompress "abcdef" ((0,2),(3,5)) -> "abc" "def"
or (whichever version your "compress" generates)
decompress "defabc" ((3,5),(0,2)) -> "abc" "def"
Wertung
Ihre Punktzahl entspricht der Größe der Zeichenfolge, die beim Aufruf zurückgegeben wird compress("<code of compress>", "<code of decompress>")
. Da dies Code-Golf ist, ist eine niedrigere Punktzahl besser.
Beispiel:
Angenommen, der Code für Ihre Funktion compress
ist c=abcd
und der Code für decompress
ist d=efghi
. Dann compress("c=abcd", "d=efghi")
ergibt sich "c=abcd=efghi"
(und die Indizes, aber diese haben keinen Einfluss auf die Punktzahl), so dass die Punktzahl ist length "c=abcd=efghi" = 12
.
Zusätzliche Regeln
- Im Geiste dieser Herausforderung muss sich Ihr
compress
und in mindestens einem Charakterdecompress
überschneiden . Sie können dies trivial erreichen, indem Sie einen Kommentar hinzufügen. Beachten Sie jedoch, dass dies Ihre Punktzahl erhöht und es möglicherweise kürzere Lösungen gibt, bei denen sich inhärent überlappender Code verwendet wird. compress
unddecompress
sollte in der Lage sein, Zeichenfolgen zu verarbeiten, die druckbare ASCII-Zeichen sowie alle Zeichen enthalten, die Sie zum Definieren voncompress
und verwendet habendecompress
.- Die Indizes können null- oder einindexiert sein.
- Ihre Programme oder Funktionen müssen nicht unbedingt benannt sein
compress
unddecompress
.
Antworten:
GNU Prolog, 105 Punkte
(Dies erfordert GNU Prolog da
prefix
undsuffix
nicht tragbar ist.)Prolog hat einen interessanten, großen Vorteil für diese Herausforderung; Sie können eine Funktion schreiben, die mehrere Aufrufmuster verarbeitet (dh Sie können der Funktion nicht nur einen Eingang zuweisen, um einen entsprechenden Ausgang zu erhalten, sondern Sie können der Funktion einen Ausgang zuweisen, um den entsprechenden Eingang zu erhalten). Als solche können wir eine Funktion definieren, die sowohl Komprimierung als auch Dekomprimierung verarbeiten kann. Dies führt zu einer 105-Byte-Übermittlung, die eine Funktion definiert
o
, die in beide Richtungen funktioniert . (Im Übrigen habe ich es meistens als Dekomprimierer geschrieben - weil es einfacher ist - und den Kompressor "kostenlos" bekommen.) Im Allgemeinen konnten wir in Prolog ein sehr kurzes Programm für diese Aufgabe erwarten, wenn nicht wegen der Tatsache, dass es so schlecht ist bei der Behandlung von Strings (sowohl in Bezug auf fehlende Primitive als auch in Bezug auf die fraglichen Primitive mit furchtbar langen Namen).Das erste Argument für
o
ist ein Tupel von Zeichenfolgen, z"abcd"-"deab"
. Das zweite Argument hat eine Form wie"deabcd"-4/6-4/4
; Dies ist ein ziemlich normales verschachteltes Tupel und bedeutet, dass die Zeichenfolge "deabcd" ist, die erste Zeichenfolge die Länge 4 hat und am sechsten Zeichen endet, die zweite Zeichenfolge die Länge 4 hat und am vierten Zeichen endet. (Beachten Sie, dass eine Zeichenkette in GNU Prolog nur eine Liste von Zeichencodes ist, was das Debuggen ärgerlich macht, da die Implementierung standardmäßig die letztere Interpretation bevorzugt.) Wenn Sie angebeno
Wenn Sie ein Argument angeben, wird das andere für Sie ausgegeben (wenn Sie das erste Argument angeben, fungiert dies als Kompressor und wenn Sie das zweite Argument angeben, als Dekomprimierer). Wenn Sie beide Argumente angeben, wird überprüft, ob die komprimierte Darstellung den angegebenen Zeichenfolgen entspricht. Wenn Sie keine Argumente angeben, wird die Ausgabe folgendermaßen generiert:Die obige Beschreibung des E / A-Formats ist so ziemlich nur eine Beschreibung des Programms. Es ist überhaupt nicht viel im Programm. Die einzige Subtilität liegt in den Hinweisen zur Evaluierungsreihenfolge. Wir müssen sicherstellen, dass das Programm nicht nur eine Suchstrategie verwendet, deren Beendigung garantiert ist, sondern auch die kürzestmögliche Ausgabezeichenfolge erzeugt.
Beim Komprimieren beginnen wir mit
length(C,_)
("C
hat eine Länge"), einem Trick, den ich in vielen Prolog- und Brachylog-Antworten verwendet habe. Wenn dies das erste ist, was Prolog sieht, wird es dazu führen, dass es Prioritäten setzt und die LängeC
über alles andere reduziert . Dies stellt sicher, dass wir eine Mindestlänge habenC
. Die Reihenfolge der Bedingungen ins
wird sorgfältig ausgewählt, so dass die Suche für jede mögliche Kandidatenlänge von eine begrenzte Zeit in Anspruch nimmtC
.A
wird eingeschränkt durchC
(wir wissen nichtC
, aber wir kennen den Zielwert, den wir für seine Länge haben),M
durchA
,U
durchA
undL
durchU
, so dass keine der Suchen unbegrenzte Zeit in Anspruch nehmen kann.Beim Dekomprimieren werden wir
C
direkt vom Benutzer angegeben. Dies stellt wiederum sicher, dass das Programm aufgrund der gleichen Folge von Einschränkungen in endlicher Zeit ausgeführt wird. (Personen, die die Auswertungsreihenfolge von Prolog kennen, werden feststellen, dass die Definition vons
beim Dekomprimieren sehr ineffizient ist. Das Platzierenlength(A,M)
undlength(U,L)
erstens wäre schneller, aber das Bewegenlength(A,M)
zum Start kann zu einer Endlosschleife beim Komprimieren führen, da sie zu diesem Zeitpunkt weder an etwas gebundenA
nochM
an etwas gebunden ist .)quelle
Brachylog ,
5046 BytesProbieren Sie es online!
Dekomprimieren:
Probieren Sie es online!
5 Bytes gespart dank @ ais523
Erläuterung
Die gute Seite deklarativer Sprachen ist, dass wir denselben Code sowohl zum Komprimieren als auch zum Dekomprimieren wiederverwenden können. Daher ist der Code für die Komprimierung genau derselbe wie für die Dekomprimierung , mit einem zusätzlichen Code
~
am Anfang.Dies
~
weist Brachylog an, die Reihenfolge der Argumente umzukehren (dh die Eingabe als Ausgabe und die Ausgabe als Eingabe zu verwenden). Da compress keine hat~
, wird das Prädikat in der Standardreihenfolge ausgeführt. Da decompress nur eine hat, wird diese mit der Eingabe als Ausgabe und der Ausgabe als Eingabe ausgeführt.Auf diese Weise können wir denselben Code (modulo that extra
~
) zum Komprimieren und Dekomprimieren verwenden: Komprimieren stellt die beiden Zeichenfolgen als Eingabe und eine Variable als Ausgabe bereit, und Dekomprimieren stellt die Indizes und die komprimierte Zeichenfolge als Ausgabe und eine Variable als Eingabe bereit .Offensichtlich bedeutet dies auch, dass wir unseren Komprimierungscode etwas explizit beschreiben müssen, damit der Interpreter ihn "rückwärts" ausführen kann. Aus diesem Grund ist der Kompressor selbst etwas lang.
Hier ist eine Aufschlüsselung des Codes für Compress (und damit auch für Decompress):
quelle
Jelly ,
5850 Bytes-1 Byte dank ais523 (Verwendung
⁾
für einen Zwei-Byte-String)Dies kann durchaus durchaus golfen ...
Bei der Komprimierung werden zwei Zeichenfolgenargumente verwendet und eine Liste zurückgegeben:
[[[startA, lengthA], [startB, lengthB]], compressedString]
Die Dekomprimierung verwendet ein Argument (eine solche Liste) und gibt zwei * Zeichenfolgen zurück:
Überlappender Code:
Einseitig indiziert.
* Dies ist möglicherweise aufgrund der impliziten Druckformatierung von Jelly nicht offensichtlich. Daher enthält der oben verlinkte Code bei TryItOnline ein zusätzliches Byte (a
Y
am Ende), um einen Zeilenvorschub zwischen den beiden in die gedruckte Ausgabe einzufügen.Ich habe mit einem einzelnen Programm begonnen, bei dem die Tiefe des ersten (oder einzigen) Arguments für die Entscheidung zwischen Komprimierung und Dekomprimierung verwendet wurde. Eine nicht verwendete Verknüpfung im Dekomprimierungscode (erste Zeile) und ein einzelnes überlappendes Byte sind jedoch um sieben Byte kürzer .
Wie?
quelle
“ṫḣ”
kann durch Verwendung von Jellys Syntax für Strings mit 2 Zeichen um 1 Byte golfen werden.