Przetłumacz kod Morse'a na podstawie czasu trwania tonu


36

Cel

Kod Morse'a jest często przedstawiany jako dźwięk. Biorąc pod uwagę strumień bitów, które reprezentują, czy dźwięk jest włączony, czy wyłączony, przetłumacz strumień na litery, cyfry i spacje.

Międzynarodowy kod Morse'a

Specyfika

  • Strumień bitów jest analizowany na podstawie długości powtarzających się bitów ON / OFF.
    • 1 bit ON to kropka
    • 3 bity ON to kreska
    • 1 OFF bit ogranicza kropki i kreski
    • 3 bity WYŁ ogranicza znaki
    • 7 bitów WYŁ ogranicza słowa (spację)
  • Dane wejściowe mogą być ciągiem lub tablicą. W danych wejściowych dozwolone są tylko dwa unikalne znaki / wartości. (np. 0/1, prawda / fałsz, przecinek / spacja)
  • Wyjście zwraca ciąg znaków lub jest drukowane na standardowe wyjście.

Przykład

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

Założenia

  • Strumień zawsze zaczyna się i kończy bitem ON.
  • Nie ma wiodących ani końcowych białych znaków.
  • Dane wejściowe są zawsze prawidłowe.
  • Obsługiwane są wszystkie litery (bez rozróżniania wielkości liter) i cyfry.

Przypadki testowe

101010100010001011101010001011101010001110111011100000001011101110001110111011100010111010001011101010001110101
HELLO WORLD

10100000001011100011101110000000101110000000101011101000101000101010001010101
I AM A FISH

1010111011101110001110111011101110111000101110111011101110001110111010101
2017

101010001110111011100010101
SOS

Punktacja

To jest kod golfowy. Wygrywa kod o najniższej liczbie bajtów do tego czasu w przyszłym tygodniu.


Czy dane wyjściowe mogą mieć końcowe białe znaki?
Brian J

Odpowiedzi:


9

APL (Dyalog) , 65 62 60 57 bajtów

-3 dzięki ngn.

Funkcja ukrytego przedrostka.

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

Wypróbuj online! Nagłówek f←i Stopka pozwalają tylko wywoływać funkcję z wejścia, zachowując liczbę bajtów TIO. W normalnej sesji APL (odpowiadającej polu wejściowemu TIO) nie byłoby to konieczne .

⎕CY'dfns'c op r z dfns pulpit (biblioteka)

() Zastosuj tę ukrytą funkcję:
'1+|(00)+'⎕S 1 PCRE S earch 1-run i parzystej-0-run i zwróć
6| resztę długości dopasowań dzieląc dzieląc przez 6
⊃∘'/. -'¨ dla każdej długości dopasowania, wybierz odpowiedni znak z tego łańcucha
'/|[-.]+'⎕S'&'∘ PCRE S ukośniki i myślnik / kropka - uruchamia i zwraca te
morse przetłumaczone z kodu Morse'a na zwykły tekst


5
Wow, nigdy nie wiedziałem, że Dyalog ma wbudowany kod Morse'a.
Zacharý

@ Zacharý Istnieje wiele, wiele wbudowanych plików w dfns.
Erik the Outgolfer

@ Zacharý Zawsze sprawdzaj dfns !
Adám

Linkujesz do starszej wersji.
Erik the Outgolfer,

Funkcja BF ...> _ <, wow.
Zacharý

8

Python 2 , 142 135 bajtów

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

Wypróbuj online!

Wyjaśnienie:

Dzieli ciąg na litery na 000(0 oznacza to spację)

Zastępuje każdy 111z3 i konwertuje na bazę 16.

Następnie każdą liczbę modyfikuje się 57, co daje zakres 0..54, który jest indeksem bieżącego znaku.


Poprzednia wersja przekonwertowana na bazę 3:

Python 2 , 273 252 247 bajtów

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

Wypróbuj online!

Poprzednia wersja przekonwertowana na binarną:

Python 2 , 282 261 256 bajtów

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

Wypróbuj online!


5

Rubin , 123 bajty

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

Wypróbuj online!

Podziel ciąg wejściowy według limitu znaków. Użyj 3 lub 4 bitów OFF, aby spacje były konwertowane na puste ciągi. Weź podstawową wartość 2 każdej postaci i sprowadź rozsądny zakres (mniej niż 60 możliwych wartości) za pomocą modulo na 3 kolejnych podziałach.


Bardzo ładnie wykonane.
Przywróć Monikę iamnotmaynard

2
Jestem pewien, że jeśli to działa dla wszystkich przypadków, ale jeśli usuniesz 0?z Regexp, nadal działa dla czterech przypadków testowych.
Jordan

4

Python , 175 168 bajtów

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

Najpierw przekonwertuj ciąg na listę ciągów 0 (myślnik) / 1 (kropka), dodaj prefiks 1 (aby zapobiec wiodącym zerom i radzić sobie z białymi spacjami), a następnie przekonwertuj na binarny.

Ponieważ każdy kod ma długość nie większą niż 5, wynik waha się od 0 do 63 i może być wymieniony w ciągu.


1
Niezależnie dostałem zasadniczo to samo rozwiązanie, ale 169 bajtów: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 Ładne użycie Pythona 2 filter!
Colera Su


3

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

-7 bajtów dzięki @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

Funkcja, która pobiera łańcuch 1s oraz 0s, i zwraca ciąg znaków. (W rzeczywistości, tylko 0for OFFjest trudnym wymaganiem. OFFZakłada się, że nic nie jestON ).

Dosłowny ciąg znaków to konfiguracja kodu Morse'a jako plik binarny w postaci tablicy. VB.NET pozwala indeksować ciągi znaków jako tablice znaków. Jest \to dzielenie liczb całkowitych, przyjmujące lewą stertę podrzędną dla 1lub prawą podstertę dla111 .

Użyłem !jako pustego, gdy nie ma wartości w tym miejscu sterty. Konieczne jest jedynie prawidłowe wypełnienie wskaźników.

VB.NET pozwala powrócić, przypisując wartość do nazwy funkcji (w tym przypadku A). Właśnie iteracyjnie wykonuję konkatenacje ciągów ( &), aby zbudować ciąg wyjściowy. Za pierwszym razem muszę użyć, &ponieważ użycie +pozostawia wiodący znak null, ale za każdym razem, gdy mogę użyć +, który zachowuje się tak samo jak w &przypadku łańcuchów.

Wypróbuj online!


1
Możesz zapisać 7 bajtów za pomocą "!ETIANMSURWDKGOHVF!L!PJBXCYZQ!!5473!!8290!!!!!16", a następnie za pomocą indeksowania M(c-c\48*22), a następnie możesz zapisać kolejne 4, nawet nie używając M, ale po prostu używając literału ciągu.
rekurencyjny

@recursive Rozumiem sztuczkę 4-bajtową, dziękuję za pomoc! Mam problem ze zrozumieniem sposobu zmiany indeksu. Jeśli zastąpię literał ciąg, a następnie użyję M(c-c\48*22), uzyskam indeks poza granicami przypadku 2017. Myślę, że VB dokonuje podziału i mnożenia z tym samym priorytetem; czy brakuje mi nawiasów?
Brian J

Masz rację co do pierwszeństwa. c\48*22będzie albo 0albo 22. Jest to sposób warunkowego odjęcia 22 c, aby Mskrócić, „składając” koniec sznurka. Jeśli to ci nie pomoże, zawsze możesz usunąć pareny z A &=(" ")kolejnych 2 bajtów. :)
rekurencyjny

A następnie można zmienić &=, aby +=i usunąć kolejne dwie przestrzenie.
rekurencyjny

@recursive Oh, duh! za dużo dodatkowych parens. Problem ze zmianą na plus polega na tym, że na początku mojego łańcucha mam wiodący znak zerowy. Może to nie jest wielka sprawa.
Brian J

3

JavaScript (ES6), 170 131 bajtów

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


Jak to działa:

Jeśli zmienisz kropki na 0, a myślniki na 1 i przedrostek z 1, otrzymasz liczby binarne, które po przeliczeniu na dziesiętne dają:

  1. Litery: 2 - 18, 20 i 22 - 29.
    Można je przekonwertować na prawidłowe litery, indeksując do ' ETIANMSURWDKGOHVF L PJBXCYZQ'.
  2. Liczby: 32, 33, 35, 39, 47, 48, 56, 60, 62 i 63.
    Jeśli weźmiemy te liczby moduł 11, otrzymamy liczby 0–8 i 10, które można przekonwertować na prawidłowe liczby za pomocą indeksowanie do '473168290 5'.

Program dzieli znaki, a następnie przekształca każdy znak w kropki i myślniki, które są konwertowane na odpowiednie dane wyjściowe zgodnie z powyższymi zasadami.


Przypadki testowe:


3

Python 2 , 127 bajtów

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

Wypróbuj online!

Budowanie off TFeld „s rozwiązania poprzez usunięcie zastąpić i pracując w bazie 10, kosztem a xor logiczną i dłuższy ciąg odniesienia.


2

PHP, 321 284 bajtów

Zaoszczędź 37 bajtów dzięki @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' ';}  

Poprzednia wersja (321 bajtów)

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

Wypróbuj online!

Wersja bez golfa:

$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 bajtów

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

Wypróbuj online!

  • 3 bajty zapisane dzięki @Jeutnarg.

1
można ogolić kilka przy użyciu Long.toString (x [i], 2) zamiast Integer.toString (x [i], 2)
Jeutnarg

2

GNU sed , 261 + 1 = 262 bajtów

+1 bajt dla -rflagi.

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

Wypróbuj online!

Wyjaśnienie

Jest to bardzo podstawowe rozwiązanie tabeli odnośników.

Pierwsze trzy linie przekształcają dane wejściowe, więc myślniki to _s, a kropki to 1s. Najpierw 000s są zastępowane przez ;, więc znaki są oddzielane przez, ;a słowa przez;;0 . Następnie 111s są zastępowane przez, _a wszystkie pozostałe 0s są odrzucane, pozostawiając 1s dla kropek.

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

Następna linia dołącza tabelę odnośników. Przybiera postać cmcmcm...gdzie cjest znakiem i mjest sekwencją _s i 1s reprezentującą go.ijest zastąpiony 1w tabeli w celu ujednoznacznienia. Ponieważ wyrażenia regularne w sed są zawsze zachłanne, tabela jest sortowana od najdłuższego do najkrótszego kodu (czyli np. 1_Dopasowania A1_zamiast 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_/

Następnie w pętli każda sekwencja _ si 1si (i kolejne ;) jest zastępowana odpowiednim znakiem:

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

Na koniec czyszczenie: is są zamieniane na 1s, pozostałe ;s są spacjami, a tabela odnośników jest usuwana:

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


1

JavaScript (ES6), 104 102 101 99 bajtów

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

Przypadki testowe

W jaki sposób?

Ponieważ konwertujemy z bajtów kosztów binarnych na dziesiętne, używamy funkcji skrótu, która działa bezpośrednio na blokach binarnych interpretowanych w bazie 10.

Przykład

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

Bardzo podoba mi się to jednoetapowe podejście. Jak duże przeprowadziłeś wyszukiwanie, aby dopasować te 37 wyników do idealnego skrótu o rozmiarze 50 z wystarczająco krótką funkcją?
jayprich

@jayprich To było brutalne. To było prawie rok temu, więc nie pamiętam dokładnie jak. :) Są szanse, że próbowałem wszystko n*p%m0%m1dla1p<10000, 1<m0<10000 i 1<m1<100.
Arnauld

1

Siatkówka , 144 138 130 103 bajtów

T`d`@#
^|@@@

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

Wypróbuj online! Link zawiera przypadki testowe. Wyjaśnienie:

T`d`@#

Zmień cyfry binarne na inne znaki, ponieważ 0 i 1 są prawidłowymi wyjściami.

^|@@@
 

Wstaw spację przed każdym znakiem i dwie spacje między słowami.

 @?#
E

Załóż, że wszystkie postacie to Es.

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

Przetłumacz wszystkie litery, zakładając, że po nich będzie kropka. Na przykład, jeśli mamy literę E i widzimy drugą kropkę (zużyliśmy pierwszą kropkę, gdy wstawiliśmy literę E), wówczas przekłada się ona na literę I. W przypadku liter, które mogą być prawnie poprzedzone myślnikiem, są one tłumaczone z tym założenie, a następnie kreska jest zużywana przez następny etap. Inne litery są usuwane (utrzymanie Lbajtu kosztów).

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

Jeśli okaże się, że po nich nastąpił kreska, napraw błędne tłumaczenia. To również zużywa kreskę, gdy została założona przez poprzedni etap. Oba tłumaczenia są powtarzane, aż wszystkie kropki i myślniki zostaną zużyte.


0

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

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

Wypróbuj online!


0

PHP, 181 + 1 bajtów

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

Uruchom jako potok z -nRlub spróbuj online .


0

ES6 , 268 bajtów

Wykorzystuje kodowanie ASCII po odwzorowaniu z podstawowej reprezentacji Morse'a na pozycję indeksu. Nie mój najlepszy dzień w golfa, ale zajęło to tylko około 15 minut.

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

Łatwiejszy do odczytania (trochę):

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 bajtów

Myślałem o wczytywaniu danych jako pliku binarnego z pliku, ale trudno to wyjaśnić. Baza 36 wydawała się dobrym kompromisowym sposobem na efektywne przechowywanie danych pod względem leksykalnym.

Pobiera na wejściu ciąg zer i jedynek. Wykonuje serię zamian, zaczynając od serii 7 zer, następnie serii 3, a następnie najdłuższych liter binarnych aż do najkrótszych. Ważna jest kolejność wymiany.

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]]]&

Wypróbuj online!


Zaraz, Mathematica nie ma wbudowanego kodu Morse'a?
Zacharý

Jeszcze nie! Sprawdziłem.
Kelly Lowder

0

Perl 5 , 195 bajtów

Kod 194 bajtów + 1 dla -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

Nie mogłem tego uruchomić ze standardowym spakowanym ciągiem binarnym, musiałem uciec od znaków o wyższych bajtach, w przeciwnym razie byłbym na 171, jeśli ktoś wie, co przegapiłem lub dlaczego łamanie to byłoby świetne !

Wypróbuj online!

Wyjaśnienie

Ciąg binarny to packzredagowana lista liczb odnoszących się do znaków Morse'a ( 101011101- 349dla Fitd.), Która jest spakowana zakresami A..Z,0..9i używana jako odnośnik. Do s///wyrażenia wymienić wszystkie serie siedmiu 0sekund z miejsca i wtedy wszystkie ciągami cyfr oddzielonych z trzech 0s lub granic słów \b, z ich odpowiedniego klucza z %hhash.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.