Traducir código Morse en función de la duración del tono

36

Gol

El código Morse a menudo se representa como sonido. Dado un flujo de bits que representan si el sonido está activado o desactivado, traduzca el flujo a letras, números y espacios.

Código Morse Internacional

Detalles específicos

  • El flujo de bits se analiza en función de la duración de la repetición de bits ON / OFF.
    • 1 bit ON es un punto
    • 3 bits ON son un guión
    • 1 bit OFF delimita puntos y guiones
    • 3 bits OFF delimitan caracteres
    • 7 bits OFF delimita palabras (espacio)
  • La entrada puede ser una cadena o matriz. Solo se permiten dos caracteres / valores únicos de su elección en la entrada. (ej. 0/1, verdadero / falso, coma / espacio)
  • La salida devuelve una cadena o se imprime en la salida estándar.

Ejemplo

Input:    101010100010001011101010001011101010001110111011100000001011101110001110111011100010111010001011101010001110101
Analysis: \--H--/   E   \---L---/   \---L---/   \----O----/\-- --/\---W---/   \----O----/   \--R--/   \---L---/   \--D--/
Output:   HELLO WORLD

Supuestos

  • La transmisión siempre comienza y termina con un bit ON.
  • No hay espacios en blanco iniciales o finales.
  • La entrada siempre es válida.
  • Todas las letras (sin distinción entre mayúsculas y minúsculas) y dígitos son compatibles.

Casos de prueba

101010100010001011101010001011101010001110111011100000001011101110001110111011100010111010001011101010001110101
HELLO WORLD

10100000001011100011101110000000101110000000101011101000101000101010001010101
I AM A FISH

1010111011101110001110111011101110111000101110111011101110001110111010101
2017

101010001110111011100010101
SOS

Tanteo

Este es el código de golf. El código de conteo de bytes más bajo para esta fecha la próxima semana gana.

Hand-E-Food
fuente
¿Puede la salida tener espacios en blanco al final?
Brian J

Respuestas:

9

APL (Dyalog) , 65 62 60 57 bytes

-3 gracias a ngn.

Función de prefijo tácito.

CY'dfns'
morse'/|[-.]+'S'&'∘(⊃∘'/. -'¨6|'1+|(00)+'S 1)

Pruébalo en línea! Encabezado, f←y Pie de página son solo para permitir llamar a la función desde Entrada mientras se retiene el recuento de bytes de TIO. En una sesión APL normal (correspondiente al campo de entrada de TIO), no sería necesario .

⎕CY'dfns'c op y el espacio de trabajo dfns (biblioteca)

() Aplique esta función tácita:
'1+|(00)+'⎕S 1 PCRE S earch 1-carreras y pares de longitud 0-carreras y devuelva el
6| resto de división de longitudes de partidos cuando se divide por 6
⊃∘'/. -'¨ para cada longitud de partido, elija el carácter correspondiente de esta cadena
'/|[-.]+'⎕S'&'∘ PCRE S earch slashes y dash / dot -ejecuta y devuelve los
morse traducidos del código Morse al texto normal

Adán
fuente
55
Wow, nunca supe que Dyalog tenía un código morse incorporado.
Zacharý
@ Zacharý Hay muchas, muchas incorporaciones en los dfns.
Erik the Outgolfer
@ Zacharý Siempre revise dfns !
Adám
Estás vinculando a una versión anterior.
Erik the Outgolfer
Una función BF ...> _ <, wow.
Zacharý
8

Python 2 , 142 135 bytes

lambda s:''.join(' E-T----Z-Q---RSWU--2FH-V980NIMA--1CBYX-6--GDOK534PLJ-7'[int('0'+l.replace('111','3'),16)%57]for l in s.split('000'))

Pruébalo en línea!

Explicación:

Divide la cadena en letras 000( 0significa espacio)

Reemplaza cada uno 111con 3y se convierte en base 16.

Luego, cada número es modificado por 57, lo que da un rango de 0..54, que es el índice del carácter actual.


Versión anterior que se convirtió a la base 3:

Python 2 , 273 252 247 bytes

lambda s:''.join(chr(dict(zip([0,242,161,134,125,122,121,202,229,238,241]+[2]*7+[5,67,70,22,1,43,25,40,4,53,23,49,8,7,26,52,77,16,13,2,14,41,17,68,71,76],[32]+range(48,91)))[int('0'+l.replace('111','2').replace('0',''),3)])for l in s.split('000'))

Pruébalo en línea!

Versión anterior que se convirtió a binario:

Python 2 , 282 261 256 bytes

lambda s:''.join(chr(dict(zip([0,489335,96119,22391,5495,1367,341,1877,7637,30581,122333]+[2]*7+[23,469,1885,117,1,349,477,85,5,6007,471,373,119,29,1911,1501,7639,93,21,7,87,343,375,1879,7543,1909],[32]+range(48,91)))[int('0'+l,2)])for l in s.split('000'))

Pruébalo en línea!

TFeld
fuente
5

Ruby , 123 bytes

->s{s.split(/0000?/).map{|r|r[0]?"YE9_0IZTO_BHKU58V_GR_SFA__1_4NP_60X_____C__D_ML7WQ3__2__J"[r.to_i(2)%253%132%74]:" "}*""}

Pruébalo en línea!

Divida la cadena de entrada en el límite de caracteres. Use 3 o 4 bits OFF para que los espacios se conviertan en cadenas vacías. Tome el valor base 2 de cada personaje y llévelo a un rango razonable (menos de 60 valores posibles) usando el módulo en 3 divisiones sucesivas.

GB
fuente
Muy bien hecho.
Restablecer Monica iamnotmaynard el
2
Estoy seguro de que funciona para todos los casos, pero si lo elimina 0?de Regexp, todavía funciona para los cuatro casos de prueba.
Jordan
4

Python , 175 168 bytes

s=lambda t,f=''.join:f('; TEMNAIOGKDWRUS;;QZYCXBJP;L;FVH09;8;;;7;;;;;;;61;;;;;;;2;;;3;45'[int('1'+f('0'if j[1:]else j for j in i.split('0')),2)]for i in t.split('000'))

Primero convierta la cadena en una lista de cadena 0 (guión) / 1 (punto), agregue un prefijo 1(para evitar ceros a la izquierda y trate con espacios en blanco), luego convierta a binario.

Como cada código tiene una longitud de no más de 5, el resultado varía de 0 a 63 y puede enumerarse en una cadena.

Colera Su
fuente
1
Independientemente obtuve básicamente la misma solución, pero 169 bytes:lambda s:''.join("_ TEMNAIOGKDWRUS__QZYCXBJP_L_FVH09_8___7_______61_______2___3_45"[int('1'+filter(int,l).replace('2','0'),2)]for l in s.replace('111','2').split('000'))
Alex Varga
@AlexVarga ¡Buen uso de Python 2 filter!
Colera Su
3

Gelatina , 67 62 bytes

ṣ0L€«2ḅ2“>.&" þ/7;=¥çı¿¢×ÆФ怌©¦Çß÷µ¬£®Ñ½ðȷñ‘iịØB;⁶¤
œṣ0ẋ3¤Ç€

Pruébalo en línea!

Erik el Outgolfer
fuente
Espera, ¿la numeración de enlaces se envuelve?
Zacharý
@ Zacharý Sí, los enlaces de línea tienen índices modulares.
Erik the Outgolfer
3

Visual Basic .NET (.NET Core) , 252 bytes

-7 bytes gracias a @recursive

Function A(i)
For Each w In i.Split({"0000000"},0)
For Each l In w.Split({"000"},0)
Dim c=0
For Each p In l.Split("0")
c=c*2+1+p.Length\2
Next
A &="!ETIANMSURWDKGOHVF!L!PJBXCYZQ!!54!3!!!2!!!!!!!16!!!!!!!7!!!8!90"(c)
Next
A+=" "
Next
End Function

Una función que toma una cadena de 1sy 0s, y devuelve una cadena. (En realidad, solo el 0para el OFFes un requisito difícil. Cualquier cosa que no OFFse suponga ON)

El literal de cadena es la configuración del código Morse como un montón binario en forma de matriz. VB.NET le permite indexar cadenas como matrices de caracteres. La \división es entera, tomando el subheap izquierdo para 1o el subheap derecho para 111.

Utilicé !como un espacio en blanco para cuando no hay un valor en ese lugar del montón. Solo es necesario rellenar correctamente los índices.

VB.NET le permite regresar asignando un valor al nombre de la función (en este caso, A). Solo hago iterativamente concatenaciones de cadenas ( &) para construir la cadena de salida. La primera vez que necesito usar &porque usar +deja un carácter nulo principal, pero en cualquier otro momento puedo usar +, que se comporta igual que &para las cadenas.

Pruébalo en línea!

Brian J
fuente
1
Puede guardar 7 bytes usando "!ETIANMSURWDKGOHVF!L!PJBXCYZQ!!5473!!8290!!!!!16", y luego indexando usando M(c-c\48*22), y luego puede guardar otros 4 ni siquiera usando M, sino simplemente usando la cadena literal en línea.
recursivo
@recursivo Entiendo el truco de 4 bytes, ¡gracias por la ayuda! Tengo problemas para entender la forma en que está cambiando el índice. Si reemplazo el literal de cadena y luego lo uso M(c-c\48*22), obtengo un índice fuera de los límites en el caso de 2017. Creo que VB hará división y multiplicación con la misma precedencia; me estoy perdiendo un paréntesis?
Brian J
Tienes razón sobre la precedencia. c\48*22será cualquiera 0o 22. Es una forma de restar condicionalmente 22 de c, para Macortar al "doblar" el final de la cadena. Si eso no funciona, siempre puede eliminar los parens de A &=(" ")otros 2 bytes. :)
recursivo
Y entonces usted puede cambiar &=a +=, y quitar otros dos espacios.
recursivo
@recursivo ¡Oh, duh! demasiados parens adicionales El problema con el cambio a más es que tengo un carácter nulo al comienzo de mi cadena. Quizás eso no sea gran cosa, sin embargo.
Brian J
3

JavaScript (ES6), 170 131 bytes

s=>s.split`000`.map(e=>'  ETIANMSURWDKGOHVF L PJBXCYZQ'[c=+`0b${1+e.replace(/0?(111|1)/g,d=>+(d>1))}`]||'473168290 5'[c%11]).join``


Cómo funciona:

Si cambia los puntos a 0s y los guiones a 1s, y el prefijo con un 1, obtendrá números binarios, que cuando se convierten a decimal le dan:

  1. Letras: 2 - 18, 20 y 22 - 29.
    Se pueden convertir a las letras correctas indexando en ' ETIANMSURWDKGOHVF L PJBXCYZQ'.
  2. Números: 32, 33, 35, 39, 47, 48, 56, 60, 62 y 63.
    Si tomamos estos números módulo 11, obtenemos los números 0 - 8 y 10, que se pueden convertir a los números correctos por indexación en'473168290 5' .

El programa se divide en caracteres, luego convierte cada carácter en puntos y guiones, que se convierten en la salida adecuada según las reglas anteriores.


Casos de prueba:

Rick Hitchcock
fuente
3

Python 2 , 127 bytes

lambda s:''.join("IVMB  T  K 9LZF 1HWO3 GUS4 8 7A  E QR 26   NJX    Y0P 5D  C"[(int('0'+l)^2162146)%59]for l in s.split('000'))

Pruébalo en línea!

Partiendo de la solución de TFeld eliminando el reemplazo y trabajando en la base 10, a costa de un xor bit a bit y una cadena de referencia más larga.

Joe
fuente
2

PHP, 321 284 bytes

Guardado 37 bytes gracias a @ovs

$a=array_flip([242,161,134,125,122,121,202,229,238,241,5,67,70,22,1,43,25,40,4,53,23,49,8,7,26,52,77,16,13,2,14,41,17,68,71,76]);foreach(split('0000000',$argv[1])as$w){foreach(split('000',$w)as$m){echo($v=$a[base_convert(str_replace([111,0],[2,],$m),3,10)])>9?chr($v+55):$v;}echo' ';}  

Versión anterior (321 bytes)

$a=array_flip([22222,12222,11222,11122,11112,11111,21111,22111,22211,22221,12,2111,2121,211,1,1121,221,1111,11,1222,212,1211,22,21,222,1221,2212,121,111,2,112,1112,122,2112,2122,2211]);foreach(split('0000000',$argv[1])as$w){foreach(split('000',$w)as$m){echo($v=$a[str_replace([111,0],[2,],$m)])>9?chr($v+55):$v;}echo' ';}

Pruébalo en línea!

Versión sin golf:

$a=array_flip(
// Building an array $a with every Morse letter representation (1=dot, 2=dash) and flip it
               [22222,12222,11222,11122,11112,
                // 01234
                11111,21111,22111,22211,22221,
                // 56789
                12,2111,2121,211,1,1121,221,
                // ABCDEFG
                1111,11,1222,212,1211,22,
                // HIJKLM
                21,222,1221,2212,121,111,2,
                // NOPQRST
                112,1112,122,2112,2122,2211]);
                // UVWXYZ
foreach (split('0000000', $argv[1]) as $w){
// for each word (separate with 7 consecutive zeroes)
    foreach (split('000',$w) as $m){
    // for each letter (separate with 3 consecutive zeroes)
        echo ($v = $a[str_replace([111,0],[2,],$m)]) > 9
        // Replace '111' with '2' and '0' with nothing and find $v, the corresponding entry in the array $a
            ? chr($v+55)
            // If > 9th element, then letter => echo the ASCII code equal to $v+55
            : $v;
            // Else echo $v
    }
    echo ' ';
    // Echo a space
}
roberto06
fuente
2

Java (OpenJDK 8) , 370 bytes

s->{String r="";for(String t:s.split("0000000")){for(String u:t.split("000"))for(int x[]={1,7,5,21,29,23,87,93,119,85,117,341,375,343,373,471,477,349,469,1877,1367,1909,1879,1501,1911,1885,7637,5495,7543,7639,6007,30581,22391,122333,96119,489335},i=x.length;i-->0;)if(u.equals(Long.toString(x[i],2)))r+="ETISNAURMHD5WVLKGFB64ZXPOC73YQJ82910".charAt(i);r+=" ";}return r;}

Pruébalo en línea!

  • 3 bytes guardados gracias a @Jeutnarg.
Olivier Grégoire
fuente
1
puede eliminar algunos utilizando Long.toString (x [i], 2) en lugar de Integer.toString (x [i], 2)
Jeutnarg
2

GNU sed , 261 + 1 = 262 bytes

+1 byte para -rbandera.

s/000/;/g
s/111/_/g
s/0//g
s/$/;:51111141111_3111__211___i1____6_11117__1118___119____10_____H1111V111_F11_1L1_11P1__1J1___B_111X_11_C_1_1Y_1__Z__11Q__1_S111U11_R1_1W1__D_11K_1_N__1G__1O___I11A1_M__E1T_/
:
s/([1_]+);(.*([^1_])\1)/\3\2/
t
y/i/1/
s/;/ /g
s/:.*//g

Pruébalo en línea!

Explicación

Esta es una solución de tabla de búsqueda muy básica.

Las primeras tres líneas transforman la entrada de modo que los guiones son _sy los puntos son 1s. Primero, los 000s se reemplazan por ;, por lo que los caracteres se separan por ;y las palabras por ;;0. Luego, las 111s se reemplazan por _y todas las 0s restantes se descartan, dejando 1s por puntos.

s/000/;/g
s/111/_/g
s/0//g

La siguiente línea agrega la tabla de búsqueda. Toma la forma cmcmcm...en que ces un carácter y mes la secuencia de _s y 1s representa. ise sustituye 1en la tabla por desambiguación. Como las expresiones regulares en sed son siempre codiciosas, la tabla se ordena del código más largo al más corto (por ejemplo, 1_coincidencias en A1_lugar de i1____).

s/$/;:51111141111_3111__211___i1____6_11117__1118___119____10_____H1111V111_F11_1L1_11P1__1J1___B_111X_11_C_1_1Y_1__Z__11Q__1_S111U11_R1_1W1__D_11K_1_N__1G__1O___I11A1_M__E1T_/

A continuación, en un bucle, cada secuencia de _sys 1(y la posterior ;) se reemplaza por el carácter correspondiente:

:
s/([1_]+);(.*([^1_])\1)/\3\2/
t

Finalmente, la limpieza: los is se reemplazan por 1s, los ;s restantes son espacios y se elimina la tabla de búsqueda:

y/i/1/
s/;/ /g
s/:.*//g
Jordán
fuente
1

Jalea , 67 bytes

ŒrḌṣ7ṣ€3ṣ€€1’H_4F€€ḅ3i@€€“ṗƙ⁶}zyȮẓŀȯ¦CFæ¢+ı(¥5ç1®¬ȷ4MÑÆ£Ç)×DGL‘ịØBK

Pruébalo en línea!

Hiperneutrino
fuente
1

JavaScript (ES6), 104 102 101 99 bytes

s=>s.split`000`.map(n=>" _T__9VEFO0K7MX_CGS__LU1RYIJ845__Z_B_D6QP_3__AHNW2"[n*1741%8360%51]).join``

Casos de prueba

¿Cómo?

Debido a que la conversión de binarios a bytes de costos decimales, utilizamos una función hash que funciona directamente en bloques binarios interpretados en la base 10.

Ejemplo

dot dash dot dot = 101110101
101110101 * 1741 = 176032685841
176032685841 % 8360 = 3081
3081 % 51 = 21

--> The 21st character in the lookup table is 'L' (0-indexed).
Arnauld
fuente
Me gusta mucho este enfoque de un solo paso. ¿Qué tan grande fue la búsqueda que realizó para ajustar estas 37 salidas en un hash perfecto de tamaño 50 con una función lo suficientemente corta?
jayprich
n*p%m0%m11pags<100001<metro0 0<100001<metro1<100
1

Retina , 144 138 130 103 bytes

T`d`@#
^|@@@

 @?#
E
{T`L#@`R6_BI_Z5S1C_GD8__\L\HNF3P__7_`\w@#
T`589B-INPRSZ#@`490XYKT2\OVAMJWUQ_`\w##

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

T`d`@#

Cambie los dígitos binarios a otros caracteres porque 0 y 1 son salidas válidas.

^|@@@
 

Inserte un espacio antes de cada carácter y dos espacios entre las palabras.

 @?#
E

Suponga que todos los personajes son Es.

{T`L#@`R6_BI_Z5S1C_GD8__\L\HNF3P__7_`\w@#

Traduzca todas las letras suponiendo que irán seguidas de un punto. Por ejemplo, si tenemos una E y vemos un segundo punto (consumimos el primero cuando insertamos la E), entonces se traduce en una I. Para las letras que solo pueden ser seguidas legalmente por un guión, se traducen con eso supuesto, y luego el guión se consume en la siguiente etapa. Se eliminan otras letras (manteniendo los Lcostos por byte).

T`589B-INPRSZ#@`490XYKT2\OVAMJWUQ_`\w##

Si resulta que, de hecho, fueron seguidos por un guión, arregle las traducciones erróneas. Esto también consume el guión cuando fue asumido por la etapa anterior. Ambas traducciones se repiten hasta que se consuman todos los puntos y guiones.

Neil
fuente
0

Perl 5 , 241 + 1 (-p ) = 242 bytes

%k=map{(23,469,1885,117,1,349,477,85,5,6007,471,373,119,29,1911,1501,7639,93,21,7,87,343,375,1879,7543,1909,489335,96119,22391,5495,1367,341,1877,7637,30581,122333)[$i++]=>$_}A..Z,0..9;map{$\.=$k{oct"0b$_"}for split/000/;$\.=$"}split/0{7}/}{

Pruébalo en línea!

Xcali
fuente
0

PHP, 181 + 1 bytes

foreach(explode(_,strtr($argn. 0,[1110=>1,10=>0,"0000"=>_A,"00"=>_]))as$t)echo$t<A?~$t[-5]?(10+substr_count($t,0)*(1-2*$t[-5]))%10:__ETIANMSURWDKGOHVF_L_PJBXCYZQ[bindec("1$t")]:" ";

Ejecutar como tubería -nRo probarlo en línea .

Titus
fuente
0

ES6 , 268 bytes

Utiliza codificación ASCII después de la asignación de una representación base36 del morse a una posición de índice. No es mi mejor día de golf, pero solo me llevó unos 15 minutos.

s=>s.split('00000').map(w=>String.fromCharCode.apply({},w.split('000').map(c=>"ahkn,225z,h9z,48n,11z,9h,1g5,5w5,nlh,2me5,,,,,,,,n,d1,1gd,39,1,9p,d9,2d,5,4mv,d3,ad,3b,t,1h3,15p,5w7,2l,l,7,2f,9j,af,1g7,1h1".split(',').indexOf(parseInt(c,2).toString(36))+48))).join(' ')

Más fácil de leer (un poco):

s=>
s
.split('00000')
.map(w=>
	String.fromCharCode.apply({},
		w.split('000')
			.map(c=>
				"ahkn,225z,h9z,48n,11z,9h,1g5,5w5,nlh,2me5,,,,,,,,n,d1,1gd,39,1,9p,d9,2d,5,4mv,d3,ad,3b,t,1h3,15p,5w7,2l,l,7,2f,9j,af,1g7,1h1"
				.split(',')
				.indexOf(
					parseInt(c,2).toString(36)
				)+48)
			)
	).join(' ')

binarymax
fuente
0

Wolfram Language (Mathematica) , 288 bytes

Pensé en leer los datos como binarios de un archivo, pero eso es difícil de explicar. Base 36 parecía una buena forma de compromiso para almacenar los datos de manera eficiente léxica.

Toma una cadena de 0 y 1 como entrada. Hace una serie de reemplazos, comenzando con las corridas de 7 ceros, luego las corridas de 3, luego las letras binarias más largas hasta las más cortas. El orden de reemplazo es importante.

StringReplace[#,Thread@Rule[Join[{"0000000","000"},#~FromDigits~36~IntegerString~2&/@StringSplit@"ahkn 2me5 225z nlh h9z 5w7 5w5 5tj 4mv 48n 1h3 1h1 1gd 1g7 1g5 15p 11z d9 d3 d1 af ad 9p 9j 9h 3b 39 2l 2f 2d t n l 7 5 1"],Insert[Characters@" 09182Q7YJ3OZCX6P4GKBWLFV5MDRUHNASTIE","",2]]]&

Pruébalo en línea!

Kelly Lowder
fuente
Espera, ¿Mathematica no tiene un código morse incorporado?
Zacharý
¡Aún no! Lo comprobé.
Kelly Lowder
0

Perl 5 , 195 bytes

Código de 194 bytes + 1 para -p.

%h=map{$_,(A..Z,0..9)[$i++]}unpack"S26I2S7I","\xd5]u]\xddUw\xd7uww\xdd\xd7]WWwWwuwwwwwWwWUU\xd5uw\xdd\xdd";s/0{7}/ /g;s/(\d+?)(000|\b)/$h{oct"0b$1"}/ge

No pude hacer que esto funcionara solo con una cadena binaria empaquetada estándar, tuve que escapar de los caracteres de byte superior, de lo contrario estaría en 171, si alguien sabe lo que me he perdido, o por qué se rompe eso sería genial !

Pruébalo en línea!

Explicación

La cadena binaria es una lista packed de los números que se relacionan con los caracteres morse ( 101011101- 349para Fetc.) y se comprime con los rangos A..Z,0..9y se usa como una búsqueda. Las s///expresiones reemplazan todas las corridas de siete 0s con espacio y luego todas las corridas de dígitos, separadas con tres 0so límites de palabras \b, con su clave correspondiente del %hhash.

Dom Hastings
fuente