Je suis devenu alarmé par la haine croissante des espaces et cette réponse m'a inspiré à m'assurer que le code Morse est à l'abri de cette suppression insidieuse des espaces blancs.
Ainsi, votre tâche sera de créer un programme capable de traduire avec succès le code Morse avec tous les espaces supprimés.
Règles:
L'entrée sera une chaîne composée uniquement de tirets et de points (ASCII 2D et 2E). La sortie n'est pas définie pour une entrée contenant d'autres caractères. N'hésitez pas à utiliser n'importe quelle méthode adaptée à la langue de votre choix pour recevoir l'entrée (stdin, fichier texte, utilisateur rapide, peu importe). Vous pouvez supposer que la saisie du code Morse se compose uniquement des lettres AZ, et que les chiffres ou la ponctuation correspondants ne sont pas requis.
La sortie doit inclure uniquement les mots contenus dans ce fichier de dictionnaire (encore une fois, n'hésitez pas à utiliser une méthode pratique pour accéder au fichier de dictionnaire). Tous les décodages valides doivent être sortis vers stdout, et tous les points et tirets en entrée doivent être utilisés. Chaque mot correspondant dans la sortie doit être séparé par un espace, et chaque décodage possible doit être séparé par une nouvelle ligne. Vous pouvez utiliser les sorties majuscules, minuscules ou mixtes comme pratique.
Toutes les restrictions sur les échappatoires standard s'appliquent à une exception près, comme indiqué ci-dessus, vous pouvez accéder au fichier dictionnaire référencé dans l'exigence 2 via une connexion Internet si vous le souhaitez vraiment. Le raccourcissement d'URL est acceptable, je pense que goo.gl/46I35Z est probablement le plus court.
C'est le golf de code, le code le plus court gagne.
Remarque: La publication du fichier de dictionnaire sur Pastebin a modifié toutes les fins de ligne en séquences de style Windows 0A 0E. Votre programme peut supposer des fins de ligne avec 0A uniquement, 0E uniquement ou 0A 0E.
Cas de test:
Contribution:
......-...-.. ---. -----.-..-..- ..
La sortie doit contenir:
Bonjour le monde
Contribution:
. - ..-. ----- ..-.. ----- ..-. - .. - ... --- .. - ...-.... ... -.-..-.-. ---- ... -. ---.-....-.
La sortie doit contenir:
programmation d'énigmes et de golf de code
Contribution:
-..... -.-..-..-.-.-. - ....-. ---. --- ...-. ---- ..-.- --.. ---. - .... --- ...-..-.-......-... --- ..-. --- ..-- ---.
La sortie doit contenir:
le renard brun rapide saute par-dessus le chien paresseux
AN (.- -.)
etEG (. --.)
?Réponses:
Rubis, 210
S'il existe une pratique telle que le "sur-golf", je soupçonne que j'ai participé cette fois-ci. Cette solution génère un tableau de tableaux de permutations répétées de tous les mots du dictionnaire , de la longueur 1 jusqu'à la longueur de l'entrée. Étant donné que "a" est le mot le plus court du fichier de dictionnaire et que son code comporte deux caractères, il aurait suffi pour générer des permutations d'une longueur jusqu'à la moitié de la taille de l'entrée, mais l'ajout
/2
équivaut à de la verbosité dans ce domaine, alors je me suis abstenu.Une fois que le tableau de permutation a été généré ( NB : il est de longueur 45404 104 dans le cas de l'exemple pangrammatique entré), chaque tableau de permutation est concaténé et ses caractères alphabétiques sont remplacés par leurs équivalents en code Morse via la
(Regexp, Hash)
variante plutôt pratique du#gsub
méthode; nous avons trouvé un décodage valide si cette chaîne est égale à l'entrée.Le dictionnaire est lu (plusieurs fois) à partir d'un fichier nommé "d" et l'entrée ne doit pas contenir de nouvelle ligne.
Exemple d'exécution (avec un dictionnaire qui donnera au programme une chance de se terminer avant la mort par la chaleur de l'univers):
la source
Haskell, 296 caractères
Explication des éléments:
main
lit le dictionnaire, lit stdin, exécute&
et formate la sortie de&
avec un espace approprié.(replicate 97"X"++words".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..")!!)
(une expression à l'intérieur de la définition de&
) est une liste dont les indices sont des codes de caractères (97 est le code de'a'
) et les valeurs sont des séquences Morse.!
(une fonction nommée opérateur infixe) fait correspondre une chaîne à un préfixe; si le préfixe est présent il retourne le reste dans une liste à un élément (succès dans la liste monad), sinon la liste vide (échec dans la liste monad)&
utilise la liste monad pour une exécution «non déterministe»; ild
(un mot du dictionnaire),!
pour faire correspondre la forme Morse de ce mot (w>>=((…)!!).fromEnum
, qui est équivalent àconcatMap (((…)!!) . fromEnum) w
) avec la chaîne d'entréei
,d&j
) pour correspondre au reste de la chaîne, etw:n
, dans la liste monad[w:n]
(qui est l'équivalent concret le plus courtreturn (w:n)
).Notez que chaque ligne après la ligne 6 fait partie de l'
do
expression commencée à la ligne 6; cela prend exactement le même nombre de caractères que l'utilisation de points-virgules sur une seule ligne, mais est plus lisible, bien que vous ne puissiez le faire qu'une seule fois dans un programme.Ce programme est extrêmement lent. Il peut être rendu plus rapide (et légèrement plus long) facilement en stockant les mots altérés à côté des originaux dans une liste plutôt que de les recalculer à chaque correspondance de modèle. La prochaine chose à faire serait de stocker les mots dans un arbre binaire composé de symboles Morse (un tri à 2 aires ) afin d'éviter d'essayer des branches inutiles.
Il pourrait être légèrement raccourci si le fichier de dictionnaire ne contenait pas de symboles inutilisés tels que "-", permettant la suppression de
replicate 97"X"++
en faveur de faire.(-97+)
avant le!!
.la source
(+(-97))
peut être réécrit(-97+)
?|0<1=[]
à la place à la deuxième définitioninteract
et gagnez 12 caractères.interact$unlines.map unwords.(words f&)
concatMap
par>>=
Python -
363345Code:
Explication:
Le dictionnaire doit être stocké sous forme de fichier texte simple nommé "d".
D
,P
,U
Et neN
sont que des variables d'aide pour une définition plus courte de la table de consultation de morse.s(i)
est une fonction récursive qui affiche la partie du message précédemment traduitep
et chaque traduction valide de la partie de code restantei
: sii
est vide, nous avons atteint la fin du code etb
contient la traduction entière, donc nous la faisons simplementprint
. Sinon, nous vérifions chaque motw
dans le dictionnaired
, le traduisons en code morseC
et, si le code restanti
commence parC
, nous ajoutons le motw
au début traduitb
et appelons la fonctions
récursivement sur le reste.Remarque sur l'efficacité:
Ceci est une version assez lente mais golfée. En particulier, le chargement du dictionnaire et la construction de la table de recherche morse (
dict(zip(...))
) à chaque itération (pour éviter plus de variables) coûtent cher. Et il serait plus efficace de traduire tous les mots du fichier dictionnaire une fois à l'avance et non à chaque récursivité à la demande. Ces idées conduisent à la version suivante avec 40 caractères supplémentaires mais une accélération significative :la source
.startswith(C)
par[:len(C)]==C
.d=sorted(open('d').read().split(),key=len,reverse=1)
Ou, faites-le en externe en pré-triant votre dictionnaire de cette façon.M=eval(open('d').read())
:)Perl (5.10+), 293 caractères
Le fichier du dictionnaire doit être enregistré sous "d" (et doit être au format Unix si vous ne voulez pas de CR entre les mots), entrée morse sur stdin, sans retour à la ligne (utilisation
echo -n
).(sauts de ligne uniquement pour le formatage).
Code non golfé:
Mode opératoire:
Les symboles du code Morse sont stockés en changeant "." et "-" en chiffres binaires 0 et 1, en ajoutant un "1" (afin que les points de tête ne soient pas engloutis), en convertissant le nombre binaire en décimal, puis en codant le caractère avec la valeur 61 plus élevée (ce qui me donne tout caractères imprimables et rien qui nécessite une barre oblique inverse).
J'ai pensé à cela comme une sorte de problème de partitionnement et j'ai construit une solution basée sur cela. Pour chaque mot du dictionnaire, il construit un objet regex qui correspondra (et capturera) la représentation morse sans espace de ce mot au début d'une chaîne. Ensuite, il commence une recherche en largeur en créant un état qui ne correspond à aucun mot et dont l'entrée entière est "entrée restante". Ensuite, il développe chaque état en recherchant des mots qui correspondent au début de l'entrée restante et en créant de nouveaux états qui ajoutent le mot aux mots correspondants et suppriment le morse de l'entrée restante. Les États qui n'ont aucune entrée restante réussissent et font imprimer leur liste de mots. Les états qui ne peuvent correspondre à aucun mot (y compris les mots réussis) ne génèrent aucun état enfant.
Notez que dans la version non golfée, les états sont des hachages pour la lisibilité; dans la version golfée, ce sont des tableaux (pour un code plus court et moins de consommation de mémoire); slot
[0]
est l'entrée restante et slot[1]
est les mots correspondants.Commentaire
C'est incroyablement lent. Je me demande s'il n'y a pas de solution. J'ai essayé d'en construire un en utilisant Marpa (un analyseur Earley avec la possibilité de donner plusieurs analyses pour une seule chaîne d'entrée) mais j'ai manqué de mémoire en construisant simplement la grammaire. Peut-être que si j'utilisais une API de niveau inférieur au lieu de l'entrée BNF ...
la source
chomp()
. Devrais-je?ord
au lieu deord$_
. Rasez 1 octet en disantjoin$"
au lieu dejoin" "
Haskell - 418
Ce problème de déco peut être résolu efficacement par une programmation dynamique. Je sais que c'est un codegolf, mais j'adore le code rapide.
Disons que nous avons la chaîne d'entrée
s
, puis nous construisons un tableaudp
,dp[i]
est la liste de tous les résultats de décodage valides de la sous-chaînes[:i]
. Pour chaque motw
dans le dictionnaire, d' abord nous encoder àmw
, nous pouvons calculer une partie dedp[i]
dedp[i - length(mw)]
sis[i - length(mw):i] == mw
. La complexité temporelle de la constructiondp
estO({count of words} {length of s} {max word length})
. Enfin,dp[length(s)]
le dernier élément, c'est ce dont nous avons besoin.En fait, nous n'avons pas besoin de stocker tout le décodage comme élément de chacun
dp[i]
. Ce dont nous avons besoin, c'est du dernier mot décodé. Cela rend l'implémentation beaucoup plus rapide. Il a fallu moins de 2 secondes pour terminer la coque "hello world" sur mon ordinateur portable i3. Pour les autres cas affichés dans la question, le programme ne se terminera pas pratiquement car il y en a trop à produire.En utilisant la technique de programmation dynamique, nous pouvons calculer le nombre de décodages valides . Vous pouvez trouver le code ici . Résultats:
Non golfé
Golfé
la source
PHP,
234226 octetsfonction récursive, prend le dictionnaire d'un fichier nommé
d
.Échoue pour chaque mot du dictionnaire contenant une non-lettre.
Vous pouvez utiliser n'importe quel nom de fichier si vous
define ("d","<filename>");
avant d'appeler la fonction.Ajoutez 2 ou 3 octets pour une exécution plus rapide:
supprimez
$s?:print"$r\n";
, insérez$s!=$m?
avant0!==
et:print$r.$w
avant;}}
.panne
la source
Groovy
377337Remarques
Le dict doit être un fichier nommé
d
. La chaîne morse est passée par ligne de commande. par exemple:Pour la "compression de code morse" j'utilise un arbre binaire
la source