Перекладіть код Морзе на основі тривалості тону


36

Мета

Код Морзе часто представляють як звук. Давши потік бітів, який відображає, чи звук увімкнено чи вимкнено, перекладіть потік на літери та цифри та пробіли.

Міжнародний кодекс Морзе

Особливості

  • Потік бітів аналізується на основі довжини повторюваних бітів ON / OFF.
    • 1 біт ON - крапка
    • 3 біта ON - тире
    • 1 біт OFF відмежовує точки і тире
    • 3 біта OFF обмежує символи
    • 7 біт OFF розмежовує слова (пробіл)
  • Вхід може представляти собою рядок або масив. Лише два унікальних символи / значення на ваш вибір дозволені. (напр., 0/1, правда / хибність, кома / пробіл)
  • Вихід повертає рядок або друкується на стандартний вихід.

Приклад

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

Припущення

  • Потік завжди починається і закінчується бітом ON.
  • Немає провідної чи задніх пробілів.
  • Вхід завжди дійсний.
  • Підтримуються всі літери (без регістру) та цифри.

Випробування

101010100010001011101010001011101010001110111011100000001011101110001110111011100010111010001011101010001110101
HELLO WORLD

10100000001011100011101110000000101110000000101011101000101000101010001010101
I AM A FISH

1010111011101110001110111011101110111000101110111011101110001110111010101
2017

101010001110111011100010101
SOS

Оцінка балів

Це код гольфу. Найнижчий код підрахунку байтів до цього часу виграє наступного тижня.


Чи може вихід мати пробіли пробілів?
Брайан Дж

Відповіді:


9

APL (Діалог) , 65 62 60 57 байт

-3 завдяки ngn.

Мовчазна префіксальна функція.

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

Спробуйте в Інтернеті! Заголовки f←та колонтитули - це лише те, щоб дозволити виклик функції з Input, зберігаючи кількість байтів TIO. У звичайному сеансі APL (що відповідає полі введення TIO) воно не знадобиться .

⎕CY'dfns'з оп у в dfns робочого простору (бібліотека)

(... ) застосовувати цю мовчазну функцію:
'1+|(00)+'⎕S 1 PCRE S нитка пошук 1-Ранов і навіть довжини 0-Ранов і довжини Матчі
6| розподіл залишок при діленні на 6
⊃∘'/. -'¨ для кожної довжини матчу, вибрати відповідний символ з цього рядка
'/|[-.]+'⎕S'&'∘ Pcre S нитка пошук косі і тире / точка -запускає та повертає
morse перекладений з коду Морзе до звичайного тексту


5
Нічого собі, ніколи не знав, що Дялог мав вбудований код для морзе.
Zacharý

@ Zacharý У dfns є багато, багато вбудованих.
Erik the Outgolfer

@ Zacharý Завжди перевіряйте dfns !
Adám

Ви посилаєтесь на старішу версію.
Ерік Аутгольфер

Функція BF ...> _ <, вау.
Zacharý

8

Python 2 , 142 135 байт

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

Спробуйте в Інтернеті!

Пояснення:

Розбиває рядок на літери на 000( 0таким чином, означає пробіл)

Замінює кожен 111на 3і перетворює в базу 16.

Потім кожне число модифікується символом 57, який дає діапазон 0..54, який є індексом поточного символу.


Попередня версія, перетворена на базу 3:

Python 2 , 273 252 247 байт

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

Спробуйте в Інтернеті!

Попередня версія, перетворена на двійкову:

Python 2 , 282 261 256 байт

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

Спробуйте в Інтернеті!


5

Рубін , 123 байти

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

Спробуйте в Інтернеті!

Розділіть рядок введення на межу символів. Використовуйте 3 або 4 біт OFF, щоб пробіли перетворилися на порожні рядки. Візьміть базове значення кожного символу та введіть у розумний діапазон (менше 60 можливих значень), використовуючи модуль на 3 послідовних поділах.


Дуже красиво зроблено.
Відновіть Моніку ямнотмайнар

2
Зауважу, впевнений, що він працює у всіх випадках, але якщо ви вилучите 0?з Regexp, він все ще працює для чотирьох тестових випадків.
Йорданія

4

Пітон , 175 168 байт

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

Спочатку перетворіть рядок у список рядка 0 (тире) / 1 (крапка), додайте префікс 1 (щоб запобігти веденню нулів і мати справу з пробілами), потім перетворіть у двійковий.

Оскільки кожен код має довжину не більше 5, результат коливається від 0 до 63 і може бути вказаний у рядку.


1
Я незалежно отримав в основному те саме рішення, але 169 байт: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'))
Алекс Варга

@AlexVarga Приємне використання Python 2 filter!
Колера Су


3

Visual Basic .NET (.NET Core) , 252 байти

-7 байт завдяки @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

Функція, яка приймає рядок 1s і 0s і повертає рядок. ( На насправді, тільки 0для OFFє жорсткою вимогою. Все , що ні OFFпередбачаєтьсяON ).

Буквальний рядок - це встановлення коду Морзе у вигляді двійкової купи у вигляді масиву. VB.NET дозволяє індексувати рядки як масиви символів. \Це ціле розподіл, з лівої суб купи для 1або правої суб купи для111 .

Я використовувався !як пробіл, коли в цій купі немає значення. Потрібно лише правильно зафіксувати показники.

VB.NET дозволяє повернутись, призначивши значення імені функції (у цьому випадку A). Я просто ітераційно роблю рядкові конкатенації ( &) для створення вихідного рядка. Перший раз, коли мені потрібно скористатися, &тому що використання +залишає провідну нульову таблицю, але я можу використовувати будь-який інший час +, який веде себе так само, як і &для рядків.

Спробуйте в Інтернеті!


1
Ви можете зберегти 7 байт, використовуючи "!ETIANMSURWDKGOHVF!L!PJBXCYZQ!!5473!!8290!!!!!16", а потім індексуючи за допомогою M(c-c\48*22), а потім можете зберегти ще 4, навіть не використовуючи M, а просто використовуючи рядковий рядковий рядок.
рекурсивна

@recursive Я розумію 4-байтний трюк, дякую за допомогу! У мене виникають проблеми з розумінням того, як ви змінюєте індекс. Якщо я заміню рядок буквальним, а потім використовую M(c-c\48*22), я отримую індекс поза межами випадку 2017. Я думаю, що VB зробить ділення та множення за тим же пріоритетом; я пропускаю дужки?
Брайан Дж

Ви маєте рацію щодо переваги. c\48*22буде 0або 22. Це спосіб умовного віднімання 22 від c, щоб Mскоротити, "склавши" кінець рядка. Якщо це не допоможе вам, ви завжди можете видалити паролі A &=(" ")ще з 2-х байт. :)
рекурсивна

І тоді ви можете змінити , &=щоб +=і видалити ще два пробілу.
рекурсивна

@recursive О, да! занадто багато зайвих парен. Проблема зі зміною на плюс полягає в тому, що я маю провідний нульовий символ на початку мого рядка. Можливо, це не велика справа.
Брайан Дж

3

JavaScript (ES6), 170 131 байт

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


Як це працює:

Якщо змінити крапки на 0, а тире на 1, а префікс на 1, ви отримаєте двійкові числа, які при перетворенні на десяткові дають вам:

  1. Літери: 2 - 18, 20 та 22 - 29.
    Їх можна перетворити на правильні літери шляхом індексації в ' ETIANMSURWDKGOHVF L PJBXCYZQ'.
  2. Числа: 32, 33, 35, 39, 47, 48, 56, 60, 62 і 63.
    Якщо взяти ці числа за модулем 11, отримаємо числа 0 - 8 і 10, які можна перетворити на правильні числа за індексація в '473168290 5'.

Програма розбивається на символи, потім перетворює кожен символ у крапки та тире, які перетворюються у відповідний вихід на основі вищезазначених правил.


Випробування:


3

Пітон 2 , 127 байт

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

Спробуйте в Інтернеті!

Побудова рішення TFeld шляхом видалення заміни та роботи в базі 10, ціною бітового xor та довшої опорної рядки.


2

PHP, 321 284 байт

Збережено 37 байт завдяки @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' ';}  

Попередня версія (321 байт)

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

Спробуйте в Інтернеті!

Негольована версія:

$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 байт

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

Спробуйте в Інтернеті!

  • 3 байти збережено завдяки @Jeutnarg.

1
Ви можете поголити декілька, використовуючи Long.toString (x [i], 2) замість Integer.toString (x [i], 2)
Jeutnarg

2

GNU sed , 261 + 1 = 262 байт

+1 байт для -rпрапора.

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

Спробуйте в Інтернеті!

Пояснення

Це дуже базове рішення таблиці пошуку.

Перші три рядки перетворюють вхід, таким чином, тире - _s, а точки - 1s. По-перше, 000s замінюються на ;, тому символи розділені ;і слова на;;0 . Потім 111s замінюються, _а всі залишилися 0s відкидаються, залишаючи 1s для крапок.

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

Наступний рядок додає таблицю пошуку. Він приймає форму, cmcmcm...де cє символ, і mце послідовність _s і 1s, що представляють його. iзамінюється1 в таблиці для розрізнення. Оскільки регулярні вирази у sed завжди жадібні, таблиця сортується від найдовшого до найкоротшого коду (наприклад, 1_збігів A1_замість 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_/

Далі, в циклі, кожна послідовність _ s і 1s (і наступні ;) замінюється відповідним символом:

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

Нарешті, очищення: is замінюється на 1s, решта ;s - пробілами, а таблиця пошуку видаляється:

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


1

JavaScript (ES6), 104 102 101 99 байт

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

Тестові справи

Як?

Оскільки для перетворення з двійкових в десяткові байти витрат ми використовуємо хеш-функцію, яка працює безпосередньо на двійкові блоки, інтерпретовані в базі 10.

Приклад

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

Мені дуже подобається такий одноетапний підхід. Наскільки великий пошук ви виконали, щоб встановити ці 37 виходів у ідеальний хеш розміром 50 з достатньо короткою функцією?
jayprich

@jayprich Це було жорстоко. Це було майже рік тому, тому я не пам’ятаю, як саме. :) Цілком ймовірно, що я все випробувавn*p%m0%m1 для1p<10000, 1<м0<10000 і 1<м1<100.
Арнольд

1

Сітківка , 144 138 130 103 байт

T`d`@#
^|@@@

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

Спробуйте в Інтернеті! Посилання включає тестові випадки. Пояснення:

T`d`@#

Змініть двійкові цифри на інші символи, оскільки 0 і 1 є дійсними результатами.

^|@@@
 

Вставте пробіл перед кожним символом і два пробіли між словами.

 @?#
E

Припустимо, що всі персонажі - це Ес.

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

Перекладіть усі букви, припускаючи, що за ними буде крапка. Наприклад, якщо у нас є E, і ми бачимо другу крапку (ми спожили першу, коли ми вставили E), то вона перекладається на I. Для літер, за якими може легально слідувати лише тире, вони перекладаються з цим припущення, і тоді тире споживається наступним етапом. Інші листи видаляються (зберігаючиL витрати в байті).

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

Якщо виявиться, що за ними насправді пішов тире, то виправте помилки. Це також споживає тире, коли це передбачалося попереднім етапом. Обидва переклади повторюються, поки не будуть використані всі крапки та тире.


0

Perl 5 , 241 + 1 ( -p) = 242 байти

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

Спробуйте в Інтернеті!


0

PHP, 181 + 1 байт

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

Запустіть як трубу -nRабо спробуйте в Інтернеті .


0

ES6 , 268 байт

Використовує кодування ASCII після зіставлення з базового 36 подання морза в індексне положення. Не мій найкращий день гольфу, але це зайняло лише 15 хвилин.

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

Легше читати (якось):

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

Мова Вольфрама (Mathematica) , 288 байт

Думав про читання даних у вигляді двійкових файлів, але це важко пояснити. База 36 видалася гарним компромісним способом ефективного зберігання даних.

В якості введення бере рядок 0 і 1. Здійснює серію замін, починаючи з прогонів 7 нулів, потім прогонів 3, потім найдовших двійкових літер до найкоротших. Порядок заміни важливий.

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

Спробуйте в Інтернеті!


Зачекайте, у Mathematica немає вбудованого коду Морзе?
Zacharý

Ще ні! Я перевірив.
Келлі Лоудер

0

Perl 5 , 195 байт

194 байт код + 1 для -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

Мені не вдалося це працювати просто зі стандартною упакованою бінарною стрічкою, мені довелося уникнути вищих байтових символів, інакше я став би на 171, якщо хтось знає, що я пропустив, або чому це порушує це було б чудово !

Спробуйте в Інтернеті!

Пояснення

Двійкова рядок є packред список номерів , які відносяться до символів Морзе ( 101011101- 349для Fт.д.) , і це заархівувати з діапазонами A..Z,0..9і використовувати в якості пошуку. У s///вираженні замінити всі пробіги семи 0секунд з простором , а потім все пробіги цифр, розділені трьома 0з або межами слова \b, з їх відповідною кнопкою виклику з %hхеша.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.