Le code le plus court par nombre de caractères, qui entrera une chaîne en utilisant uniquement des caractères alphabétiques (majuscules et minuscules), des chiffres, des virgules, des points et un point d'interrogation, et renvoie une représentation de la chaîne en code Morse. La sortie du code Morse doit consister en un tiret (-
, ASCII 0x2D) pour un bip long (AKA 'dah') et un point (.
, ASCII 0x2E) pour un bip court (AKA 'dit').
Chaque lettre doit être séparée par un espace (' '
, ASCII 0x20), et chaque mot doit être séparé par une barre oblique (/
, ASCII 0x2F).
Table de code Morse:
texte alternatif http://liranuna.com/junk/morse.gif
Input:
Hello world
Output:
.... . .-.. .-.. --- / .-- --- .-. .-.. -..
Input:
Hello, Stackoverflow.
Output:
.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- .-.-.-
Le nombre de codes comprend les entrées/sorties (c'est-à-dire le programme complet).
Oui, 131!
main(c){for(;c=c?c:(c=toupper(getch())-32)?
"•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5"
[c-12]-34:-3;c/=2)putch(c/2?46-c%2:0);}
J'ai effleuré quelques caractères supplémentaires en combinant la logique des boucles while
et for
en une seule boucle for
, et en déplaçant la déclaration de c
variable dans la définition main
comme paramètre d'entrée. Cette dernière technique que j'ai empruntée à la réponse de Strager à un autre défi .
Pour ceux qui essaient de vérifier le programme avec GCC ou avec des éditeurs ASCII uniquement, vous aurez peut-être besoin de la version suivante, légèrement plus longue:
main(c){for(;c=c?c:(c=toupper(getchar())-32)?c<0?1:
"\x95#\x8CKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5"
[c-12]-34:-3;c/=2)putchar(c/2?46-c%2:32);}
Cette version est plus longue de 17 caractères (pesant 148), en raison des modifications suivantes:
getchar()
et putchar()
au lieu du non portable getch()
et putch()
c<0?1:
" Pour supprimer les ordures des caractères inférieurs à ASCII 32 (à savoir, de '\n'
). Vous obtiendrez toujours les ordures de tout de !"#$%&'()*+[\]^_
`{|}~
, ou n'importe quoi au-dessus ASCII 126.Cela devrait rendre le code complètement portable. Compiler avec:
gcc -std = c89 -funsigned-char morse.c
Le -std=c89
Est facultatif. Le -funsigned-char
Est cependant nécessaire, sinon vous obtiendrez des ordures pour la virgule et le point final.
c;main(){while(c=toupper(getch()))for(c=c-32?
"•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5"
[c-44]-34:-3;c;c/=2)putch(c/2?46-c%2:0);}
À mon avis, cette dernière version est également beaucoup plus attrayante visuellement. Et non, ce n'est pas portable et il n'est plus protégé contre les entrées en dehors des limites. Il a également une interface utilisateur assez mauvaise, prenant une entrée caractère par caractère et la convertissant en code Morse et ayant une condition de sortie non (vous devez appuyer sur Ctrl+Break). Mais un code portable et robuste avec une belle interface utilisateur n'était pas une exigence.
Une explication aussi brève que possible du code suit:
main(c){
while(c = toupper(getch())) /* well, *sort of* an exit condition */
for(c =
c - 32 ? // effectively: "if not space character"
"•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5"[c - 44] - 34
/* This array contains a binary representation of the Morse Code
* for all characters between comma (ASCII 44) and capital Z.
* The values are offset by 34 to make them all representable
* without escape codes (as long as chars > 127 are allowed).
* See explanation after code for encoding format.
*/
: -3; /* if input char is space, c = -3
* this is chosen because -3 % 2 = -1 (and 46 - -1 = 47)
* and -3 / 2 / 2 = 0 (with integer truncation)
*/
c; /* continue loop while c != 0 */
c /= 2) /* shift down to the next bit */
putch(c / 2 ? /* this will be 0 if we're down to our guard bit */
46 - c % 2 /* We'll end up with 45 (-), 46 (.), or 47 (/).
* It's very convenient that the three characters
* we need for this exercise are all consecutive.
*/
: 0 /* we're at the guard bit, output blank space */
);
}
Chaque caractère de la longue chaîne du code contient le code Morse codé pour un caractère de texte. Chaque bit du caractère codé représente soit un tiret soit un point. Un représente un tiret et un zéro représente un point. Le bit le moins significatif représente le premier tiret ou point du code Morse. Un bit "garde" final détermine la longueur du code. C'est-à-dire que le bit le plus élevé de chaque caractère codé représente la fin du code et n'est pas imprimé. Sans ce bit de garde, les caractères avec des points de fin ne pourraient pas être imprimés correctement.
Par exemple, la lettre "L" est ".-..
" Dans le code Morse. Pour représenter cela en binaire, nous avons besoin d'un 0, d'un 1 et de deux autres 0, en commençant par le bit le moins significatif: 0010. Tack un 1 de plus pour un bit de garde, et nous avons notre code Morse codé: 10010, ou décimal 18. Ajoutez le décalage +34 pour obtenir 52, qui est la valeur ASCII du caractère "4". Ainsi, le tableau de caractères codés a un "4" comme 33ème caractère (index 32) .
Cette technique est similaire à celle utilisée pour coder les caractères dans ACoolie's , strager's(2), Miles's , pingw33n's , Alec's , et Andrea's solutions, mais est légèrement plus simple, ne nécessitant qu'une seule opération par bit (décalage/division), plutôt que deux (décalage/division et décrémentation).
MODIFIER:
En lisant le reste des implémentations, je vois que Alec et Anon est venu avec ce schéma de codage — en utilisant le bit de garde — avant moi. La solution d'Anon est particulièrement intéressante, en utilisant la fonctionbin
de Python et en supprimant le préfixe"0b"
Et le bit de garde avec[3:]
, Plutôt que de boucler, anding et décalage, comme Alec et J'ai fait.
En prime, cette version gère également les tirets (-....-
), Les barres obliques (-..-.
), Les deux points (---...
), Les points-virgules (-.-.-.
), Égaux ( -...-
), Et au signe (.--.-.
). Tant que les caractères 8 bits sont autorisés, ces caractères ne nécessitent aucun octet de code supplémentaire à prendre en charge. Aucun autre caractère ne peut être pris en charge avec cette version sans ajouter de longueur au code (sauf s'il y a des codes Morse pour plus/moins de signes).
Parce que je trouve les anciennes implémentations toujours intéressantes et que le texte contient quelques mises en garde applicables à cette version, j'ai laissé le contenu précédent de ce post ci-dessous.
D'accord, sans doute, l'interface utilisateur peut être nulle, non? Donc, en empruntant à strager , j'ai remplacé gets()
, qui fournit une entrée de ligne en tampon et en écho, par getch()
, qui fournit une entrée de caractère sans tampon et sans écho. Cela signifie que chaque caractère que vous tapez est immédiatement traduit en Morse Code à l'écran. C'est peut-être cool. Cela ne fonctionne plus avec stdin ou un argument de ligne de commande, mais c'est sacrément petit.
J'ai cependant gardé l'ancien code ci-dessous pour référence. Voici le nouveau.
W(i){i?W(--i/2),putch(46-i%2):0;}c;main(){while(c=toupper(getch())-13)
c=c-19?c>77|c<31?0:W("œ*~*hXPLJIYaeg*****u*.AC5+;79-@6=0/8?F31,2:4BDE"
[c-31]-42):putch(47),putch(0);}
Enter rompt la boucle et quitte le programme.
W(i){i?W(--i/2),putch(46-i%2):0;}c;main(){while(c=toupper(getch())-13)
c=c-19?W("œ*~*hXPLJIYaeg*****u*.AC5+;79-@6=0/8?F31,2:4BDE"[c-31]-42):
putch(47),putch(0);}
W(i){i?W(--i/2),putch(46-i%2):0;}main(){char*p,c,s[99];gets(s);
for(p=s;*p;)c=*p++,c=toupper(c),c=c-32?c>90|c<44?0:W(
"œ*~*hXPLJIYaeg*****u*.AC5+;79-@6=0/8?F31,2:4BDE"[c-44]-42):
putch(47),putch(0);}
Ceci est basé sur Andrea Python , en utilisant la même technique pour générer le code morse que dans cette réponse. Mais au lieu de stocker les caractères encodables les uns après les autres et de trouver leurs index, j'ai stocké les index les uns après les autres et les recherche par caractère (de la même manière que ma réponse précédente ). Cela évite les longues lacunes près de la fin qui ont causé des problèmes aux implémenteurs antérieurs.
Comme avant , j'ai utilisé un caractère supérieur à 127. Le convertir en ASCII ajoute seulement 3 caractères. Le premier caractère de la longue chaîne doit être remplacé par \x9C
. Le décalage est nécessaire cette fois, sinon un grand nombre de caractères est inférieur à 32, et doit être représenté avec des codes d'échappement.
Comme précédemment, le traitement d'un argument de ligne de commande au lieu de stdin ajoute 2 caractères et l'utilisation d'un véritable espace entre les codes ajoute 1 caractère.
D'un autre côté, certaines des autres routines ici ne traitent pas des entrées en dehors de la plage acceptée de [ .0-9 \? A-Za-z]. Si une telle manipulation était supprimée de cette routine, alors 19 caractères pourraient être supprimés, ce qui ramènerait le total à 177 caractères. Mais si cela est fait et qu'une entrée non valide est envoyée à ce programme, il peut se bloquer et brûler.
Le code dans ce cas pourrait être:
W(i){i?W(--i/2),putch(46-i%2):0;}main(){char*p,s[99];gets(s);
for(p=s;*p;p++)*p=*p-32?W(
"œ*~*hXPLJIYaeg*****u*.AC5+;79-@6=0/8?F31,2:4BDE"
[toupper(*p)-44]-42):putch(47),putch(0);}
Utilisation d'une police de code Morse ?
Console.Write(params[0]);
Perl, 170 caractères (avec l'aide d'un golfeur accompli mauke
). Enveloppé pour plus de clarté; toutes les nouvelles lignes sont amovibles.
$_=uc<>;y,. ,|/,;s/./$& /g;@m{A..Z,0..9,qw(| , ?)}=
".-NINNN..]IN-NII..AMN-AI---.M-ANMAA.I.-].AIAA-NANMMIOMAOUMSMSAH.B.MSOIONARZMIZ"
=~/../g;1while s![]\w|,?]!$m{$&}!;print
"Hello world"
devient "H E L L O / W O R L D"
|
)Dans la version finale, le dictionnaire est optimisé pour l'efficacité d'exécution:
Étant donné que le code joué ne remplace qu'un caractère par boucle (pour enregistrer un caractère de code!), Le nombre de boucles est limité à cinq fois la longueur de l'entrée (trois fois la longueur de l'entrée si seuls les caractères alphabétiques sont utilisés). Mais en ajoutant un g
au s///
opération, le nombre de boucles est limité à trois (deux si seuls les alphabétiques sont utilisés).
Hello 123
H E L L O / 1 2 3
II .] AI AI M- / AO UM SM
.... . .-.. .-.. --- / .-M- .A-- I.--
.... . .-.. .-.. --- / .---- ..--- ...--
for c in raw_input().upper():print c<","and"/"or bin(ord("•ƒwTaQIECBRZ^`šŒ#S#n|':<.$402&9/6)(18?,*%+3-;=>"[ord(c)-44])-34)[3:].translate(" "*47+"/.-"+" "*206),
Utilise la compression de données similaire à implémentation C de P Daddy , mais ne stocke pas les bits dans l'ordre inverse et utilise bin()
pour extraire les données plutôt que l'arithmétique. Notez également que les espaces sont détectés en utilisant l'inégalité; il considère que chaque caractère "moins qu'une virgule" est un espace.
for
, 205 caractères, y compris les sauts de lignefor a in raw_input().upper():
q='_ETIANMSURWDKGOHVF_L_PJBXCYZQ__54_3___2__+____16=/_____7___8_90'.find(a);s=''
while q>0:s='-.'[q%2]+s;q=~-q/2
print['/','--..--','..--..','.-.-.-',''][' ,?.'.find(a)]+s,
Je travaillais avec un codage compact pour les symboles, mais je ne vois pas si cela va mieux que les arbres implicites déjà utilisés, donc je présente le codage ici au cas où quelqu'un d'autre pourrait l'utiliser.
Considérez la chaîne:
--..--..-.-.-..--...----.....-----.--/
qui contient toutes les séquences nécessaires en tant que sous-chaînes. Nous pourrions coder les symboles par décalage et longueur comme ceci:
ET RRRIIGGGJJJJ
--..--..-.-.-..--...----.....-----.--/
CCCC DD WWW 00000
,,,,,, AALLLL BBBB 11111
--..--..-.-.-..--...----.....-----.--/
?????? KKK MMSSS 22222
FFFF PPPP 33333
--..--..-.-.-..--...----.....-----.--/
UUU XXXX 44444
NN PPPP OOO 55555
--..--..-.-.-..--...----.....-----.--/
ZZZZ 66666
77777 YYYY
--..--..-.-.-..--...----.....-----.--/
...... 88888 HHHH
99999 VVVV QQQQ
--..--..-.-.-..--...----.....-----.--/
avec l'espace (c.-à-d. la limite du mot) commençant et se terminant par le dernier caractère (le '/'). N'hésitez pas à l'utiliser, si vous voyez un bon moyen.
La plupart des symboles plus courts ont bien sûr plusieurs codages possibles.
P Daddy a trouvé une version plus courte de cette astuce (et je peux maintenant voir au moins une partie de la redondance ici) et a fait une implémentation de Nice c. Alec a fait une python avec la première version (buggy et incomplète). Hobbs a fait une version Perl assez compacte que je ne fais pas comprendre du tout.
'.- /'{~;2,~&.>(]`(<&3:)@.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-@B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper
J bat C! Impressionnant!
Usage:
'.- /'{~;2,~&.>(]`(<&3:)@.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-@B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper 'Hello World'
.... . .-.. .-.. --- / .-- --- .-. .-.. -..
'.- /'{~;2,~&.>(]`(<&3:)@.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-@B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper 'Hello, Stackoverflow.'
.... . .-.. .-.. --- .-.-.- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- --..--
la nouvelle ligne à la fin de l'entrée n'est pas prise en charge, utilisez donc quelque chose comme ceci
echo -n Hello, Stackoverflow| ../golfscript.rb morse.gs
' '/{{.32|"!etianmsurwdkgohvf!l!pjbxcyzq"?)"UsL?/'#! 08<>"@".,?0123456789"?=or
2base(;>{'.-'\=}%' '}%}%'/'*
Les lettres sont un cas spécial et converties en minuscules et ordonnées dans leurs positions binaires.
Tout le reste est fait par une table de traduction
La solution de 131 caractères C traduite en C # produit 266 caractères:
foreach(var i in Encoding.ASCII.GetBytes(args[0].ToUpper())){var c=(int)i;for(c=(c-32!=0)?Encoding.ASCII.GetBytes("•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5")[c-44]-34:-3;c!=0;c/=2)Console.Write(Encoding.ASCII.GetChars(new byte[]{(byte)((c/2!=0)?46-c%2:0)}));}
qui est plus lisible comme:
foreach (var i in Encoding.ASCII.GetBytes(args[0].ToUpper()))
{
var c = (int)i;
for (c = ((c - 32) != 0) ? Encoding.ASCII.GetBytes("•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5")[c - 44] - 34 : -3
; c != 0
; c /= 2)
Console.Write(Encoding.ASCII.GetChars(new byte[] { (byte)((c / 2 != 0) ? 46 - c % 2 : 0) }));
}
Python 3 One Liner: 172 caractères
print(' '.join('/'if c==' 'else''.join('.'if x=='0'else'-'for x in bin(ord("ijÁĕÁÿïçãáàðøüþÁÁÁÁÁČÁÅ×ÚÌÂÒÎÐÄ×ÍÔÇÆÏÖÝÊÈÃÉÑËÙÛÜ"[ord(c)-44])-192)[3:])for c in input().upper()))
(Encodage de la table de traduction en points de code unicode. Fonctionne très bien, et ils s'affichent bien ici dans mon test sur ma machine Windows Vista.)
Modifié pour réduire à 184 caractères en supprimant certains espaces et crochets inutiles (création d'expositions génériques de la liste).
Modifier à nouveau: Plus d'espace supprimé que je ne savais même pas possible avant de voir d'autres réponses ici - donc jusqu'à 176.
Modifiez à nouveau jusqu'à 172 (woo woo!) En utilisant '' .join au lieu de '' .join et en faisant les espaces séparément. (duh!)
Solution incomplète, mais peut-être que quelqu'un peut en faire une solution complète. Ne gère pas les chiffres ou la ponctuation, mais ne pèse que 154 caractères.
def e(l):
i='_etianmsurwdkgohvf_l_pjbxcyzq'.find(l.lower());v=''
while i>0:v='-.'[i%2]+v;i=(i-1)/2;return v or '/'
def enc(s):return ' '.join(map(e,s))
Une autre solution arborescente.
#define O putchar
char z[99],*t=
" ETINAMSDRGUKWOHBL~FCPJVX~YZQ~~54~3~~~2~~+~~~~16=/~~.~~7,~~8~90";c,p,i=0;
main(){gets(z);while(c=z[i++]){c-46?c-44?c:O(45):O(c);c=c>96?c-32:c;p=-1;
while(t[++p]!=c);for(;p;p/=2){O(45+p--%2);}c-32?O(32):(O(47),O(c));}}
Il pourrait y avoir des erreurs dans l'arborescence source parce que wikipedia semble avoir mal ou peut-être que j'ai mal compris quelque chose.
let rec D i=if i=16 then" "else
let x=int"U*:+F8c]uWjGbJ0-0Dnmd0BiC5?\4o`h7f>9[1E=pr_".[i]-32
if x>43 then"-"+D(x-43)else"."+D x
let M(s:string)=s.ToUpper()|>Seq.fold(fun s c->s+match c with
|' '->"/ "|','->"--..-- "|'.'->".-.-.- "|_->D(int c-48))""
Par exemple
M("Hello, Stack.") |> printfn "%s"
les rendements
.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- .-.-.-
Je pense que ma technique peut être unique jusqu'à présent. L'idée est:
Il y a un peu plus, mais c'est l'essentiel. La virgule, le point et l'espace ne sont pas compris entre 0 et Z, ils sont donc traités spécialement par la "correspondance". Certains caractères "inutilisés" dans la plage 0..Z (comme ";") sont utilisés dans le tableau comme suffixes d'autres traductions morse qui ne sont pas elles-mêmes des "lettres" morse.
Une implémentation vieille d'environ 10 ans
foreach c ask""[l: index? find" etinamsdrgukwohblzfcpövxäqüyj"c while[l >= 2][prin pick"-."odd? l l: l / 2]prin" "]
Cité de: http://www.rebol.com/oneliners.html
(pas de chiffres cependant et les mots sont juste séparés par des doubles espaces:/...)
Voici ma contribution en tant qu'application console dans VB.Net
Module MorseCodeConverter
Dim M() As String = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."}
Sub Main()
Dim I, O
Dim a, b
While True
I = Console.ReadLine()
O = ""
For Each a In I
b = AscW(UCase(a))
If b > 64 And b < 91 Then
O &= M(b - 65) & " "
ElseIf b > 47 And b < 58 Then
O &= M(b - 22) & " "
ElseIf b = 46 Then
O &= ".-.-.- "
ElseIf b = 44 Then
O &= "--..-- "
ElseIf b = 63 Then
O &= "..--.. "
Else
O &= "/"
End If
Next
Console.WriteLine(O)
End While
End Sub
End Module
J'ai laissé un espace blanc pour le rendre lisible. Totaux 1100 caractères. Il lira l'entrée de la ligne de commande, une ligne à la fois, et renverra la sortie correspondante au flux de sortie. La version compressée est ci-dessous, avec seulement 632 caractères.
Module Q
Dim M() As String={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."}
Sub Main()
Dim I,O,a,b:While 1:I=Console.ReadLine():O="":For Each a In I:b=AscW(UCase(a)):If b>64 And b<91 Then:O &=M(b-65)&" ":ElseIf b>47 And b<58 Then:O &=M(b-22)&" ":ElseIf b=46 Then:O &=".-.-.- ":ElseIf b=44 Then:O &="--..-- ":ElseIf b=63 Then:O &= "..--.. ":Else:O &="/":End IF:Next:Console.WriteLine(O):End While
End Sub
End Module
W(n,p){while(n--)putch(".-.-.--.--..--..-.....-----..../"[p++]);}main(){
char*p,c,s[99];gets(s);for(p=s;*p;){c=*p++;c=toupper(c);c=c>90?35:c-32?
"È#À#¶µ´³²±°¹¸·#####Ê#@i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c-44]:63;c-35?
W(c>>5,c&31):0;putch(0);}}
Cela prend l'entrée de stdin. La saisie de la ligne de commande ajoute 2 caractères. Au lieu de:
...main(){char*p,c,s[99];gets(s);for(p=s;...
vous obtenez:
...main(int i,char**s){char*p,c;for(p=s[1];...
J'utilise la page de codes Windows-1252 pour les caractères supérieurs à 127, et je ne sais pas comment ils apparaîtront dans les navigateurs d'autres personnes. Je remarque que, dans mon navigateur au moins (Google Chrome), deux des caractères (entre "@" et "i") n'apparaissent pas. Si vous copiez hors du navigateur et collez dans un éditeur de texte, cependant, ils apparaissent, bien que sous forme de petites boîtes.
Il peut être converti en ASCII uniquement, mais cela ajoute 24 caractères, augmentant le nombre de caractères à 257. Pour ce faire, je décale d'abord chaque caractère de la chaîne de -64, minimisant le nombre de caractères supérieurs à 127. Ensuite Je remplace \x
[~ # ~] xx [~ # ~] le caractère s'échappe si nécessaire. Cela change cela:
...c>90?35:c-32?"È#À#¶µ´³²±°¹¸·#####Ê#@i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c-44]:63;
c-35?W(...
pour ça:
...c>90?99:c-32?"\x88#\x80#vutsrqpyxw#####\x8A#\0PA)\xE0N%Q\nU!O\5\1\66DE 1
\xE1*S$ICH"[c-44]+64:63;c-99?W(...
Voici une version plus joliment formatée et commentée du code:
/* writes `n` characters from internal string to stdout, starting with
* index `p` */
W(n,p){
while(n--)
/* warning for using putch without declaring it */
putch(".-.-.--.--..--..-.....-----..../"[p++]);
/* dmckee noticed (http://tinyurl.com/n4eart) the overlap of the
* various morse codes and created a 37-character-length string that
* contained the morse code for every required character (except for
* space). You just have to know the start index and length of each
* one. With the same idea, I came up with this 32-character-length
* string. This not only saves 5 characters here, but means that I
* can encode the start indexes with only 5 bits below.
*
* The start and length of each character are as follows:
*
* A: 0,2 K: 1,3 U: 10,3 4: 18,5
* B: 16,4 L: 15,4 V: 19,4 5: 17,5
* C: 1,4 M: 5,2 W: 4,3 6: 16,5
* D: 9,3 N: 1,2 X: 9,4 7: 25,5
* E: 0,1 O: 22,3 Y: 3,4 8: 24,5
* F: 14,4 P: 4,4 Z: 8,4 9: 23,5
* G: 5,3 Q: 5,4 0: 22,5 .: 0,6
* H: 17,4 R: 0,3 1: 21,5 ,: 8,6
* I: 20,2 S: 17,3 2: 20,5 ?: 10,6
* J: 21,4 T: 1,1 3: 19,5
*/
}
main(){ /* yuck, but it compiles and runs */
char *p, c, s[99];
/* p is a pointer within the input string */
/* c saves from having to do `*p` all the time */
/* s is the buffer for the input string */
gets(s); /* warning for use without declaring */
for(p=s; *p;){ /* begin with start of input, go till null character */
c = *p++; /* grab *p into c, increment p.
* incrementing p here instead of in the for loop saves
* one character */
c=toupper(c); /* warning for use without declaring */
c = c > 90 ? 35 : c - 32 ?
"È#À#¶µ´³²±°¹¸·#####Ê#@i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c - 44] : 63;
/**** OR, for the ASCII version ****/
c = c > 90 ? 99 : c - 32 ?
"\x88#\x80#vutsrqpyxw#####\x8A#\0PA)\xE0N%Q\nU!O\5\1\66DE 1\xE1"
"*S$ICH"[c - 44] + 64 : 63;
/* Here's where it gets hairy.
*
* What I've done is encode the (start,length) values listed in the
* comment in the W function into one byte per character. The start
* index is encoded in the low 5 bits, and the length is encoded in
* the high 3 bits, so encoded_char = (char)(length << 5 | position).
* For the longer, ASCII-only version, 64 is subtracted from the
* encoded byte to reduce the necessity of costly \xXX representations.
*
* The character array includes encoded bytes covering the entire range
* of characters covered by the challenge, except for the space
* character, which is checked for separately. The covered range
* starts with comma, and ends with capital Z (the call to `toupper`
* above handles lowercase letters). Any characters not supported are
* represented by the "#" character, which is otherwise unused and is
* explicitly checked for later. Additionally, an explicit check is
* done here for any character above 'Z', which is changed to the
* equivalent of a "#" character.
*
* The encoded byte is retrieved from this array using the value of
* the current character minus 44 (since the first supported character
* is ASCII 44 and index 0 in the array). Finally, for the ASCII-only
* version, the offset of 64 is added back in.
*/
c - 35 ? W(c >> 5, c & 31) : 0;
/**** OR, for the ASCII version ****/
c - 99 ? W(c >> 5, c & 31) : 0;
/* Here's that explicit check for the "#" character, which, as
* mentioned above, is for characters which will be ignored, because
* they aren't supported. If c is 35 (or 99 for the ASCII version),
* then the expression before the ? evaluates to 0, or false, so the
* expression after the : is evaluated. Otherwise, the expression
* before the ? is non-zero, thus true, so the expression before
* the : is evaluated.
*
* This is equivalent to:
*
* if(c != 35) // or 99, for the ASCII version
* W(c >> 5, c & 31);
*
* but is shorter by 2 characters.
*/
putch(0);
/* This will output to the screen a blank space. Technically, it's not
* the same as a space character, but it looks like one, so I think I
* can get away with it. If a real space character is desired, this
* must be changed to `putch(32);`, which adds one character to the
* overall length.
} /* end for loop, continue with the rest of the input string */
} /* end main */
Cela bat tout ici, sauf pour quelques implémentations Python. Je continue de penser que cela ne peut pas être plus court, mais je trouve un moyen de raser quelques caractères supplémentaires. Si quelqu'un peut trouver plus de place pour l'amélioration, faites le moi savoir.
MODIFIER:
J'ai remarqué que, bien que cette routine rejette tous les caractères non valides ci-dessus ASCII 44 (sortie juste un espace vide pour chacun), elle ne vérifie pas les caractères non valides en dessous de cette valeur. Pour les vérifier ajoute 5 caractères à la longueur totale, en changeant ceci:
...c>90?35:c-32?"...
pour ça:
...c-32?c>90|c<44?35:"...
Fondamentalement la même chose que la solution d'Andrea , mais en tant que programme complet, et en utilisant des astuces stupides pour le raccourcir.
for c in raw_input().lower():print"".join(".-"[int(d)]for d in bin(
(' etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'
%(('',)*5)).find(c))[3:])or'/',
(les nouvelles lignes ajoutées peuvent toutes être supprimées)
Ou, si vous préférez ne pas utiliser la fonction bin()
en 2.6, nous pouvons le faire en 176:
for c in raw_input():C=lambda q:q>0and C(~-q/2)+'-.'[q%2]or'';print C(
(' etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'%
(('',)*5)).find(c.lower()))or'/',
(encore une fois, les nouvelles lignes ajoutées peuvent toutes être supprimées)
C, 338 caractères
338 avec retrait et tous les sauts de ligne amovibles supprimés:
#define O putchar
#define W while
char*l="x@@@@@ppmmmmm@@FBdYcbcbSd[Kcd`\31(\b1g_<qCN:_'|\25D$W[QH0";
int c,b,o;
main(){
W(1){
W(c<32)
c=getchar()&127;
W(c>96)
c^=32;
c-=32;
o=l[c/2]-64;
b=203+(c&1?o>>3:0);
o=c&1?o&7:o>>3;
W(o>6)
O(47),o=0;
c/=2;
W(c--)
b+=(l[c]-64&7)+(l[c]-64>>3);
b=(((l[b/7]<<7)+l[b/7+1])<<(b%7))>>14-o;
W(o--)
O(b&(1<<o)?46:45);
O(32);
}
}
Ce n'est pas basé sur l'approche arborescente que d'autres personnes ont adoptée. Au lieu de cela, l
code d'abord les longueurs de tous les octets compris entre 32 et 95 inclus, deux octets pour un caractère. Par exemple, D est - .. pour une longueur de 3 et E est. pour une longueur de 1. Ceci est codé comme 011 et 001, donnant 011001. Pour rendre plus de caractères encodables et éviter les échappements, 64 est ensuite ajouté au total, donnant 1011001 - 89, ASCII Y Les caractères non morse se voient attribuer une longueur de 0. La seconde moitié de l
(commençant par \031
) sont les bits du code morse lui-même, avec un point égal à 1 et un tiret 0. Pour éviter d'entrer en ASCII élevé, ces données sont codées à 7 bits/octet.
Le code nettoie d'abord c
, puis calcule la longueur morse de c
(dans o
), puis additionne les longueurs de tous les caractères précédents pour produire b
, l'index des bits dans les données.
Enfin, il parcourt les bits, imprimant des points et des tirets.
La longueur "7" est utilisée comme indicateur spécial pour imprimer un/lorsque vous rencontrez un espace.
Il y a probablement quelques petits gains à retirer de la suppression des crochets, mais je suis loin de certains des meilleurs résultats et j'ai faim, alors ...
static void Main()
{
Console.WriteLine(String.Join(" ", (from c in Console.ReadLine().ToUpper().ToCharArray()
select m[c]).ToArray()));
}
OK, j'ai donc triché. Vous devez également définir un dictionnaire comme suit (cela n'a pas pris la peine de compter les caractères, car cela me souffle hors du jeu):
static Dictionary<char, string> m = new Dictionary<char, string>() {
{'A', ".-"},
{'B', "-.."},
{'C', "-.-."},
{'D', "-.."},
{'E', "."},
{'F', "..-."},
{'G', "--."},
{'H', "...."},
{'I', ".."},
{'J', ".---"},
{'K', "-.-"},
{'L', ".-.."},
{'M', "--"},
{'N', "-."},
{'O', "---"},
{'P', ".--."},
{'Q', "--.-"},
{'R', ".-."},
{'S', "..."},
{'T', "-"},
{'U', "..-"},
{'V', "...-"},
{'W', ".--"},
{'X', "-..-"},
{'Y', "-.--"},
{'Z', "--.."},
{'0', "-----"},
{'1', ".----"},
{'2', "..---"},
{'3', "...--"},
{'4', "....-"},
{'5', "....."},
{'6', "-...."},
{'7', "--..."},
{'8', "---.."},
{'9', "----."},
{' ', "/"},
{'.', ".-.-.-"},
{',', "--..--"},
{'?', "..--.."},
};
Pourtant, quelqu'un peut-il fournir une implémentation C # plus concise qui est également aussi facile à comprendre et à maintenir que cela?
Perl, 206 caractères, en utilisant l'idée de dmckee
C'est plus long que le premier que j'ai soumis, mais je pense toujours que c'est intéressant . Et/ou horrible. Je ne suis pas encore sûr. Cela utilise l'idée de codage de dmckee, ainsi que quelques autres bonnes idées que j'ai vues. Au début, je pensais que la chose "longueur/décalage dans une chaîne fixe" ne pouvait pas produire moins de données que le schéma de mon autre solution, qui utilise deux octets fixes par caractère (et tous les octets imprimables, à ce sujet). J'ai en fait réussi à réduire considérablement les données (un octet par caractère, plus quatre octets pour stocker le modèle de 26 bits dans lequel nous indexons), mais le code pour le récupérer est plus long, malgré mes meilleurs efforts pour jouer au golf. (Moins complexe, OMI, mais plus long quand même).
Quoi qu'il en soit, 206 caractères; les nouvelles lignes sont amovibles sauf la première.
#!Perl -lp
($a,@b)=unpack"b32C*",
"\264\202\317\0\31SF1\2I.T\33N/G\27\308XE0=\x002V7HMRfermlkjihgx\207\205";
$a=~y/01/-./;@m{A..Z,0..9,qw(. , ?)}=map{substr$a,$_%23,1+$_/23}@b;
$_=join' ',map$m{uc$_}||"/",/./g
Explication:
"\264\202\317\0"
) représentent 32 bits de code morse ("--.-..-.-.-----.....--..--------"
) bien que seuls les 26 premiers bits soient utilisés. Il s'agit de la "chaîne de référence".$m{'a'} = '.-'
et cetera, il ne reste plus qu'à faire correspondre les caractères de l'entrée, à les rechercher dans le hachage et à formater la sortie, ce que fait la dernière ligne ... avec l'aide du Shebang, qui dit à Perl de supprimer la nouvelle ligne en entrée, placez les lignes d'entrée dans $_
, et lorsque le code est terminé, écrivez $_
retour à la sortie avec ajout de nouvelles lignes.Ceci est une solution complète basée sur celle de Alec
def e(l):
i=(' etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'%Tuple('_'*5)).find(l.lower());v=''
while i>0:v='-.'[i%2]+v;i=(i-1)/2
return v or '/'
def enc(s):return ' '.join(map(e,s))
J'ai modifié le précédent PHP entry pour être légèrement plus efficace. :)
$a=array(32=>"/",44=>"--..--",1,".-.-.-",48=>"-----",".----","..---","...--","....-",".....","-....","--...","---..","----.",63=>"..--..",1,".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..");
foreach(str_split(strtoupper("hello world?"))as$k=>$v){echo $a[ord($v)]." ";}
Komodo dit 380 caractères sur 2 lignes - la ligne supplémentaire est juste pour la lisibilité. ; D Le 1 intercalé dans le tableau est juste pour enregistrer 2 octets en remplissant cette position du tableau avec des données au lieu de sauter manuellement à la position du tableau après cela.
Considérez le premier contre le second. La différence est clairement visible. :)
array(20=>"data",22=>"more data";
array(20=>"data",1,"more data";
Le résultat final, cependant, est exactement aussi long que vous utilisez les positions du tableau plutôt que de parcourir le contenu, ce que nous ne faisons pas sur ce parcours de golf.
Résultat final: 578 caractères, jusqu'à 380 (198 caractères, soit ~ 34,26% d'économies).
Bash, un script que j'ai écrit il y a quelque temps (l'horodatage dit l'année dernière) pesant 1661 caractères. Juste pour le plaisir vraiment :)
#!/bin/sh
txt=''
res=''
if [ "$1" == '' ]; then
read -se txt
else
txt="$1"
fi;
len=$(echo "$txt" | wc -c)
k=1
while [ "$k" -lt "$len" ]; do
case "$(expr substr "$txt" $k 1 | tr '[:upper:]' '[:lower:]')" in
'e') res="$res"'.' ;;
't') res="$res"'-' ;;
'i') res="$res"'..' ;;
'a') res="$res"'.-' ;;
'n') res="$res"'-.' ;;
'm') res="$res"'--' ;;
's') res="$res"'...' ;;
'u') res="$res"'..-' ;;
'r') res="$res"'.-.' ;;
'w') res="$res"'.--' ;;
'd') res="$res"'-..' ;;
'k') res="$res"'-.-' ;;
'g') res="$res"'--.' ;;
'o') res="$res"'---' ;;
'h') res="$res"'....' ;;
'v') res="$res"'...-' ;;
'f') res="$res"'..-.' ;;
'l') res="$res"'.-..' ;;
'p') res="$res"'.--.' ;;
'j') res="$res"'.---' ;;
'b') res="$res"'-...' ;;
'x') res="$res"'-..-' ;;
'c') res="$res"'-.-.' ;;
'y') res="$res"'-.--' ;;
'z') res="$res"'--..' ;;
'q') res="$res"'--.-' ;;
'5') res="$res"'.....' ;;
'4') res="$res"'....-' ;;
'3') res="$res"'...--' ;;
'2') res="$res"'..---' ;;
'1') res="$res"'.----' ;;
'6') res="$res"'-....' ;;
'7') res="$res"'--...' ;;
'8') res="$res"'---..' ;;
'9') res="$res"'----.' ;;
'0') res="$res"'-----' ;;
esac;
[ ! "$(expr substr "$txt" $k 1)" == " " ] && [ ! "$(expr substr "$txt" $(($k+1)) 1)" == ' ' ] && res="$res"' '
k=$(($k+1))
done;
echo "$res"
Voici une troisième façon complètement différente d'encoder du code morse:
232 caractères
def d(c):
o='';b=ord("Y_j_?><80 !#'/_____f_\x06\x11\x15\x05\x02\x15\t\x1c\x06\x1e\r\x12\x07\x05\x0f\x16\x1b\n\x08\x03\r\x18\x0e\x19\x01\x13"[ord(c.upper())-44])
while b!=1:o+='.-'[b&1];b/=2
return o
e=lambda s:' '.join(map(d,s))
Si vous pouvez trouver un moyen de mapper cela sur un ensemble de caractères imprimables, vous pouvez enregistrer plusieurs caractères. C'est probablement ma solution la plus directe, même si je ne sais pas si c'est la plus lisible.
OK, maintenant j'ai perdu façon trop de temps à ce sujet.
Basé sur certaines des autres réponses.
EDIT: rétréci l'arbre (oui).
#define P putchar
char t['~']="~ETIANMSURWDKGOHVF~L~PJBXCYZQ~~54~3",o,q[9],Q=10;main(c){for(;Q;)t[
"&./7;=>KTr"[--Q]]="2167890?.,"[Q];while((c=getchar())>=0){c-=c<'{'&c>96?32:0;c-
10?c-32?0:P(47):P(10);for(o=1;o<'~';++o)if(t[o]==c){for(;o;o/=2)q[Q++]=45+(o--&1
);for(;Q;P(q[--Q]));break;}P(32);}}
Haskell
type MorseCode = String
program :: String
program = "__5__4H___3VS__F___2 UI__L__+_ R__P___1JWAE"
++ "__6__=B__/_XD__C__YKN__7_Z__QG__8_ __9__0 OMT "
decode :: MorseCode -> String
decode = interpret program
where
interpret = head . foldl exec []
exec xs '_' = undefined : xs
exec (x:y:xs) c = branch : xs
where
branch (' ':ds) = c : decode ds
branch ('-':ds) = x ds
branch ('.':ds) = y ds
branch [] = [c]
Par exemple, decode "-- --- .-. ... . -.-. --- -.. ."
Retour "MORSE CODE"
.
Ce programme est tiré de l'excellent article Fun with Morse Code .
Voici une autre approche, basée sur le travail de dmckee, démontrant à quel point lisible Python est:
244 caractères
def h(l):p=2*ord(l.upper())-88;a,n=map(ord,"AF__GF__]E\\E[EZEYEXEWEVEUETE__________CF__IBPDJDPBGAHDPC[DNBSDJCKDOBJBTCND`DKCQCHAHCZDSCLD??OD"[p:p+2]);return "--..--..-.-.-..--...----.....-----.-"[a-64:a+n-128]
def e(s):return ' '.join(map(h,s))
Limites:
Étant donné que les règles exigeaient le moins caractères, pas le moins octets, vous pourriez réduire au moins l'une de mes tables de recherche (de moitié) si vous vouliez sortir de l'imprimable ASCII caractères.
EDIT: Si j'utilise des caractères Unicode choisis avec naïveté, mais que je les garde juste dans échappé ASCII dans le fichier source, il devient encore un peu plus court car le décodeur est plus simple:
240 caractères
def h(l):a,n=divmod(ord(u'\x06_7_\xd0\xc9\xc2\xbb\xb4\xad\xa6\x9f\x98\x91_____\x14_AtJr2<s\xc1d\x89IQdH\x8ff\xe4Pz9;\xba\x88X_f'[ord(l.upper())-44]),7);return "--..--..-.-.-..--...----.....-----.-"[a:a+n]
def e(s):return ' '.join(map(h,s))
Je pense que cela clarifie également l'intention du programme.
Si vous avez enregistré cela en UTF-8, je pense que le programme compterait jusqu'à 185 caractères, ce qui en fait la solution complète la plus courte Python solution, et la deuxième seulement en Perl. :-)
char*p[36]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
main(){int c;while((c=tolower(getchar()))!=10)printf("%s ",c==46?".-.-.-":c==44?"--..--":c==63?"..--..":c==32?"/":*(p+(c-97)));}
C , 448 octets utilisant des arguments cmdline:
char*a[]={".-.-.-","--..--","..--..","/",".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."},*k=".,? ",*s,*p,x;main(int _,char**v){for(;s=*++v;putchar(10))for(;x=*s++;){p=strchr(k,x);printf("%s ",p?a[p-k]:isdigit(x)?a[x-18]:isalpha(x=toupper(x))?a[x-61]:0);}}
C , 416 octets utilisant stdin:
char*a[]={".-.-.-","--..--","..--..","/",".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."},*k=".,? ",*p,x;main(){while((x=toupper(getchar()))-10){p=strchr(k,x);printf("%s ",p?a[p-k]:isdigit(x)?a[x-18]:isalpha(x)?a[x-61]:0);}}
VBA/VB6 (576 caractères)
Remarque: aucune option explicite
Function MC(S)
For I = 1 To Len(S): C = UCase(Mid(S, I, 1)): MC = MC & IIf(C = " ", "/", "") & IIf(InStr("AEFHIJLPRSUVW12345.?", C), ".", IIf(InStr("BCDGKMNOQTXYZ06789,", C), "-", "")) & IIf(InStr("BCDFHIKNSUVXY23456?", C), ".", IIf(InStr("AGJLMOPQRWZ01789,.", C), "-", "")) & IIf(InStr("BDGHLQRSVXZ34567,.", C), ".", IIf(InStr("CFJKOPUWY01289?", C), "-", "")) & IIf(InStr("CFHLPZ45678,", C), ".", IIf(InStr("JQVXY01239.?", C), "-", "")) & IIf(InStr("56789.?", C), ".", IIf(InStr("01234,", C), "-", "")) & IIf(C = "?", ".", IIf(InStr(".,", C), "-", "")) & " ": Next
End Function
C, 533 caractères
J'ai suivi les conseils de certains commentaires et suis passé à stdin. Tué environ 70 autres personnages à peu près.
#include <stdio.h>
#include <ctype.h>
char *u[36] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
main(){
char*v;int x;char o;
do{
o = toupper(getc(stdin));v=0;if(o>=65&&o<=90)v=u[o-'A'];if(o>=48&&o<=57)v=u[o-'0'+26];if(o==46)v=".-.-.-";if(o==44)v="--..--";if(o==63)v="..--..";if(o==32)v="/";if(v)printf("%s ", v);} while (o != EOF);
}
Ceci est incomplet car il ne gère pas encore les virgules, les arrêts complets et les requêtes.
#define P putchar
char q[10],Q,tree[]=
"EISH54V 3UF 2ARL + WP J 1TNDB6=X/ KC Y MGZ7 Q O 8 90";s2;e(x){q[Q++]
=x;}p(){for(;Q--;putchar(q[Q]));Q=0;}T(int x,char*t,int s){s2=s/2;return s?*t-x
?t[s2]-x?T(x,++t+s2,--s/2)?e(45):T(x,t,--s/2)?e(46):0:e(45):e(46):0;}main(c){
while((c=getchar())>=0){c-=c<123&&c>96?32:0;if(c==10)P(10);if(c==32)P(47);else
T(c,tree,sizeof(tree)),p();P(' ');}}
Enveloppé pour la lisibilité. Seuls deux des sauts de ligne sont requis (un pour le #define, un après l'autre, qui pourrait être un espace). J'ai ajouté quelques caractères non standard mais je n'ai pas ajouté de caractères non 7 bits.