Montag Minigolf: Eine Reihe von kurzen Code-Golf- Herausforderungen, die (hoffentlich!) Jeden Montag veröffentlicht werden.
Viele Webanwendungen (insbesondere soziale Medien) kürzen lange Textpassagen automatisch, damit sie in die Formatierung der App passen. In dieser Herausforderung werden wir einen Algorithmus erstellen, mit dem eine Textpassage automatisch auf eine bestimmte Länge gekürzt wird.
Herausforderung
Das Ziel der Herausforderung besteht darin, ein Programm oder eine Funktion zu schreiben, die zwei Argumente enthält:
- T , der Text, der abgeschnitten werden soll.
- L , die maximale Länge, die zurückgegeben werden soll.
Und gibt T zurück , abgeschnitten mit der folgenden Logik:
- Wenn die Länge von T kleiner oder gleich L ist , ist keine Kürzung erforderlich. Geben Sie die ursprüngliche Zeichenfolge zurück.
- Kürzen Sie T auf die Länge L -2. Wenn dies keine Leerzeichen oder Bindestriche enthält, geben Sie T mit genau L -3 Zeichen gefolgt von einem Auslassungszeichen zurück
...
. - Ansonsten kürzen Sie das Ende des Ergebnisses bis zum letzten Leerzeichen oder Bindestrich. Fügen Sie ein Auslassungszeichen hinzu
...
und geben Sie das Ergebnis zurück.
Einzelheiten
- T und L können in beliebiger Reihenfolge und in beliebigem Format angegeben werden.
- Sie können annehmen, dass 3 < L <2 31 .
- Sie dürfen U + 2026 Horizontal Ellipsis nicht verwenden
…
. Sie müssen drei Punkte verwenden. - Die Eingabe beginnt nicht mit einem Leerzeichen oder einem Bindestrich.
- Die Eingabe enthält keine anderen Leerzeichen als normale Leerzeichen. (Keine Tabulatoren, Zeilenumbrüche usw.)
Testfälle
Eingänge:
"This is some very long text." 25
"This-is-some-long-hyphen-separated-text." 33
"Programming Puzzles & Code Golf is a question and answer site for programming puzzle enthusiasts and code golfers." 55
"abcdefghijklmnopqrstuvwxyz" 20
"a b c" 4
"Very long." 100
Ausgänge:
"This is some very long..."
"This-is-some-long-hyphen..."
"Programming Puzzles & Code Golf is a question and..."
"abcdefghijklmnopq..."
"a..."
"Very long."
(Beachten Sie, dass die Anführungszeichen nur angeben sollen, dass es sich um Zeichenfolgen handelt. Sie müssen nicht eingeschlossen werden.)
Wertung
Das ist Code-Golf , also gewinnt der kürzeste gültige Code in Bytes. Tiebreaker geht zu einer Übermittlung über, die als erste ihre letzte Bytezahl erreicht hat. Der Gewinner wird am kommenden Montag, 5. Oktober, ermittelt. Viel Glück!
Bearbeiten: Herzlichen Glückwunsch an Ihren Gewinner, @Jakube mit Pyth erneut, mit 25 Bytes!
Antworten:
Pyth, 25 Bytes
Probieren Sie es online aus: Demo oder Test Suite
Erläuterung:
quelle
Perl,
695952 Bytes51 Byte Code + 1 Byte Befehlszeile. Angenommen, die numerische Eingabe darf mit dem Parameter -i erfolgen.
Verwendung:
quelle
Python 2,
7873 BytesDas Eingabeformat folgt der Beispieleingabe.
quelle
JavaScript (ES6),
123786761 BytesIch hatte nicht erwartet, dass ich das so stark reduzieren könnte, aber es stellte sich heraus, dass die Kombination aus Spleißen und Ersetzen jeden Fall abdecken kann, in dem eine Kürzung erforderlich ist.
Das erste Argument ist die Zeichenfolge, das zweite die Länge. Besonderer Dank geht an edc65 für die Längenüberprüfungsoptimierung!
Hier ist der Originalcode (123 Bytes):
quelle
.length
die Länge einer Saite nicht überprüft werden.(T,L)=>T[L]?T.slice(0,L-2).replace(/([ -][^ -]*|.)$/,'...'):T
Punktzahl 61[ -][^ -]
mit\s\S
zu speichern 5 mehr BytesTI-BASIC, 87 Bytes
TI-BASIC verfügt nicht über viele Befehle zur Manipulation von Zeichenfolgen. Daher müssen wir den letzten Index manuell suchen: Wenn die Zeichenfolge die zu suchende Zeichenfolge nicht enthält, wird
inString(
0 zurückgegeben. Wir suchen nach Bindestrichen und Leerzeichen, beginnend an jeder Position von 1 bisL
und notieren Sie die größte Zahl, die kleiner oder gleich istL-3
. Wenn diese ZahlI
immer noch 0 ist, verwenden wirL-3
stattdessen als Endungsindex.Aufgrund der Einschränkungen des Rechners beträgt der größte adressierbare Index eines Strings 9999; Daher schlägt dies für größere Zeichenfolgen fehl.
Ich verlasse mich auf das Verhalten des Rechners, die Variable automatisch
I
auf 0 zu initialisieren. LöschenI
oder löschen Sie daher den Speicher Ihres Rechners, bevor Sie ihn ausführen.quelle
C # .NET,
187169 BytesHmm ...
quelle
Python 2, 105 Bytes
Angerufen mit
quelle
Groovy, 95 Bytes
Ziemlich unkompliziert, kann wohl weiter golfen werden
quelle
CJam, 34 Bytes
Probieren Sie es online aus: Chrome | Feuerfuchs
quelle
T-SQL, 145 Bytes
Verwendung:
exec a("This is some very long text.", 25) exec a("This-is-some-long-hyphen-separated-text.", 33)
quelle
rs , 116
Zumindest ist es kürzer als C # ...
Live-Demo und Testfälle.
quelle
Ceylon
386333252230222216171153131111Ungolfed Original:
Dies sind 386 Bytes / Zeichen. Einige interessante Features hier:
Die
x[y:z]
Syntax ist syntaktischer Zucker fürx.measure(y, z)
und gibt einen Unterbereich vonx
beginnendy
mit Länge zurückz
- für Zeichenfolgen ist dies eine Teilzeichenfolge. (Es gibt auchx[y..z]
Syntax, die eine ist Spanne von Index y bis z, beide eingeschlossen, wie auch halboffene Spannweitenx[...z]
undx[y...]
.)List.lastIndexWhere
Nimmt ein Prädikat (dh eine Funktion, die ein Listenelement nimmt und einen Booleschen Wert zurückgibt, dh hier aCallable<Boolean, [Character]>
) und gibt den Index des letzten Listenelements an, in dem das Prädikat erfüllt ist (oder null, wenn es nie erfüllt ist). Da Strings Listen sind, funktioniert dies auch für Strings.Das Ergebnis
spaceIndex
ist vom TypInteger|Null
oderInteger?
kurz - dh es kann entweder eine Ganzzahl odernull
(der einzige Wert von TypNull
) sein. (Der NamespaceIndex
stammt aus der Zeit, als ich nicht wusste, dass-
das auch etwas Besonderes ist - ich denke, esbreakIndex
wäre besser.)Mit können
exists spaceIndex
wir überprüfen, obspaceIndex
nicht null ist, und dann etwas anderes tun. (In diesem if-Block weiß der Compiler, dass er nicht null ist ... ohne dass er sich beschwert hätte, wenn ichspaceIndex
auf den String zugegriffen hätte.)Anstelle der lokalen Funktion können
spacePredicate
wir auch eine anonyme Funktion verwendenDies bringt uns auf 333 Zeichen:
Die nächste Optimierung besteht darin, kürzere Variablen- und Funktionsnamen zu verwenden, was uns um 81 Bytes auf 252 reduziert:
Für die Prädikatfunktion muss tatsächlich kein Argumenttyp deklariert sein, der vom Compiler abgeleitet werden kann. Gleiches gilt für die Art von
i
(wo wir noch schreiben müssenvalue
, um es als Deklaration zu kennzeichnen). Diese Erklärung ist jetzt kurz genug, um in eine Zeile zu passen, und bringt uns auf 230:Anstelle von können
e == ' ' || e == '-'
wir auch schreibene in [' ', '-']
(odere in {' ', '-'}
, dies ist ein iterierbarer Konstruktor anstelle eines Tupels). Derin
Operator ordnet der Methode Category.contains zu, was uns auf die Idee bringt, dass wir diecontains
Methode dieses Tupels direkt übergeben können (es ist ein aufrufbares Objekt, das ein beliebiges Objekt annimmt, also auch Zeichen akzeptiert), ohne das(e) => ...
Boilerplate (222 Bytes):Eine andere Kategorie, die dieselben zwei Zeichen enthält, ist die aus zwei Zeichen bestehende Zeichenfolge
" -"
. (Außerdem enthält es auch seine Teilzeichenfolgen, aber das tut hier nicht weh). 216 Bytes.Ich denke, wir haben das Beste aus dieser Zeile herausgeholt, wenden wir uns den anderen zu ... Die letzten beiden return-Anweisungen haben eine Ähnlichkeit, die wir ausnutzen können - sie unterscheiden sich nur in
i
vs.l-3
und verwendeni
nur, wenn sie nicht null sindl-3
. Zum Glück ist das genau das, wofür derelse
Bediener gemacht ist!(Die Klammern scheinen hier erforderlich zu sein, da
else
sie eine niedrigere Priorität haben als[:]
.) Dies sind 171 Zeichen. Jetzti
wird es nur einmal verwendet, damit wir es einbinden können, sodass wir 153 Zeichen haben:Wir können diese
if-return-return
Kombination auch durch eine Kombination der Operatorenthen
undelse
in einem ersetzenreturn
. (then
Gibt den zweiten Operanden zurück, wenn der erste wahr ist, andernfalls null, wodurchelse
der zweite Operand zurückgegeben werden kann.) 131 Bytes (obwohl einige der Einsparungen die Leerzeichen sind, die wir sowieso beseitigen werden):Eine Funktion, die nur einen Rücksprung mit einem Ausdruck enthält, kann alternativ mit der "Fettpfeil" -Notation geschrieben werden, die 123 ergibt:
Durch Entfernen des nicht benötigten Leerzeichens erhalten wir die letzten 111 Bytes:
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Zusätzlich gibt es hier eine Funktion, die die Beispiele aus der Frage druckt (unter Verwendung des Namens,
t
der nach Schritt zwei verwendet wird):quelle
POSIX-Shell + GNU sed, 65 Bytes
Dies ist ein Job für sed gemacht! Aber ich brauchte Shell, um das Längenlimit zu erreichen (vielleicht wäre Perl besser). Der sed-Teil erweitert sich zu einer ziemlich einfachen Sequenz mit bedingten Sprüngen, wenn wir fertig sind:
quelle
Mathematica 192 Bytes
Genannt als
quelle
> <> 74 Bytes
Bei dieser Lösung muss die Zeichenfolge
L
in dieser Reihenfolge abgeschnitten sein und sich bereits auf dem Stapel befinden.Es gibt 7 verschwendete Bytes, die durch Ausrichtungsprobleme verursacht wurden und immer noch versuchen, diese auszuspielen.
quelle
C # (157):
Basierend auf der Antwort von Salah Alami , aber kürzer. Die Zeichenfolgenklasse leitet sich von ab
IEnumerable<char>
, also verwendeT.Contains(" ")||T.Contains("-")
ich stattdessen" -".Any(x=>T.Contains(x))
.Lösung:
Ungolfed:
Aktualisieren:
Gespeichert 6 Bytes dank des Kommentars von SLuck49, mit
Any(T.Contains)
anstelle vonAny(x=>T.Contains(x))
.quelle
.Any(x=>T.Contains(x))
Sie können direkt die Methode anstelle eines Lambda verwenden.Any(T.Contains)
, um 6 Bytes zu sparenGS2 , 29 Bytes
Dieses Programm verwendet die Standardeingabe. Die erste Zeile ist die Zeichenfolge, und die zweite Zeile ist die Ziellängennummer.
GS2-Code ist manchmal etwas schwer zu lesen. :) Hier ist ein Kommentar.
quelle
Groovy, 56 Bytes
Kopierte zuerst die Antwort von Kleyguerth, daher die gleichen Variablennamen ...
Kürzen Sie die Zeichenfolge um 2 Zeichen. Die meiste Arbeit erledigt dann der Regex. Ersetzen Sie einen Bindestrich oder ein Leerzeichen, gefolgt von einer beliebigen Anzahl von Zeichen, die kein Bindestrich oder Leerzeichen am Ende der Zeichenfolge sind, durch ein "." ODER Ersetzen Sie ein beliebiges Zeichen am Ende der Zeichenfolge, wenn alle Zeichen davor weder ein Bindestrich noch ein Leerzeichen mit einem "." Schwieriger in Worte zu fassen als den Regex zu schreiben ...
Bearbeiten: Eigentlich kann man einfach den Teil der Zeichenkette entfernen, der mit der Regex übereinstimmt und am Ende "..." hinzufügen:
quelle
Gelee , 29 Bytes
Probieren Sie es online!
Volles Programm.
quelle
Sauber , 89 Bytes
Probieren Sie es online!
Als eine Funktion
$ :: Int String -> String
quelle
C # (Visual C # Interactive Compiler) , 117 Byte
Basierend auf @ Abba's, basierend auf der Antwort von @ Salah Alami. Anstatt
Contains
und unnötig zu verwendenSubstring
Aufruf zu verwenden, wird IndexOf verwendet, um zu überprüfen, ob in der abgeschnittenen Zeichenfolge ein Bindestrich oder ein Leerzeichen vorhanden ist.Probieren Sie es online!
quelle