Terjemahkan kode Morse berdasarkan durasi nada


36

Tujuan

Kode morse sering direpresentasikan sebagai suara. Diberi aliran bit yang mewakili apakah suara hidup atau mati, menerjemahkan aliran menjadi huruf dan angka dan spasi.

Kode Morse Internasional

Spesifik

  • Bit stream dianalisis berdasarkan pada panjang bit ON / OFF berulang.
    • 1 ON bit adalah sebuah titik
    • Bit 3 ON adalah tanda hubung
    • 1 OFF bit membatasi titik dan garis
    • 3 OFF bit membatasi karakter
    • 7 OFF bit membatasi kata-kata (spasi)
  • Input mungkin berupa string atau larik. Hanya dua karakter / nilai unik pilihan Anda yang diizinkan dalam input. (mis. 0/1, benar / salah, koma / spasi)
  • Output mengembalikan string atau dicetak ke output standar.

Contoh

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

Asumsi

  • Streaming selalu dimulai dan diakhiri dengan bit ON.
  • Tidak ada spasi putih terdepan atau tambahan.
  • Masukan selalu valid.
  • Semua huruf (tidak peka huruf besar-kecil) dan angka didukung.

Uji Kasus

101010100010001011101010001011101010001110111011100000001011101110001110111011100010111010001011101010001110101
HELLO WORLD

10100000001011100011101110000000101110000000101011101000101000101010001010101
I AM A FISH

1010111011101110001110111011101110111000101110111011101110001110111010101
2017

101010001110111011100010101
SOS

Mencetak gol

Ini kode golf. Kode byte-hitung terendah saat ini menang minggu depan.


Bisakah output memiliki spasi spasi tambahan?
Brian J

Jawaban:


9

APL (Dyalog) , 65 62 60 57 byte

-3 Terima kasih kepada ngn.

Fungsi awalan Tacit.

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

Cobalah online! Header,, f←dan Footer hanya untuk memungkinkan memanggil fungsi dari Input sambil mempertahankan jumlah byte TIO. Dalam sesi APL normal (sesuai dengan bidang Input TIO), itu tidak akan diperlukan .

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

(... ) menerapkan fungsi ini diam-diam:
'1+|(00)+'⎕S 1 PCRE S earch 1-berjalan dan bahkan panjang 0-berjalan dan panjang kembali pertandingan
6| sisa pembagian ketika dibagi dengan 6
⊃∘'/. -'¨ untuk setiap panjang pertandingan, memilih sesuai karakter dari string ini
'/|[-.]+'⎕S'&'∘ PCRE S earch garis miring dan dash / dot -mulai dan kembalikan yang
morse diterjemahkan dari kode Morse ke teks biasa


5
Wow, tidak pernah tahu Dyalog memiliki kode morse untuk builtin.
Zacharý

@ Zacharý Ada banyak, banyak bawaan di dfns.
Erik the Outgolfer

@ Zacharý Selalu periksa dfns !
Adám

Anda menautkan ke versi yang lebih lama.
Erik the Outgolfer

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

Cobalah online!

Penjelasan:

Pisahkan string menjadi huruf-huruf 000( 0artinya ruang)

Ganti masing 111- masing dengan 3, dan diubah menjadi basis 16.

Kemudian setiap angka dimodded oleh 57, yang memberikan kisaran 0..54, yang merupakan indeks dari karakter saat ini.


Versi sebelumnya yang dikonversi ke basis 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'))

Cobalah online!

Versi sebelumnya yang dikonversi menjadi biner:

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

Cobalah online!


5

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

Cobalah online!

Pisahkan string input pada batas karakter. Gunakan bit 3 atau 4 OFF sehingga spasi dikonversi ke string kosong. Ambil nilai basis 2 dari setiap karakter, dan bawa ke kisaran yang wajar (kurang dari 60 nilai yang mungkin) menggunakan modulo pada 3 divisi berturut-turut.


Dilakukan dengan sangat baik.
Pasang kembali Monica iamnotmaynard

2
Saya perhatikan yakin apakah itu bekerja untuk semua kasus, tetapi jika Anda menghapus 0?dari Regexp itu masih berfungsi untuk empat kasus uji.
Jordan

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

Pertama-tama ubah string menjadi daftar 0 (dash) / 1 (dot) string, tambahkan awalan 1 (untuk mencegah angka nol di depan dan berurusan dengan spasi putih), kemudian konversikan ke biner.

Karena setiap kode memiliki panjang tidak lebih dari 5, hasilnya berkisar dari 0 hingga 63 dan dapat dicantumkan dalam sebuah string.


1
Saya mandiri pada dasarnya mendapat solusi yang sama, tetapi 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 Penggunaan bagus Python 2 filter!
Colera Su


3

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

-7 byte terima kasih kepada @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

Fungsi yang mengambil string 1s dan 0s, dan mengembalikan string. (Sebenarnya, hanya 0untuk yang OFFmerupakan persyaratan sulit. Apa pun tidak OFFdianggap sebagai ON).

Literal string adalah pengaturan kode Morse sebagai tumpukan biner dalam bentuk array. VB.NET memungkinkan Anda mengindeks string sebagai array karakter. The \integer divisi, mengambil sub tumpukan kiri untuk 1atau sub tumpukan tepat untuk111 .

Saya digunakan !sebagai kosong ketika tidak ada nilai di tumpukan tempat itu. Itu hanya perlu untuk pad keluar indeks dengan benar.

VB.NET memungkinkan Anda kembali dengan memberikan nilai ke nama fungsi (dalam hal ini, A ). Saya hanya iteratif melakukan penggabungan string ( &) untuk membangun string keluaran. Pertama kali saya perlu menggunakan &karena menggunakan +meninggalkan null char terkemuka, tetapi setiap saat saya bisa menggunakan +, yang berperilaku sama seperti &untuk string.

Cobalah online!


1
Anda dapat menyimpan 7 byte dengan menggunakan "!ETIANMSURWDKGOHVF!L!PJBXCYZQ!!5473!!8290!!!!!16", dan kemudian mengindeks menggunakan M(c-c\48*22), dan kemudian Anda dapat menyimpan 4 byte lainnya bahkan dengan tidak menggunakan M, tetapi hanya menggunakan inline string literal.
rekursif

@recursive Saya mengerti trik 4 byte, terima kasih atas bantuannya! Saya mengalami kesulitan memahami cara Anda mengubah indeks. Jika saya mengganti string literal, dan kemudian menggunakan M(c-c\48*22), saya mendapatkan indeks di luar batas pada kasus 2017. Saya pikir VB akan melakukan pembagian dan perkalian pada saat yang sama; Apakah saya kehilangan tanda kurung?
Brian J

Anda benar tentang prioritas. c\48*22akan menjadi 0atau 22. Ini adalah cara mengurangi 22 dari kondisi c, untuk membuat Mlebih pendek dengan "melipat" ujung tali. Jika itu tidak berhasil untuk Anda, Anda selalu dapat menghapus paren dari A &=(" ")untuk 2 byte lainnya. :)
rekursif

Dan kemudian Anda dapat mengubah &=ke +=, dan menghapus dua spasi lainnya.
rekursif

@ Rekursif Oh, ya! terlalu banyak paren ekstra. Masalah dengan mengubah ke plus adalah kemudian saya memiliki karakter nol di awal string saya. Mungkin itu bukan masalah besar.
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``


Bagaimana itu bekerja:

Jika Anda mengubah titik ke 0s dan tanda hubung ke 1s, dan awalan dengan 1, Anda mendapatkan angka biner, yang ketika dikonversi ke desimal memberi Anda:

  1. Surat: 2 - 18, 20, dan 22 - 29.
    Ini dapat dikonversi ke huruf yang benar dengan mengindeks ke ' ETIANMSURWDKGOHVF L PJBXCYZQ'.
  2. Bilangan: 32, 33, 35, 39, 47, 48, 56, 60, 62, dan 63.
    Jika kita mengambil angka-angka ini modulus 11, kita mendapatkan angka 0 - 8 dan 10, yang dapat dikonversi ke angka yang benar dengan pengindeksan ke '473168290 5'.

Program terpecah pada karakter, kemudian mengubah setiap karakter menjadi titik dan garis, yang dikonversi menjadi output yang sesuai berdasarkan aturan di atas.


Kasus uji:


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

Cobalah online!

Membangun solusi TFeld dengan menghapus penggantian dan dengan bekerja di basis 10, dengan biaya bitor xor dan string referensi yang lebih panjang.


2

PHP, 321 284 byte

Disimpan 37 byte berkat @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 sebelumnya (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' ';}

Cobalah online!

Versi tidak disatukan:

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

Cobalah online!

  • 3 byte disimpan berkat @Jeutnarg.

1
dapat mencukur habis beberapa dengan menggunakan Long.toString (x [i], 2) alih-alih Integer.toString (x [i], 2)
Jeutnarg

2

GNU sed , 261 + 1 = 262 byte

+1 byte untuk -rbendera.

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

Cobalah online!

Penjelasan

Ini adalah solusi tabel pencarian yang sangat mendasar.

Tiga baris pertama mentransformasikan input sehingga tanda hubung adalah _s dan titik adalah 1s. Pertama, 000s diganti dengan ;, sehingga karakter dipisahkan oleh ;dan kata oleh ;;0. Kemudian 111s digantikan oleh _dan semua 0s yang tersisa dibuang, meninggalkan 1s untuk titik-titik.

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

Baris berikutnya menambahkan tabel pencarian. Dibutuhkan bentuk di cmcmcm...mana ckarakter dan madalah urutan _s dan 1s yang mewakilinya. idiganti 1dalam tabel untuk disambiguasi. Karena ekspresi reguler dalam sed selalu serakah, tabel diurutkan dari kode terpanjang ke kode terpendek (jadi mis1_ cocok A1_bukan 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_/

Selanjutnya, dalam satu lingkaran, setiap urutan _s dan1 s (dan selanjutnya ;) digantikan oleh karakter yang sesuai:

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

Akhirnya, pembersihan: is diganti dengan 1s, sisa ;s adalah spasi, dan tabel pencarian dihapus:

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

Uji kasus

Bagaimana?

Karena mengkonversi dari biner ke desimal biaya byte, kami menggunakan fungsi hash yang bekerja langsung pada blok biner yang ditafsirkan dalam basis 10.

Contoh

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

Saya sangat menyukai pendekatan satu langkah ini. Seberapa besar pencarian yang Anda lakukan agar sesuai dengan 37 output ini menjadi hash sempurna ukuran 50 dengan fungsi yang cukup pendek?
jayprich

@ Jayprich Ini sangat kasar. Itu hampir 1 tahun yang lalu, jadi saya tidak ingat persis bagaimana caranya. :) Kemungkinannya adalah bahwa saya mencoba semua n*p%m0%m1untuk1hal<10000, 1<m0<10000 dan 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##

Cobalah online! Tautan termasuk kasus uji. Penjelasan:

T`d`@#

Ubah digit biner ke karakter lain karena 0 dan 1 adalah output yang valid.

^|@@@
 

Masukkan spasi sebelum setiap karakter dan dua spasi di antara kata-kata.

 @?#
E

Asumsikan semua karakter adalah Es.

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

Terjemahkan semua huruf dengan asumsi bahwa mereka akan diikuti oleh titik. Misalnya, jika kita memiliki E, dan kita melihat titik kedua (kita mengkonsumsi yang pertama ketika kita memasukkan E) maka itu diterjemahkan menjadi I. Untuk huruf yang hanya dapat secara legal diikuti oleh tanda hubung, mereka diterjemahkan dengan asumsi, dan kemudian garis putus-putus dikonsumsi oleh tahap berikutnya. Surat-surat lain dihapus (menjaga Lbiaya byte).

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

Jika diketahui bahwa mereka benar-benar diikuti oleh tanda hubung, maka perbaiki kesalahan penerjemahan. Ini juga mengkonsumsi tanda hubung ketika diasumsikan oleh tahap sebelumnya. Kedua terjemahan diulang sampai semua titik dan garis terputus.


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

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

Jalankan sebagai pipa dengan -nRatau coba online .


0

ES6 , 268 byte

Menggunakan pengkodean ASCII setelah pemetaan dari representasi base36 dari morse ke posisi indeks. Bukan hari golf terbaik saya, tetapi hanya butuh sekitar 15 menit.

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

Lebih mudah dibaca (agak):

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

Bahasa Wolfram (Mathematica) , 288 byte

Memikirkan membaca data sebagai biner dari file tapi itu sulit dijelaskan. Basis 36 tampak seperti cara kompromi yang baik untuk menyimpan data secara efisien secara leksikal.

Mengambil string 0 dan 1 sebagai input. Apakah serangkaian penggantian, dimulai dengan berjalan dari 7 nol, kemudian berjalan dari 3, kemudian huruf biner terpanjang hingga yang terpendek. Urutan penggantian itu penting.

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

Cobalah online!


Tunggu, Mathematica tidak memiliki kode morse bawaan?
Zacharý

Belum! Saya sudah memeriksa.
Kelly Lowder

0

Perl 5 , 195 byte

194 byte kode +1 untuk -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

Saya tidak bisa mendapatkan ini bekerja hanya dengan string biner dikemas standar, saya harus melarikan diri dari byte byte yang lebih tinggi kalau tidak saya akan berada di 171, jika ada yang tahu apa yang saya lewatkan, atau mengapa melanggar itu akan menjadi besar !

Cobalah online!

Penjelasan

String biner adalah daftar packed angka yang berhubungan dengan karakter morse ( 101011101- 349untuk Fdll) dan ini di-zip dengan rentang A..Z,0..9dan digunakan sebagai pencarian. The s///ekspresi mengganti semua berjalan tujuh 0s dengan ruang dan kemudian semua berjalan digit, dipisahkan dengan tiga 0s atau batas kata \b, dengan kunci yang sesuai mereka dari %hhash.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.