language-agnostic code-golf

language agnostic - Convierta una cadena en código Morse



language-agnostic code-golf (30)

C # 266 caracteres

La solución 131 char C traducida a C # produce 266 caracteres:

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)}));}

que es más legible como:

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) })); }

El reto

El código más corto por recuento de caracteres, que ingresará una cadena utilizando solo caracteres alfabéticos (mayúsculas y minúsculas), números, comas, puntos y signo de interrogación, y devuelve una representación de la cadena en código Morse. La salida del código Morse debe consistir en un guion ( - , ASCII 0x2D) para un pitido largo (AKA ''dah'') y un punto ( . , ASCII 0x2E) para un pitido corto (AKA ''dit'').

Cada letra debe estar separada por un espacio ( '' '' , ASCII 0x20), y cada palabra debe estar separada por una barra inclinada ( / , ASCII 0x2F).

Tabla de código Morse:

texto alternativo http://liranuna.com/junk/morse.gif

Casos de prueba:

Input: Hello world Output: .... . .-.. .-.. --- / .-- --- .-. .-.. -..

Input: Hello, Stackoverflow. Output: .... . .-.. .-.. --- --..-- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- .-.-.-

El recuento de códigos incluye entrada / salida (es decir, el programa completo).


C (131 caracteres)

Sí, 13 1 !

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);}

Eché un par de caracteres más combinando la lógica del while y for bucles en un único bucle for , y moviendo la declaración de la variable c a la definición main como un parámetro de entrada. Esta última técnica la tomé prestada de la respuesta de Strager a otro desafío .

Para aquellos que intentan verificar el programa con GCC o con editores de solo ASCII, es posible que necesite la siguiente versión, ligeramente más larga:

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);}

Esta versión tiene 17 caracteres más (con un peso comparativamente enorme de 148), debido a los siguientes cambios:

  • +4: getchar() y putchar() lugar del getch() no portátil getch() y putch()
  • +6: códigos de escape para dos de los caracteres en lugar de caracteres que no son ASCII
  • +1: 32 en lugar de 0 para el carácter de espacio
  • +6: se agregó " c<0?1: " para suprimir la basura de caracteres menores que ASCII 32 (es decir, de ''/n'' ). ¡Aún obtendrás basura de cualquiera de !"#$%&''()*+[/]^_ {|}~ , O algo por encima de ASCII 126.

Esto debería hacer que el código sea completamente portátil. Compilar con:

gcc -std=c89 -funsigned-char morse.c

El -std=c89 es opcional. Sin -funsigned-char es necesario, o obtendrás basura por coma y punto.

135 caracteres

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);}

En mi opinión, esta última versión es mucho más atractiva visualmente también. Y no, no es portátil, y ya no está protegido contra la entrada fuera de límites. También tiene una interfaz de usuario bastante mala, toma la entrada de carácter por carácter y la convierte a código Morse y no tiene condición de salida (debe presionar Ctrl + Break ). Pero el código portátil y robusto con una interfaz de usuario agradable no era un requisito.

A continuación se ofrece una breve explicación del código:

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 */ ); }

Cada carácter en la cadena larga del código contiene el código Morse codificado para un carácter de texto. Cada bit del carácter codificado representa un guión o un punto. Uno representa un guión, y un cero representa un punto. El bit menos significativo representa el primer guión o punto en el Código Morse. Un bit final de "guardia" determina la longitud del código. Es decir, el bit más alto en cada carácter codificado representa el final del código y no se imprime. Sin este bit de guardia, los caracteres con puntos finales no podrían imprimirse correctamente.

Por ejemplo, la letra ''L'' es " .-.. " en Código Morse. Para representar esto en binario, necesitamos un 0, un 1 y dos más 0, comenzando con el bit menos significativo: 0010. Virar uno más 1 para un bit de guardia, y tenemos nuestro código Morse codificado: 10010, o decimal 18. Agregue el desplazamiento +34 para obtener 52, que es el valor ASCII del carácter ''4''. Por lo tanto, la matriz de caracteres codificados tiene un ''4'' como el 33er carácter (índice 32).

Esta técnica es similar a la utilizada para codificar caracteres en las ACoolie''s , strager''s (2) , Miles''s , pingw33n''s , Alec''s y Andrea''s , pero es un poco más simple, requiriendo solo una operación por bit (cambio / división), en lugar de dos (desplazamiento / dividiendo y decrementando).

EDITAR:
Al leer el resto de las implementaciones, veo que Alec y Anon este esquema de codificación, usando el bit de guardia, antes que yo. La solución de Anon es particularmente interesante, utilizando la función bin de Python y quitando el prefijo "0b" y el bit de guardia con [3:] , en lugar de bucles, anding y cambios, como lo hicimos Alec y yo.

Como -....- adicional, esta versión también maneja -....- ( -....- ), -..-. ( -..-. ), ---... puntos ( ---... ), punto y coma ( -.-.-. ), Es igual a ( -...- ), y en el signo ( .--.-. ). Siempre que se permitan caracteres de 8 bits, estos caracteres no requieren bytes de código adicionales para admitir. No se pueden admitir más caracteres con esta versión sin agregarle longitud al código (a menos que haya códigos Morse para signos mayores / menores que).

Como encuentro que las implementaciones anteriores siguen siendo interesantes, y el texto tiene algunas salvedades aplicables a esta versión, he dejado el contenido anterior de esta publicación a continuación.

De acuerdo, presumiblemente, la interfaz de usuario puede apestar, ¿verdad? Entonces, tomando prestado de (2) , he reemplazado (2) gets() , que proporciona entrada de línea con eco amortiguado, con getch() , que proporciona una entrada de caracteres sin búfer y sin búfer. Esto significa que cada personaje que escribe se traduce inmediatamente al código Morse en la pantalla. Tal vez eso es genial. Ya no funciona ni con stdin ni con un argumento de línea de comandos, pero es bastante pequeño.

Sin embargo, he guardado el código anterior a continuación, como referencia. Aquí está lo nuevo.

Nuevo código, con comprobación de límites, 171 caracteres:

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 rompe el ciclo y sale del programa.

Nuevo código, sin límites, 159 caracteres:

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);}

A continuación sigue el viejo código 196/177, con alguna explicación:

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);}

Esto se basa en Andrea''s , usando la misma técnica para generar el código morse que en esa respuesta. Pero en lugar de almacenar los caracteres codificables uno tras otro y encontrar sus índices, almacené los índices uno tras otro y los busqué por carácter (de manera similar a mi respuesta anterior ). Esto evita las brechas largas cerca del final que causaron problemas para los implementadores anteriores.

Como antes , he usado un personaje que es mayor que 127. Convertirlo a ASCII-only agrega 3 caracteres. El primer carácter de la cadena larga debe reemplazarse por /x9C . El desplazamiento es necesario esta vez; de lo contrario, un gran número de caracteres tiene menos de 32 y debe representarse con códigos de escape.

También como antes, procesar un argumento de línea de comandos en lugar de stdin agrega 2 caracteres, y usar un carácter de espacio real entre los códigos agrega 1 carácter.

Por otro lado, algunas de las otras rutinas aquí no tratan con entradas fuera del rango aceptado de [, .0-9 /? A-Za-z]. Si dicho manejo se eliminó de esta rutina, entonces se podrían eliminar 19 caracteres, lo que reduciría el total a 177 caracteres. Pero si se hace esto, y la entrada no válida se alimenta a este programa, puede bloquearse y grabarse.

El código en este caso podría ser:

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);}


F #, 256 caracteres

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))""

Por ejemplo

M("Hello, Stack.") |> printfn "%s"

rendimientos

.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- .-.-.-

Creo que mi técnica puede ser única hasta ahora. La idea es:

  • hay una gama de caracteres ASCII que cubre la mayor parte de lo que queremos (0..Z)
  • solo hay 43 caracteres en este rango
  • así podemos codificar un bit (guión o punto) más un "próximo personaje" en un rango de 86 caracteres
  • el rango ascii (32-117) es todo ''imprimible'' y puede servir como este rango de 86 char
  • entonces la cadena literal codifica una tabla a lo largo de esas líneas

Hay un poco más, pero esa es la esencia. La coma, el punto y el espacio no están en el rango 0..Z, por lo que se manejan especialmente con el "partido". Algunos caracteres ''no utilizados'' en el rango 0..Z (como '';'') se usan en la tabla como sufijos de otras traducciones morse que no son en sí mismas ''letras'' morse.


Golfscript - 106 caracteres - SIN DATOS GRACIOSOS :)

nueva línea al final de la entrada no es compatible, entonces use algo como esto

echo -n Hello, | ../golfscript.rb morse.gs

'' ''/{{.32|"!etianmsurwdkgohvf!l!pjbxcyzq"?)"UsL?/''#! 08<>"@".,?0123456789"?=or 2base(;>{''.-''/=}%'' ''}%}%''/''*

Las letras son un caso especial y se convierten a minúsculas y se ordenan en sus posiciones binarias.
Todo lo demás se hace mediante una tabla de traducción


Pitón

Solución incompleta, pero tal vez alguien pueda hacer una solución completa de eso. No maneja dígitos ni signos de puntuación, pero pesa solo 154 caracteres.

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))


C (233 caracteres)

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);}}

Esto toma la entrada de stdin. Tomando entrada de la línea de comando agrega 2 caracteres. En lugar de:

...main(){char*p,c,s[99];gets(s);for(p=s;...

usted obtiene:

...main(int i,char**s){char*p,c;for(p=s[1];...

Estoy usando la página de códigos de Windows-1252 para los personajes por encima de 127, y no estoy seguro de cómo aparecerán en los navegadores de otras personas. Noté que, al menos en mi navegador (Google Chrome), dos de los personajes (entre "@" e "i") no se muestran. Sin embargo, si copias desde el navegador y pegas en un editor de texto, aparecen, aunque en pequeños cuadros.

Se puede convertir a ASCII solamente, pero esto agrega 24 caracteres, lo que aumenta el número de caracteres a 257. Para hacer esto, primero comparto cada carácter en la cadena por -64, minimizando el número de caracteres que son mayores que 127. Luego Sustituyo /x XX escapes de caracteres cuando sea necesario. Esto cambia esto:

...c>90?35:c-32?"È#À#¶µ´³²±°¹¸·#####Ê#@i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c-44]:63; c-35?W(...

a esto:

...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(...

Aquí hay una versión del código más formateada y comentada:

/* 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 */

Esto es mejor que todo aquí, excepto por un par de implementaciones de Python. Sigo pensando que no puede ser más corto, pero luego encuentro la forma de afeitar a algunos personajes más. Si alguien puede encontrar más margen de mejora, házmelo saber.

EDITAR:

Me di cuenta de que, aunque esta rutina rechaza cualquier carácter no válido por encima de ASCII 44 (generando solo un espacio en blanco para cada uno), no verifica si hay caracteres no válidos por debajo de este valor. Para verificar esto, agrega 5 caracteres a la longitud total, cambiando esto:

...c>90?35:c-32?"...

a esto:

...c-32?c>90|c<44?35:"...


C (248 caracteres)

Otra solución basada en árbol.

#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));}}

Podría haber errores en el árbol fuente porque wikipedia parece tenerlo mal o tal vez entendí mal algo.


J, 124 130 134 caracteres

''.- /''{~;2,~&.>(]`(<&3:)@.(a:=])"0)}.&,&#:&.></.40-~a.i.'')}ggWOKIHX`dfggggggg-@B4*:68,?5</.7>E20+193ACD''{~0>.45-~a.i.toupper

J vence a C! ¡Increíble!

Uso:

''.- /''{~;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, .'' .... . .-.. .-.. --- .-.-.- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- --..--


PHP

Modifiqué la entrada PHP anterior para que fuera un poco más eficiente. :)

$a=array(32=>"/",44=>"--..--",1,".-.-.-",48=>"-----",".----","..---","...--","....-",".....","-....","--...","---..","----.",63=>"..--..",1,".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."); foreach(str_split(strtoupper("hello world?"))as$k=>$v){echo $a[ord($v)]." ";}

Komodo dice 380 caracteres en 2 líneas: la línea adicional es solo para facilitar la lectura. ; D Los 1s intercalados en la matriz son solo para guardar 2 bytes al llenar esa posición de la matriz con datos en lugar de saltar manualmente a la posición de la matriz después de eso.

Considera el primero vs. el segundo. La diferencia es claramente visible. :)

array(20=>"data",22=>"more data"; array(20=>"data",1,"more data";

El resultado final, sin embargo, es exactamente el mismo tiempo que usa las posiciones de la matriz en lugar de recorrer los contenidos, algo que no hacemos en este campo de golf.

Resultado final: 578 caracteres, hasta 380 (198 caracteres o ~ 34.26% de ahorro).


C (381 caracteres)

char*p[36]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."}; main(){int c;while((c=tolower(getchar()))!=10)printf("%s ",c==46?".-.-.-":c==44?"--..--":c==63?"..--..":c==32?"/":*(p+(c-97)));}


C89 (293 caracteres)

Basado en algunas de las otras respuestas.

EDITAR: redujo el árbol (yay).

#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);}}


C89 (388 caracteres)

Esto está incompleto ya que no maneja la coma, la parada completa y la consulta todavía.

#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('' '');}}

Envuelto para la legibilidad. Solo se requieren dos de los saltos de línea (uno para el #define, uno después del otro, que podría ser un espacio). Agregué algunos caracteres no estándar pero no agregué los que no son de 7 bits.


Python (210 caracteres)

Esta es una solución completa basada en Alec''s uno ''s

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))


REBOL (118 caracteres)

Una implementación de aproximadamente 10 años

foreach c ask""[l: index? find" etinamsdrgukwohblzfcpövxäqüyj"c while[l >= 2][prin pick"-."odd? l l: l / 2]prin" "]

Citado de: http://www.rebol.com/oneliners.html

(Sin embargo, no hay dígitos y las palabras están separadas por espacios dobles: / ...)


Comprensión de la lista de Python, trazador de una línea de 159 caracteres

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),

Utiliza el paquete de datos similar a la implementación C de P Daddy , pero no almacena los bits en orden inverso y usa bin() para extraer los datos en lugar de aritmética. Tenga en cuenta también que los espacios se detectan usando desigualdad; considera que cada personaje "menos que coma" es un espacio.

Python for loop, 205 caracteres incluyendo líneas nuevas

for 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,


C # utilizando Linq (133 caracteres)

static void Main() { Console.WriteLine(String.Join(" ", (from c in Console.ReadLine().ToUpper().ToCharArray() select m[c]).ToArray())); }

OK, entonces hice trampa. También necesita definir un diccionario de la siguiente manera (no se molestó en contar los caracteres, ya que esto me saca del juego):

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'', "----."}, {'' '', "/"}, {''.'', ".-.-.-"}, {'','', "--..--"}, {''?'', "..--.."}, };

Aún así, ¿alguien puede proporcionar una implementación de C # más concisa que también es tan fácil de entender y mantener como esta?


Python 2; 171 caracteres

Básicamente lo mismo que Andrea''s , pero como un programa completo y usando trucos estúpidos para acortarlo.

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''/'',

(las nuevas líneas agregadas pueden ser eliminadas)

O, si prefiere no usar la bin()función en 2.6, podemos hacerlo 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''/'',

(nuevamente, las nuevas líneas agregadas pueden ser eliminadas)



Aquí está mi contribución como aplicación de consola en 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

Dejé el espacio en blanco para que sea legible. Totales 1100 caracteres Leerá la entrada de la línea de comando, una línea a la vez, y enviará la salida correspondiente a la secuencia de salida. La versión comprimida está debajo, con solo 632 caracteres.

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


Estuve jugueteando con una codificación compacta de los símbolos, pero no veo si conseguir algo mejor que los árboles implícitos que ya están en uso, así que presento la codificación aquí en caso de que alguien más pueda usarla.

Considera la cadena:

--..--..-.-.-..--...----.....-----.--/

que contiene todas las secuencias necesarias como subcadenas. Podríamos codificar los símbolos por desplazamiento y longitud de esta manera:

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 --..--..-.-.-..--...----.....-----.--/

con el espacio (es decir, el límite de palabras) que comienza y termina en el carácter final (el ''/''). Siéntase libre de usarlo, si ve una buena manera.

La mayoría de los símbolos más cortos tienen varias codificaciones posibles, por supuesto.

P Daddy encontró una versión más corta de este truco (y ahora puedo ver al menos parte de la redundancia aquí) e hizo una buena implementación c. Alec hizo una implementación de Python con la primera versión (defectuosa e incompleta). Hobbs hizo una versión perl bastante compacta que no entiendo en absoluto.


Perl, 170 caracteres (con un poco de ayuda del consumado golfista mauke ). Envuelto para mayor claridad; todas las nuevas líneas son extraíbles.

$_=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

Explicación:

  1. Extrae el diccionario morse. Cada símbolo se define en términos de dos caracteres, que pueden ser puntos o guiones literales, o una referencia al valor de otro carácter definido. E y T contienen caracteres falsos para evitar desintegrar el decodificador; los eliminaremos más tarde.
  2. Lee y formatea la entrada. "Hello world" convierte en "HELLO / WORLD"
  3. El siguiente paso depende de que los diccionarios de entrada y salida sean distintos, así que convierta los puntos en la entrada a un carácter no utilizado (barra vertical, | )
  4. Reemplace cualquier char en la entrada que ocurra en el diccionario morse con su valor en el diccionario, hasta que no ocurran reemplazos.
  5. Retire el simulacro mencionado en el paso 1.
  6. Imprime la salida.

En la versión final, el diccionario está optimizado para la eficiencia del tiempo de ejecución:

  • Todos los caracteres de un solo símbolo (E y T) y los caracteres de dos símbolos (A, I, M y N) se definen directamente y se decodifican en una sola pasada.
  • Todos los caracteres de tres símbolos se definen en términos de un carácter de dos símbolos y un símbolo literal, decodificando en dos pasadas.
  • Todos los caracteres de cuatro símbolos se definen en términos de dos caracteres de dos símbolos, decodificando en dos pasadas con tres reemplazos.
  • Los caracteres de cinco y seis símbolos (números y puntuación) se decodifican en tres pasadas, con cuatro o cinco reemplazos respectivamente.

Como el código golfed solo reemplaza un carácter por bucle (para guardar un carácter de código), el número de bucles está limitado a cinco veces la longitud de la entrada (tres veces la longitud de la entrada si solo se usan alfabéticos). Pero al agregar una g a la operación s/// , el número de bucles está limitado a tres (dos si solo se usan alfabéticos).

Transformación de ejemplo:

Hello 123 H E L L O / 1 2 3 II .] AI AI M- / AO UM SM .... . .-.. .-.. --- / .-M- .A-- I.-- .... . .-.. .-.. --- / .---- ..--- ...--


Bash , un guión que escribí hace un tiempo (el sello de tiempo dice que el año pasado) pesaba unos fuertes 1661 caracteres. Solo por diversión realmente :)

#!/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"


C, 338 caracteres

338 con indentación y todos los saltos de línea extraíbles eliminados:

#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); } }

Esto no se basa en el enfoque de árbol que otras personas han estado tomando. En cambio, lprimero codifica las longitudes de todos los bytes entre 32 y 95 inclusive, dos bytes para un personaje. Como ejemplo, D es - .. para una longitud de 3 y E es. para una longitud de 1. Esto se codifica como 011 y 001, dando 011001. Para hacer más caracteres codificables y evitar escapes, 64 se agrega al total, dando 1011001 - 89, ASCII Y. Los caracteres no morse se les asigna una longitud de 0. La segunda mitad de l(comenzando con /031) son los bits del código morse en sí, con un punto que es 1 y un guión 0. Para evitar entrar en ASCII alto, estos datos están codificados a 7 bits / byte.

Primero c, el código se desinfecta , luego calcula la longitud morse de c(in o), luego suma las longitudes de todos los caracteres previos para producir b, el índice de bit en los datos.

Finalmente, recorre los bits, imprimiendo puntos y guiones.

La longitud ''7'' se usa como una bandera especial para imprimir a / cuando se encuentra con un espacio.

Probablemente se obtengan algunos pequeños beneficios al eliminar los paréntesis, pero estoy bastante lejos de algunos de los mejores resultados y tengo hambre, así que ...


C , 448 bytes usando argumentos de 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 bytes usando 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);}}


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]

Por ejemplo, decode "-- --- .-. ... . -.-. --- -.. ."regresa "MORSE CODE".

Este programa es tomado del excelente artículo Fun with Morse Code .


Perl, 206 caracteres, usando la idea de dmckee

Esto es más largo que el primero que envié, pero aún así creo que es interesante . Y / o horrible Todavia no estoy seguro. Esto hace uso de la idea de codificación de dmckee, más algunas otras buenas ideas que vi. Inicialmente, pensé que la cosa "longitud / desplazamiento en una cadena fija" no podría ofrecer menos datos que el esquema en mi otra solución, que usa dos bytes por char (y todos los bytes imprimibles). De hecho, me las arreglé para obtener los datos mucho menos (un byte por char, más cuatro bytes para almacenar el patrón de 26 bits que estamos indexando) pero el código para volver a sacarlo es más largo, a pesar de mis mejores esfuerzos para jugar al golf. (Menos complejo, IMO, pero más largo de todos modos).

De todos modos, 206 caracteres; las líneas nuevas son extraíbles excepto la primera.

#!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

Explicación:

  • Hay dos partes en los datos. Los primeros cuatro bytes ( "/264/202/317/0") representan 32 bits de código morse ( "--.-..-.-.-----.....--..--------") aunque solo se usan los primeros 26 bits. Esta es la "cadena de referencia".
  • El resto de la cadena de datos almacena la posición inicial y la longitud de las subcadenas de la cadena de referencia que representan cada carácter: un byte por carácter, en el orden (A, B, ... Z, 0, 1, ... 9 , ".", ",", "?"). Los valores se codifican como 23 * (longitud - 1) + pos, y el descodificador invierte eso. La última posición inicial es, por supuesto, 22.
  • Entonces el desempaquetado hace la mitad del trabajo de extraer los datos y la tercera línea (como se ve aquí) hace el resto, ahora tenemos un hash con $m{''a''} = ''.-''etc., así que todo lo que queda es hacer coincidir los caracteres de la entrada, búscalos en el hash, y formatee la salida, que hace la última línea ... con alguna ayuda del shebang, que le dice a perl que elimine la nueva línea en la entrada, ponga líneas de entrada $_, y cuando el código termine de ejecutarse, $_vuelva a escribir en la salida con nuevas líneas agregadas de nuevo.

Python 3 One Liner: 172 caracteres

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()))

(Codificando la tabla de traducción en puntos de código Unicode. Funciona bien, y se muestran aquí bien en mi prueba en mi máquina con Windows Vista.)

Editado para reducir hasta 184 caracteres eliminando algunos espacios innecesarios y corchetes (haciendo listas comps gen exps).

Editar nuevamente: se eliminaron más espacios que ni siquiera sabía que era posible antes de ver otras respuestas aquí, así que hasta 176.

Vuelva a editar hasta 172 (woo woo!) Usando '''' .join en vez de '''' .join y haciendo los espacios por separado. (¡duh!)


Aquí hay otro enfoque, basado en el trabajo de dmckee, que demuestra cuán legible es Python:

Pitón

244 caracteres

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))

Limitaciones

  • La secuencia de dmckee se perdió el carácter ''Y'', y yo era demasiado flojo para agregarlo. Creo que solo tendrías que cambiar el "??" parte, y agregue un "-" al final de la segunda cadena literal
  • no coloca ''/'' entre las palabras; de nuevo, flojo

Como las reglas requerían menos caracteres , no menos bytes , podía hacer que al menos una de mis tablas de búsqueda fuera más pequeña (a la mitad) si estaba dispuesto a salir de los caracteres ASCII imprimibles.

EDITAR: Si uso caracteres Unicode elegidos ingenuamente, pero los guardo en ASCII escapado en el archivo de origen, todavía es un poco más corto porque el decodificador es más simple:

Pitón

240 caracteres

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))

Creo que también hace que la intención del programa sea mucho más clara.

Si guardó esto como UTF-8, creo que el programa tendría 185 caracteres, por lo que es la solución de Python completa más corta y solo superada por Perl. :-)


Aquí hay una tercera forma completamente diferente de codificar el código morse:

Pitón

232 caracteres

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 puede encontrar una forma de asignar esto a un conjunto de caracteres imprimibles, puede guardar bastantes caracteres. Esta es probablemente mi solución más directa , aunque no sé si es la más fácil de leer.

Bien, ahora que he perdido manera demasiado tiempo en esto.


C, 533 caracteres

Tomé el consejo de algunos comentarios y cambié a stdin. Mató a otros 70 personajes más o menos.

#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); }