Traduzir código Morse com base na duração do tom


36

Objetivo

O código Morse é frequentemente representado como som. Dado um fluxo de bits que representam se o som está ativado ou desativado, traduza o fluxo em letras, números e espaços.

Código Morse Internacional

Específicos

  • O fluxo de bits é analisado com base no comprimento dos bits ON / OFF repetidos.
    • 1 bit ON é um ponto
    • 3 bits ON são um traço
    • 1 bit OFF delimita pontos e traços
    • 3 bits OFF delimita caracteres
    • 7 bits OFF delimita palavras (espaço)
  • A entrada pode ser uma sequência ou matriz. Apenas dois caracteres / valores exclusivos de sua escolha são permitidos na entrada. (por exemplo, 0/1, verdadeiro / falso, vírgula / espaço)
  • A saída retorna uma sequência ou é impressa na saída padrão.

Exemplo

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

Suposições

  • O fluxo sempre inicia e termina com um bit ON.
  • Não há espaços em branco à esquerda ou à direita.
  • A entrada é sempre válida.
  • Todas as letras (sem distinção entre maiúsculas e minúsculas) e dígitos são suportados.

Casos de teste

101010100010001011101010001011101010001110111011100000001011101110001110111011100010111010001011101010001110101
HELLO WORLD

10100000001011100011101110000000101110000000101011101000101000101010001010101
I AM A FISH

1010111011101110001110111011101110111000101110111011101110001110111010101
2017

101010001110111011100010101
SOS

Pontuação

Isso é código de golfe. O código de contagem de bytes mais baixo a esta hora da próxima semana vence.


A saída pode ter espaço em branco à direita?
Brian J

Respostas:


9

APL (Dyalog) , 65 62 60 57 bytes

-3 graças a ngn.

Função de prefixo tácito.

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

Experimente online! Cabeçalho, f←e Rodapé são apenas para permitir a chamada da função de Entrada, mantendo a contagem de bytes do TIO. Em uma sessão normal de APL (correspondente ao campo de entrada do TIO), isso não seria necessário .

⎕CY'dfns'c op y os NDR espaço de trabalho (biblioteca)

() Aplique esta função tácita:
'1+|(00)+'⎕S 1 PCRE S pesquisa 1 séries e pares pares 0 e retorna o
6| restante da divisão dos comprimentos das partidas quando dividido por 6
⊃∘'/. -'¨ para cada duração da partida, escolha o caractere correspondente dessa string
'/|[-.]+'⎕S'&'∘ Barras de pesquisa PCRE S e traço / ponto -runs e retorna aqueles
morse traduzidos do código Morse para o texto normal


5
Uau, nunca soube que Dyalog tinha um código embutido para morse.
Zachary

@ Zacharý Existem muitos, muitos builtins nos dfns.
Erik the Outgolfer

@ Zacharý Sempre verifique dfns !
Adám 17/11/17

Você está vinculando a uma versão mais antiga.
Erik the Outgolfer

Uma função BF ...> _ <, uau.
Zachary

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

Experimente online!

Explicação:

Divide a sequência em letras 000( 0significa espaço)

Substitui cada um 111por 3e converte na base 16.

Cada número é modificado por 57, o que fornece um intervalo de 0..54, qual é o índice do caractere atual.


Versão anterior que foi convertida na 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'))

Experimente online!

Versão anterior que foi convertida em binário:

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

Experimente online!


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]:" "}*""}

Experimente online!

Divida a sequência de entrada no limite de caracteres. Use 3 ou 4 bits OFF para que os espaços sejam convertidos em cadeias vazias. Pegue o valor base 2 de cada personagem e leve a um intervalo razoável (menos de 60 valores possíveis) usando o módulo em 3 divisões sucessivas.



2
Tenho certeza de que funciona para todos os casos, mas se você remover 0?do Regexp, ele ainda funcionará para os quatro casos de teste.
Jordânia

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

Primeiro converta a string na lista de 0 (traço) / 1 (ponto), adicione um prefixo 1(para evitar zeros à esquerda e lidar com espaços em branco) e depois converta para binário.

Como todo código tem um comprimento não superior a 5, o resultado varia de 0 a 63 e pode ser listado em uma sequência.


1
Eu obtive independentemente basicamente a mesma solução, mas 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 Bom uso do Python 2 filter!
Colera Su


3

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

-7 bytes graças 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

Uma função que leva uma série de 1s e 0s, e retorna um string. (Na verdade, apenas o 0para o OFFé uma exigência difícil. Tudo o que não OFFé consideradoON ).

O literal da cadeia de caracteres é a configuração do código Morse como uma pilha binária no formato de matriz. O VB.NET permite indexar cadeias de caracteres como matrizes de caracteres. A \divisão é inteiro, levando a sub-pilha esquerda para 1ou a sub-pilha direita por111 .

Eu usei !como um espaço em branco para quando não há um valor nesse ponto de pilha. Só é necessário preencher adequadamente os índices.

O VB.NET permite retornar atribuindo um valor ao nome da função (nesse caso, A). Eu apenas iterativamente faço concatenações de strings ( &) para criar a string de saída. Na primeira vez em que preciso usar, o &uso de +deixa um caracter nulo inicial, mas em qualquer outro momento em que eu possa usar +, que se comporta da mesma forma que &para seqüências de caracteres.

Experimente online!


1
Você pode salvar 7 bytes usando "!ETIANMSURWDKGOHVF!L!PJBXCYZQ!!5473!!8290!!!!!16"e, em seguida, indexar usando M(c-c\48*22)e, em seguida, você pode salvar outros 4 nem usando M, mas apenas usando a string literal inline.
recursivo

@recursive Eu entendo o truque de 4 bytes, obrigado pela ajuda! Estou tendo problemas para entender como você está alterando o índice. Se eu substituir a string literal e depois utilizá-la M(c-c\48*22), obtenho o índice fora dos limites no caso de 2017. Eu acho que o VB fará divisão e multiplicação na mesma precedência; estou faltando parênteses?
Brian J

Você está certo sobre precedência. c\48*22será ou 0ou 22. É uma maneira de subtrair condicionalmente 22 de c, para Mencurtar "dobrando" o final da corda. Se isso não funcionar, você sempre pode remover os parênteses de A &=(" ")outros 2 bytes. :)
recursivo

E então você pode mudar &=para +=e remover outros dois espaços.
recursivo

@recursive Oh, duh! muitos parênteses extras. O problema com a alteração para mais é que eu tenho um caractere nulo inicial no início da minha string. Talvez isso não seja grande coisa, no entanto.
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``


Como funciona:

Se você alterar os pontos para 0s e os traços para 1s e o prefixo com 1, obterá números binários que, quando convertidos em decimal, fornecem:

  1. Letras: 2 - 18, 20 e 22 - 29.
    Elas podem ser convertidas nas letras corretas, indexando em ' ETIANMSURWDKGOHVF L PJBXCYZQ'.
  2. Números: 32, 33, 35, 39, 47, 48, 56, 60, 62 e 63.
    Se usarmos esses números no módulo 11, obtemos os números 0 - 8 e 10, que podem ser convertidos nos números corretos por indexação em'473168290 5' .

O programa divide-se em caracteres e converte cada caractere em pontos e traços, que são convertidos na saída apropriada com base nas regras acima.


Casos de teste:


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

Experimente online!

Desenvolvendo a solução do TFeld removendo a substituição e trabalhando na base 10, ao custo de um xor bit a bit e uma string de referência mais longa.


2

PHP, 321 284 bytes

Guardado 37 bytes graças 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' ';}  

Versão 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' ';}

Experimente online!

Versão não destruída:

$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
}

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

Experimente online!

  • 3 bytes salvos graças a @Jeutnarg.

1
pode raspar alguns usando Long.toString (x [i], 2) em vez de Integer.toString (x [i], 2) #
18767 Jeutnarg

2

GNU sed , 261 + 1 = 262 bytes

+1 byte para -rsinalizador.

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

Experimente online!

Explicação

Esta é uma solução de tabela de pesquisa muito básica.

As três primeiras linhas transformam a entrada para que os traços sejam se os _pontos sejam 1s. Primeiro, 000s são substituídos por ;, para que os caracteres sejam separados por ;e as palavras por ;;0. Então, 111s são substituídos por _e todos os 0s restantes são descartados, deixando 1s para pontos.

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

A próxima linha anexa a tabela de pesquisa. Ele assume a forma cmcmcm...onde cestá um caractere e mé a sequência de _s e 1s que o representam. ié substituído 1na tabela por desambiguação. Como as expressões regulares no sed são sempre gananciosas, a tabela é classificada do código mais longo ao mais curto (por exemplo, 1_corresponde ao A1_invés 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_/

Em seguida, num ciclo, cada sequência de _s e 1s (e a subsequente ;) é substituído pelo carácter correspondente:

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

Por fim, cleanup: is são substituídos por 1s, ;s restantes são espaços e a tabela de pesquisa é excluída:

y/i/1/
s/;/ /g
s/:.*//g


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 teste

Quão?

Como a conversão de bytes de custos binários para decimais, usamos uma função hash que funciona diretamente em blocos binários interpretados na base 10.

Exemplo

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

Eu gosto muito dessa abordagem de uma etapa. Qual o tamanho da pesquisa realizada para ajustar essas 37 saídas em um hash perfeito de tamanho 50 com uma função curta o suficiente?
Jayprich 27/09/19

@jayprich Isso foi brutalmente forçado. Foi há quase 1 ano atrás, então não me lembro exatamente como. :) As chances são de que eu tentei tudo n*p%m0%m1por1p<10000, 1<m0 0<10000 e 1<m1<100.
Arnauld

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

Experimente online! O link inclui casos de teste. Explicação:

T`d`@#

Altere os dígitos binários para outros caracteres, porque 0 e 1 são saídas válidas.

^|@@@
 

Insira um espaço antes de cada caractere e dois espaços entre as palavras.

 @?#
E

Suponha que todos os caracteres sejam Es.

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

Traduza todas as letras, assumindo que serão seguidas por um ponto. Por exemplo, se temos um E, e vemos um segundo ponto (consumimos o primeiro quando inserimos o E), ele se traduz em um I. Para letras que só podem ser seguidas legalmente por um traço, elas são traduzidas com esse suposição e, em seguida, o traço é consumido no próximo estágio. Outras letras são excluídas (mantendoL custos em um byte).

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

Se parecer que eles foram seguidos de fato, corrija os erros de tradução. Isso também consome o traço quando foi assumido no estágio anterior. Ambas as traduções são repetidas até que todos os pontos e traços sejam consumidos.


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}/}{

Experimente online!


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")]:" ";

Execute como pipe -nRou experimente online .


0

ES6 , 268 bytes

Usa a codificação ASCII após o mapeamento de uma representação base36 do morse para uma posição de índice. Não é o meu melhor dia de golfe, mas levou apenas 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(' ')

Mais fácil de ler (meio):

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


0

Língua Wolfram (Mathematica) , 288 bytes

Pensou em ler os dados como binários de um arquivo, mas isso fica difícil de explicar. A base 36 parecia uma boa maneira de comprometer o armazenamento eficiente dos dados de maneira lexical.

Toma uma sequência de 0 e 1 como entrada. Faz uma série de substituições, começando com 7 zeros, depois 3, e as letras binárias mais longas até as menores. A ordem de substituição é 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]]]&

Experimente online!


Espere, o Mathematica não tem um código morse embutido?
precisa

Ainda não! Eu chequei.
perfil completo de 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

Eu não conseguia fazer isso funcionar com apenas uma string binária padrão, eu tinha que escapar dos caracteres de bytes mais altos, caso contrário eu estaria no 171, se alguém sabe o que eu perdi ou por que está quebrando isso seria ótimo !

Experimente online!

Explicação

A string binária é uma lista packed dos números relacionados aos caracteres morse ( 101011101- 349para Fetc) e é compactada com os intervalos A..Z,0..9e usada como uma pesquisa. As s///expressões substituem todas as execuções de sete 0s por espaço e, em seguida, todas as execuções de dígitos, separadas por três 0s ou limites de palavras \b, pela chave correspondente do %hhash.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.