Der wachsende Hass auf Leerzeichen hat mich beunruhigt , und diese Antwort hat mich dazu inspiriert, sicherzustellen, dass Morse-Code vor dieser heimtückischen Entfernung von Leerzeichen sicher ist.
Ihre Aufgabe wird es also sein, ein Programm zu erstellen, das erfolgreich Morse-Code übersetzt, wobei alle Leerzeichen entfernt werden.
Regeln:
Die Eingabe ist eine Zeichenfolge, die nur aus Strichen und Punkten besteht (ASCII 2D und 2E). Die Ausgabe ist für Eingaben, die andere Zeichen enthalten, undefiniert. Sie können eine beliebige Methode verwenden, die für die Sprache Ihrer Wahl geeignet ist, um die Eingaben zu erhalten (stdin, Textdatei, Benutzeraufforderung usw.). Sie können davon ausgehen, dass die Eingabe des Morsecodes nur aus den Buchstaben AZ besteht und keine übereinstimmenden Zahlen oder Satzzeichen erforderlich sind.
Die Ausgabe sollte nur Wörter enthalten, die in dieser Wörterbuchdatei enthalten sind (Sie können auch hier eine beliebige Methode verwenden, um auf die Wörterbuchdatei zuzugreifen). Alle gültigen Dekodierungen sollten auf stdout ausgegeben werden, und alle Punkte und Striche in der Eingabe müssen verwendet werden. Jedes übereinstimmende Wort in der Ausgabe sollte durch ein Leerzeichen getrennt sein, und jede mögliche Dekodierung sollte durch eine neue Zeile getrennt sein. Sie können die Ausgabe in Groß- und Kleinschreibung oder in gemischten Groß- und Kleinschreibung verwenden.
Alle Beschränkungen für Standardlücken gelten mit einer Ausnahme wie oben angegeben. Sie können auf die in Anforderung 2 genannte Wörterbuchdatei über eine Internetverbindung zugreifen, wenn Sie dies wirklich möchten. URL-Kürzung ist akzeptabel, ich glaube, dass goo.gl/46I35Z wahrscheinlich die kürzeste ist.
Dies ist Code Golf, der kürzeste Code gewinnt.
Hinweis: Durch das Posten der Wörterbuchdatei in Pastebin wurden alle Zeilenenden in Sequenzen im Windows-Stil 0A 0E geändert. Ihr Programm kann Zeilenenden mit nur 0A, nur 0E oder 0A 0E annehmen.
Testfälle:
Eingang:
...... -...-.. ---. -----.-..-..- ..
Die Ausgabe muss enthalten:
Hallo Welt
Eingang:
... - ... - ... - ... - ... - ... - ... - ... - ... - ... - ... - ... ... - ... - ... - ... - ... - ... - ...
Die Ausgabe muss enthalten:
Programmieren von Rätseln und Code-Golf
Eingang:
-...- ..- ..- ..- ..- ..- ..- ....- ..- ..- ..- ..- ..- ..- ..- - ...................................................................................................................................................................................... ---.
Die Ausgabe muss enthalten:
der schnelle braune Fuchs springt über den faulen Hund
AN (.- -.)
und unterscheidenEG (. --.)
?Antworten:
Rubin, 210
Wenn es so etwas wie "Übergolf" gibt, habe ich vermutlich dieses Mal daran teilgenommen. Diese Lösung generiert ein Array von Arrays wiederholter Permutationen aller Wörterbuchwörter von Länge 1 bis zur Länge der Eingabe. Da "a" das kürzeste Wort in der Wörterbuchdatei und sein Code zwei Zeichen lang ist, wäre es ausreichend gewesen, Permutationen mit einer Länge von bis zu der halben Größe der Eingabe zu generieren, aber das Hinzufügen entspricht
/2
der Ausführlichkeit in diesem Bereich. also habe ich verzichtet.Sobald die Permutation Array erzeugt worden ist ( NB : es ist mit einer Länge von 45404 104 in dem Fall der pangrammatic Beispiel Eingabe), wird jede Permutation Array verkettet, und seine alphabetischen Zeichen sind mit ihrem Morsealphabet Äquivalenten über die eher bequem ersetzt
(Regexp, Hash)
Variante der#gsub
Methode; Wir haben eine gültige Dekodierung gefunden, wenn diese Zeichenfolge der Eingabe entspricht.Das Wörterbuch wird (mehrmals) aus einer Datei mit dem Namen "d" gelesen, und die Eingabe darf keinen Zeilenumbruch enthalten.
Beispiellauf (mit einem Wörterbuch, das dem Programm die Chance gibt, vor dem Hitzetod des Universums zu enden):
quelle
Haskell, 296 Zeichen
Erklärung der Elemente:
main
Liest das Wörterbuch, liest stdin, führt aus&
und formatiert die Ausgabe&
mit geeigneten Leerzeichen.(replicate 97"X"++words".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..")!!)
(Ein Ausdruck innerhalb der Definition von&
) ist eine Liste, deren Indizes Zeichencodes (97 ist der Code von'a'
) und deren Werte Morsefolgen sind.!
(eine Funktion, die als Infix-Operator bezeichnet wird) vergleicht eine Zeichenfolge mit einem Präfix. Wenn das Präfix vorhanden ist, gibt es den Rest in einer Liste mit einem Element zurück (Erfolg in der Listenmonade), andernfalls die leere Liste (Fehler in der Listenmonade).&
verwendet die Listenmonade für die „nicht deterministische“ Ausführung; esd
(ein Wörterbuchwort),!
, um die Morseform dieses Wortes (w>>=((…)!!).fromEnum
was äquivalent zu istconcatMap (((…)!!) . fromEnum) w
) mit der Eingabezeichenfolge abzugleicheni
,d&j
) auf, um mit dem Rest der Zeichenfolge übereinzustimmen, undw:n
in der Listenmonade zurück[w:n]
(die das kürzere, konkrete Äquivalent zu istreturn (w:n)
).Beachten Sie, dass jede Zeile nach Zeile 6 Teil des
do
in Zeile 6 gestarteten Ausdrucks ist. Dies erfordert genau die gleiche Anzahl von Zeichen wie die Verwendung von Semikolons in einer einzelnen Zeile, ist jedoch besser lesbar, obwohl Sie dies in einem Programm nur einmal tun können.Dieses Programm ist extrem langsam. Es kann schneller (und etwas länger) gemacht werden, indem die morsifizierten Wörter neben den Originalen in einer Liste gespeichert werden, anstatt sie bei jeder Musterübereinstimmung neu zu berechnen. Das nächste, was zu tun wäre, wäre, die Wörter in einem Binärbaum zu speichern, der mit Morse-Symbolen (einem 2-stelligen Trie ) versehen ist, um unnötige Verzweigungen zu vermeiden.
Es könnte etwas kürzer gemacht werden, wenn die Wörterbuchdatei keine unbenutzten Symbole wie "-" enthielte, was das Entfernen von
replicate 97"X"++
zugunsten von.(-97+)
vor dem erlaubt!!
.quelle
(+(-97))
umgeschrieben werden kann als(-97+)
?|0<1=[]
zur zweiten Definition hinzufügeninteract
und gewinne 12 Charaktere.interact$unlines.map unwords.(words f&)
concatMap
mit>>=
Python -
363345Code:
Erläuterung:
Das Wörterbuch muss als reine Textdatei mit dem Namen "d" gespeichert werden.
D
,P
,U
UndN
sind nur einige Helfer Variablen für eine kürzere Definition der morse Lookup - Tabelle.s(i)
ist eine rekursive Funktion, die den zuvor übersetzten Nachrichtenteilp
und jede gültige Übersetzung des restlichen Codeteils ausgibti
: Wenni
leer, haben wir das Ende des Codes erreicht undb
enthalten die gesamte Übersetzung, also haben wir es einfachprint
. Andernfalls überprüfen wir jedes Wortw
im Wörterbuchd
, übersetzen es in Morsecode,C
und wenn der verbleibende Code miti
beginntC
, fügen wir das Wortw
zum übersetzten Anfang hinzub
und rufen die Funktions
rekursiv für den Rest auf.Hinweis zur Effizienz:
Dies ist eine ziemlich langsame, aber golfene Version. Insbesondere das Laden des Wörterbuchs und das Erstellen der Morse-Nachschlagetabelle (
dict(zip(...))
) in jeder Iteration (um mehr Variablen zu vermeiden) kostet viel. Und es wäre effizienter, alle Wörter in der Wörterbuchdatei einmal im Voraus und nicht bei jeder Rekursion nach Bedarf zu übersetzen. Diese Ideen führen zu der folgenden Version mit 40 weiteren Zeichen, die sich jedoch erheblich beschleunigt:quelle
.startswith(C)
mit[:len(C)]==C
.d=sorted(open('d').read().split(),key=len,reverse=1)
Oder tun Sie dies extern, indem Sie Ihr Wörterbuch auf diese Weise vorsortieren.M=eval(open('d').read())
Perl (5.10+), 293 Zeichen
Die Wörterbuchdatei sollte als "d" gespeichert werden (und sollte im Unix-Format sein, wenn Sie keine CRs zwischen Wörtern wünschen), Morseeingabe auf stdin, ohne abschließende Newline (Verwendung
echo -n
).(Zeilenumbrüche nur zur Formatierung).
Ungolfed-Code:
Modus Operandi:
Morsecodesymbole werden durch Ändern von "." Gespeichert. und "-" in die Binärziffern 0 und 1, wobei eine "1" vorangestellt wird (damit die führenden Punkte nicht verschlungen werden), die Binärzahl in eine Dezimalzahl umgewandelt wird und dann das Zeichen mit dem höheren Wert 61 codiert wird (wodurch ich alle bekomme) druckbare Zeichen und nichts, was Backslashing benötigt).
Ich stellte mir das als eine Art Partitionierungsproblem vor und baute darauf eine Lösung auf. Für jedes Wort im Wörterbuch wird ein reguläres Objekt erstellt, das mit der raumlosen Morse-Darstellung des Wortes am Anfang einer Zeichenfolge übereinstimmt (und diese erfasst). Dann beginnt eine Breitensuche, indem ein Zustand erzeugt wird, der keinen Wörtern entspricht und die gesamte Eingabe als "verbleibende Eingabe" enthält. Anschließend wird jeder Zustand erweitert, indem nach Wörtern gesucht wird, die am Anfang der verbleibenden Eingabe übereinstimmen, und neue Zustände erstellt werden, die das Wort zu den übereinstimmenden Wörtern hinzufügen und die Morse aus der verbleibenden Eingabe entfernen. Zustände ohne verbleibende Eingabe sind erfolgreich und ihre Wortliste wird gedruckt. Zustände, die keinem Wort entsprechen (einschließlich erfolgreicher), erzeugen keine untergeordneten Zustände.
Beachten Sie, dass die Zustände in der ungolfed-Version Hashes für die Lesbarkeit sind. in der Golf-Version sind sie Arrays (für kürzeren Code und weniger Speicherverbrauch); slot
[0]
ist die verbleibende Eingabe und slot[1]
die übereinstimmenden Wörter.Kommentar
Das ist gottlos langsam. Ich frage mich, ob es eine Lösung gibt, die es nicht gibt. Ich habe versucht, einen mit Marpa (einem Earley-Parser mit der Möglichkeit, mehrere Parser für eine einzelne Eingabezeichenfolge zu erstellen) zu erstellen, aber es fehlte mir der Speicher, nur um die Grammatik zu konstruieren. Vielleicht, wenn ich eine niedrigere API anstelle der BNF-Eingabe verwendet ...
quelle
chomp()
. Sollte ich?ord
statt mitord$_
. Shave 1 Byte Spruchjoin$"
stattjoin" "
Haskell - 418
Dieses Enthüllungsproblem kann durch dynamische Programmierung effizient gelöst werden. Ich weiß, dass dies ein Codegolf ist, aber ich liebe schnellen Code.
Angenommen, wir haben die Eingabezeichenfolge
s
, dann erstellen wir ein Arraydp
,dp[i]
das die Liste aller gültigen Dekodierungsergebnisse der Teilzeichenfolge enthälts[:i]
. Für jedes Wortw
im Wörterbuch codieren wir es zuerst nachmw
, dann können wir einen Teildp[i]
vondp[i - length(mw)]
if berechnens[i - length(mw):i] == mw
. Die zeitliche Komplexität des Bauensdp
istO({count of words} {length of s} {max word length})
. Schließlich istdp[length(s)]
das letzte Element, was wir brauchen.Tatsächlich müssen wir nicht die gesamte Dekodierung als das Element von jedem speichern
dp[i]
. Was wir brauchen, ist das letzte entschlüsselte Wort. Dies beschleunigt die Implementierung erheblich. Es kostete weniger als 2 Sekunden, um das "Hallo Welt" -Fall auf meinem i3-Laptop zu beenden. In anderen in der Frage genannten Fällen wird das Programm nicht automatisch beendet, da zu viele ausgegeben werden können.Mit der dynamischen Programmiertechnik können wir die Anzahl der gültigen Decodierungen berechnen . Den Code finden Sie hier . Ergebnisse:
Ungolfed
Golf gespielt
quelle
PHP,
234226 Bytesrekursive Funktion, nimmt das Wörterbuch aus einer Datei mit dem Namen
d
.Schlägt für jedes Wort im Wörterbuch fehl, das einen Nichtbuchstaben enthält.
Sie können einen beliebigen Dateinamen verwenden,
define ("d","<filename>");
bevor Sie die Funktion aufrufen.Fügen Sie 2 oder 3 Bytes für eine schnellere Ausführung hinzu:
Entfernen
$s?:print"$r\n";
, Einfügen$s!=$m?
vor0!==
und:print$r.$w
vor;}}
.Nervenzusammenbruch
quelle
Groovy
377337Anmerkungen
Das Diktat muss eine Datei mit dem Namen sein
d
. Die Morsezeichenfolge wird über die Befehlszeile übergeben. z.B:Für "Morse-Code-Komprimierung" verwende ich einen Binärbaum
quelle