Traduci il codice Morse in base alla durata del tono


36

Obbiettivo

Il codice Morse è spesso rappresentato come suono. Dato un flusso di bit che rappresentano se il suono è attivato o disattivato, traduci il flusso in lettere, numeri e spazi.

Codice Morse Internazionale

specifiche

  • Il flusso di bit viene analizzato in base alla lunghezza dei bit ON / OFF ripetuti.
    • 1 bit ON è un punto
    • 3 bit ON sono un trattino
    • 1 bit OFF delimita punti e trattini
    • 3 bit OFF delimitano i caratteri
    • 7 bit OFF delimita le parole (spazio)
  • L'input può essere una stringa o un array. Nell'input sono consentiti solo due caratteri / valori unici di tua scelta. (es. 0/1, vero / falso, virgola / spazio)
  • L'output restituisce una stringa o viene stampato sull'output standard.

Esempio

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

ipotesi

  • Lo stream inizia e termina sempre con un bit ON.
  • Non esiste spazio bianco iniziale o finale.
  • L'input è sempre valido.
  • Sono supportate tutte le lettere (senza distinzione tra maiuscole e minuscole) e le cifre.

Casi test

101010100010001011101010001011101010001110111011100000001011101110001110111011100010111010001011101010001110101
HELLO WORLD

10100000001011100011101110000000101110000000101011101000101000101010001010101
I AM A FISH

1010111011101110001110111011101110111000101110111011101110001110111010101
2017

101010001110111011100010101
SOS

punteggio

Questo è il codice golf. Il codice di conteggio dei byte più basso di questa volta la prossima settimana vince.


L'output può contenere spazi vuoti finali?
Brian J,

Risposte:


9

APL (Dyalog) , 65 62 60 57 byte

-3 grazie a ngn.

Funzione prefisso tacita.

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

Provalo online! Intestazione, f←e Piè di pagina servono solo per consentire la chiamata della funzione da Input mantenendo il conteggio dei byte di TIO. In una normale sessione APL (corrispondente al campo di input di TIO), non sarebbe necessario .

⎕CY'dfns'c op y the dfns workspace (library)

(... ) applicare questa funzione tacito:
'1+|(00)+'⎕S 1 PCRE S earch 1-corre e persino lunghezza 0-corre e lunghezze abbinamento ritorno
6| divisione resto quando divisi per 6
⊃∘'/. -'¨  per ogni lunghezza partita, scegliere il carattere corrispondente a questa stringa
'/|[-.]+'⎕S'&'∘ PCRE S barre e precipitare earch / puntino -runs e restituisce quelli
morse tradotti dal codice Morse a testo normale


5
Wow, non ho mai saputo che Dyalog aveva un codice incorporato per il codice morse.
Zacharý,

@ Zacharý Ci sono molti, molti builtin nei dfns.
Erik the Outgolfer,

@ Zacharý Controlla sempre dfns !
Adám,

Stai collegando a una versione precedente.
Erik the Outgolfer,

Una funzione BF ...> _ <, wow.
Zacharý,

8

Python 2 , 142 135 byte

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

Provalo online!

Spiegazione:

Divide la stringa in lettere 000( 0quindi significa spazio)

Sostituisce ciascuno 111con 3e si converte in base 16.

Quindi ogni numero viene modificato da 57, che fornisce un intervallo di 0..54, che è l'indice del carattere corrente.


Versione precedente convertita in base 3:

Python 2 , 273 252 247 byte

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

Provalo online!

Versione precedente convertita in binario:

Python 2 , 282 261 256 byte

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

Provalo online!


5

Rubino , 123 byte

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

Provalo online!

Dividi la stringa di input sul limite di caratteri. Utilizzare 3 o 4 bit OFF in modo che gli spazi vengano convertiti in stringhe vuote. Prendi il valore base 2 di ogni personaggio e porta in un intervallo ragionevole (meno di 60 possibili valori) usando il modulo su 3 divisioni successive.



2
Sono sicuro che funzionerà per tutti i casi, ma se rimuovi 0?da Regexp funziona ancora per i quattro casi di test.
Giordania,

4

Python , 175 168 byte

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

Per prima cosa converti la stringa in un elenco di 0 (trattino) / 1 (punto) stringa, aggiungi un prefisso 1(per evitare zero iniziali e gestire spazi bianchi), quindi converti in binario.

Poiché ogni codice ha una lunghezza non superiore a 5, il risultato varia da 0 a 63 e può essere elencato in una stringa.


1
Praticamente ho ottenuto sostanzialmente la stessa soluzione, ma 169 byte: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 Simpatico utilizzo di Python 2 filter!
Colera il


3

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

-7 byte grazie 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 funzione che prende una stringa di 1s e 0s, e restituisce una stringa. (In realtà, solo il 0per OFFè un requisito difficile. Tutto ciò che non OFFsi presume sia ON).

Il valore letterale stringa è l'impostazione del codice Morse come un heap binario in forma di matrice. VB.NET ti consente di indicizzare le stringhe come matrici di caratteri. È \divisione intera, prendendo l'heap secondario sinistro per 1o l'heap secondario destro per111 .

Ho usato !come spazio per quando non c'è un valore in quel punto heap. È solo necessario riempire correttamente gli indici.

VB.NET ti consente di tornare assegnando un valore al nome della funzione (in questo caso, A). Faccio solo concatenazioni di stringhe ( &) per creare la stringa di output. La prima volta che devo usare &perché usare +lascia un carattere null iniziale, ma ogni altra volta che posso usare +, che si comporta come &per le stringhe.

Provalo online!


1
Puoi salvare 7 byte usando "!ETIANMSURWDKGOHVF!L!PJBXCYZQ!!5473!!8290!!!!!16", quindi indicizzando usando M(c-c\48*22), e quindi puoi salvarne altri 4 nemmeno usando M, ma semplicemente usando la stringa letterale in linea.
ricorsivo il

@recursive Capisco il trucco da 4 byte, grazie per l'aiuto! Ho difficoltà a capire come stai cambiando l'indice. Se sostituisco il valore letterale della stringa e quindi lo utilizzo M(c-c\48*22), ottengo l'indice fuori dai limiti del caso 2017. Penso che VB farà divisione e moltiplicazione con la stessa precedenza; mi manca una parentesi?
Brian J,

Hai ragione sulla precedenza. c\48*22sarà o 0o 22. È un modo per sottrarre condizionalmente 22 da c, per Maccorciare "piegando" la fine della stringa. Se ciò non funziona per te, puoi sempre rimuovere le parentesi da A &=(" ")per altri 2 byte. :)
ricorsivo il

E poi si può cambiare &=a +=, e rimuovere altri due spazi.
ricorsivo il

@recursive Oh, duh! troppi genitori extra. Il problema con il passaggio a più è che ho un carattere null iniziale all'inizio della mia stringa. Forse non è un grosso problema, però.
Brian J,

3

JavaScript (ES6), 170 131 byte

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


Come funziona:

Se cambi i punti in 0 e i trattini in 1 e il prefisso con 1, ottieni numeri binari che, convertiti in decimali, ti danno:

  1. Lettere: 2 - 18, 20 e 22 - 29.
    Queste possono essere convertite nelle lettere corrette indicizzandole in ' ETIANMSURWDKGOHVF L PJBXCYZQ'.
  2. Numeri: 32, 33, 35, 39, 47, 48, 56, 60, 62 e 63.
    Se prendiamo questi moduli modulo 11, otteniamo i numeri 0 - 8 e 10, che possono essere convertiti nei numeri corretti da indicizzazione in '473168290 5'.

Il programma si divide in caratteri, quindi converte ogni carattere in punti e trattini, che vengono convertiti nell'output appropriato in base alle regole precedenti.


Casi test:


3

Python 2 , 127 byte

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

Provalo online!

Costruendo la soluzione di TFeld rimuovendo la sostituzione e lavorando nella base 10, al costo di un xor bit a bit e di una stringa di riferimento più lunga.


2

PHP, 321 284 byte

37 byte salvati grazie 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' ';}  

Versione precedente (321 byte)

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

Provalo online!

Versione non golfata:

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

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

Provalo online!

  • 3 byte salvati grazie a @Jeutnarg.

1
puoi raderne alcuni usando Long.toString (x [i], 2) invece di Integer.toString (x [i], 2)
Jeutnarg

2

GNU sed , 261 + 1 = 262 byte

+1 byte per -rflag.

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

Provalo online!

Spiegazione

Questa è una soluzione di tabella di ricerca molto semplice.

Le prime tre righe trasformano l'input in modo che i trattini siano se _i punti siano 1s. Innanzitutto, 000s viene sostituito da ;, quindi i caratteri sono separati da ;e le parole da ;;0. Quindi le 111s vengono sostituite da _e tutte le rimanenti 0s vengono scartate, lasciando 1s per i punti.

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

La riga successiva aggiunge la tabella di ricerca. Prende la forma in cmcmcm...cui cè un personaggio ed mè la sequenza di se _e1 s che lo rappresenta. iviene sostituito 1nella tabella per chiarimento delle ambiguità. Poiché le espressioni regolari in sed sono sempre avide, la tabella viene ordinata dal codice più lungo a quello più breve (quindi ad esempio 1_corrispondenze A1_anziché 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_/

Successivamente, in un ciclo, ogni sequenza di _s e 1s (e il successivo ;) è sostituito dal carattere corrispondente:

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

Infine, cleanup: is vengono sostituiti con 1s, i rimanenti ;s sono spazi e la tabella di ricerca viene eliminata:

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


1

JavaScript (ES6), 104 102 101 99 byte

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

Casi test

Come?

Poiché convertiamo da byte binari a costi decimali, utilizziamo una funzione hash che funziona direttamente su blocchi binari interpretati in base 10.

Esempio

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

Mi piace molto questo approccio in un solo passaggio. Quanto è stata eseguita una ricerca per adattarsi a questi 37 output in un hash perfetto della dimensione 50 con una funzione abbastanza corta?
jayprich,

@jayprich Questo è stato forzato. Era quasi un anno fa, quindi non ricordo esattamente come. :) È probabile che io abbia provato tutto n*p%m0%m1per1p<10000, 1<m0<10000 e 1<m1<100.
Arnauld,

1

Retina , 144 138 130 103 byte

T`d`@#
^|@@@

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

Provalo online! Il link include casi di test. Spiegazione:

T`d`@#

Cambia le cifre binarie in altri caratteri perché 0 e 1 sono output validi.

^|@@@
 

Inserisci uno spazio prima di ogni carattere e due spazi tra le parole.

 @?#
E

Supponiamo che tutti i personaggi siano Es.

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

Traduci tutte le lettere assumendo che saranno seguite da un punto. Ad esempio, se abbiamo una E e vediamo un secondo punto (abbiamo consumato il primo quando abbiamo inserito la E), allora si traduce in un I. Per le lettere che possono essere legalmente seguite solo da un trattino, vengono tradotte con quello presupposto, e quindi il trattino viene consumato dalla fase successiva. Altre lettere vengono eliminate (mantenendoL costi un byte).

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

Se si scopre che in realtà sono stati seguiti da un trattino, quindi correggere le traduzioni errate. Questo consuma anche il trattino quando è stato assunto dalla fase precedente. Entrambe le traduzioni vengono ripetute fino a quando tutti i punti e i trattini non vengono consumati.


0

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

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

Provalo online!


0

PHP, 181 + 1 byte

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

Esegui come pipe -nRo provalo online .


0

ES6 , 268 byte

Utilizza la codifica ASCII dopo il mapping da una rappresentazione base36 del morse a una posizione di indice. Non è stata la mia migliore giornata di golf, ma ci sono voluti solo circa 15 minuti.

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

Più facile da leggere (kinda):

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

Wolfram Language (Mathematica) , 288 byte

Pensato di leggere i dati come binari da un file, ma diventa difficile da spiegare. Base 36 sembrava un buon modo di compromesso per archiviare i dati in modo efficiente in modo lessicale.

Accetta una stringa di 0 e 1 come input. Esegue una serie di sostituzioni, iniziando con le esecuzioni di 7 zeri, quindi con le esecuzioni di 3, quindi le lettere binarie più lunghe fino alla più breve. L'ordine di sostituzione è 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]]]&

Provalo online!


Aspetta, Mathematica non ha un codice Morse integrato?
Zacharý,

Non ancora! Ho controllato.
Kelly Lowder,

0

Perl 5 , 195 byte

194 byte codice + 1 per -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

Non riuscivo a farlo funzionare solo con una stringa binaria impacchettata standard, dovevo scappare dai caratteri a byte più alto, altrimenti sarei su 171, se qualcuno sa cosa mi sono perso o perché si sta rompendo sarebbe fantastico !

Provalo online!

Spiegazione

La stringa binaria è un elenco packed dei numeri che si riferiscono ai caratteri morse ( 101011101- 349per Fecc.) E questo è compresso con gli intervalli A..Z,0..9e usato come una ricerca. Le s///espressioni sostituiscono tutte le corse di sette 0secondi con lo spazio e quindi tutte le corse di cifre, separate da tre 0secondi o limiti di parola \b, con la loro chiave corrispondente %hdall'hash.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.