トーン持続時間に基づいてモールス信号を変換します


36

ゴール

モールス信号はしばしば音として表されます。サウンドがオンかオフかを表すビットのストリームが与えられたら、ストリームを文字と数字とスペースに変換します。

国際モールス符号

仕様

  • ビットストリームは、ON / OFFビットの繰り返しの長さに基づいて分析されます。
    • 1 ONビットはドットです
    • 3 ONビットはダッシュです
    • 1 OFFビットはドットとダッシュを区切ります
    • 3 OFFビットは文字を区切ります
    • 7 OFFビットは単語(スペース)を区切ります
  • 入力は文字列または配列です。入力では、選択した2つの一意の文字/値のみが許可されます。(例:0/1、true / false、カンマ/スペース)
  • 出力は文字列を返すか、標準出力に出力されます。

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

得点

これはコードゴルフです。来週のこの時点までに最低のバイトカウントコードが勝ちます。


出力に末尾の空白を含めることができますか?
ブライアンJ

回答:


9

APL(Dyalog)65 62 60 57バイト

-3 ngnに感謝します。

暗黙のプレフィックス機能。

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

オンラインでお試しください!ヘッダーf←、、およびフッターは、TIOのバイトカウントを保持しながら入力から関数を呼び出すことを許可するためのものです。通常のAPLセッション(TIOの入力フィールドに対応)では、必要ありません

⎕CY'dfns'CのオペアンプY DFNSの作業領域(ライブラリ)

(... ) :この暗黙関数適用
'1+|(00)+'⎕S 1 PCRE S earchが1ランと偶数長0ランとリターンマッチ長さ
6| 6で割ったときに分割剰余を
⊃∘'/. -'¨ それぞれ一致長のために、この文字列から対応する文字を選択
'/|[-.]+'⎕S'&'∘ PCRE S earchがスラッシュとダッシュ/ドット-実行し、それら
morse をモールス信号から通常のテキストに翻訳して返します


5
うわー、Dyalogがモールス信号の組み込み機能を持っていることを知らなかった。
ザカリー

@Zacharýdfnsには多くの多くの組み込み関数があります。
エリックアウトゴルファー

@Zacharý常にdfnsをチェックしてください
アダム

古いバージョンにリンクしています。
エリックアウトゴルファー

BF関数...> _ <、すごい。
ザカリー

8

パイソン2142の 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'))

オンラインでお試しください!

説明:

文字列を文字に分割します0000したがって、スペースを意味します)

それぞれ1113で置き換え、基数16に変換します。

次に、各数値はによって修正され570..54現在の文字のインデックスであるの範囲を与えます。


ベース3に変換された以前のバージョン:

パイソン2273の 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'))

オンラインでお試しください!

バイナリに変換した以前のバージョン:

パイソン2282の 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ビットを使用します。すべての文字の基数2の値を取得し、3つの連続した除算でモジュロを使用して妥当な範囲(60未満の可能な値)にします。


とてもうまくできました。
モニカiamnotmaynardを

2
すべてのケースで機能するかどうかは確かですが0?、Regexpから削除しても4つのテストケースで機能します。
ヨルダン

4

Python175 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
コレラSu


3

Visual Basic .NET(.NET Core)、252バイト

@recursiveのおかげで-7バイト

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の文字列を受け取り、文字列を返す関数。(実際には、0for のみがOFF厳しい要件です。OFFはすべて想定されませんON)。

文字列リテラルは、配列形式のバイナリヒープとしてのモールス信号セットアップです。VB.NETでは、文字列を文字の配列としてインデックス付けできます。\以下のために左サブ・ヒープを取る、整数除算であります1か、のための右のサブ・ヒープを111

私は使った !そのヒープスポットに値がない場合の空白としてました。インデックスを適切に埋めるだけです。

VB.NETでは、関数名(この場合はA)に値を割り当てることで戻ることができます。&出力文字列を作成するために、文字列の連結()を繰り返し行います。最初に使用する必要があるのは&、使用+すると先頭にヌル文字が残るためですが、それ以外の場合+は、と同じように動作します&は文字列します。

オンラインでお試しください!


1
を使用して7バイトを節約し"!ETIANMSURWDKGOHVF!L!PJBXCYZQ!!5473!!8290!!!!!16"、次にを使用してインデックスを作成しM(c-c\48*22)、さらにを使用せずにMインラインで文字列リテラルを使用するだけで別の4 バイトを節約できます。
再帰的

@recursive助けてくれてありがとう、4バイトのトリックを理解しています!インデックスの変更方法を理解できません。文字列リテラルを置き換えてからを使用するM(c-c\48*22)と、2017年の場合、インデックスが範囲外になります。VBは同じ優先順位で除算と乗算を行うと思います。かっこがありませんか?
ブライアンJ

あなたは優先順位について正しいです。 またはのc\48*22いずれ0かになります22。文字列の末尾を「折り畳む」cことでM短くするために、条件付きで22から22を引く方法です。それがうまくいかない場合は、いつでもA &=(" ")別の2バイトの括弧を削除できます。:)
再帰的

次に、に変更&=して+=、さらに2つのスペースを削除できます。
再帰的

@再帰再帰ああ!余分な括弧が多すぎます。プラスに変更する際の問題は、文字列の先頭に先行ヌル文字があることです。たぶんそれは大したことではないでしょう。
ブライアンJ

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に変更すると、2進数が得られ、10進数に変換すると次のようになります。

  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

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

オンラインでお試しください!

ビット単位のxorと長い参照文字列を犠牲にして、replaceを削除し、ベース10で作業することにより、TFeldのソリューションを構築します。


2

PHP、321 284バイト

@ovsのおかげで37バイト節約

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

オンラインでお試しください!

  • @Jeutnargのおかげで3バイト節約されました。

1
Integer.toString(x [i]、2)の代わりにLong.toString(x [i]、2)を使用することにより、いくつかを削ることができます
Jeutnarg

2

GNU sed、261 + 1 = 262バイト

-rフラグ用に+1バイト。

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

オンラインでお試しください!

説明

これは非常に基本的なルックアップテーブルソリューションです。

最初の3行は入力を変換するため、ダッシュは_s、ドットは1sです。最初に、000sがに置き換えられる;ため、文字はとで区切られ;ます;;0。次に、111sはに置き換えられ_、残り0のsはすべて破棄され、1sはドットになります。

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

次の行は、ルックアップテーブルを追加します。それは形式を取り文字があるとの順序でsおよびそれを表す秒。明確化のために表の代わりに使用されます。sedの正規表現は常に貪欲であるため、テーブルは最長のコードから最短のコードに並べ替えられます(たとえば一致cmcmcm...cm_1i11_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および1 s(および後続の;)の対応する文字に置き換えられます。

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

最後に、クリーンアップ:isはsに置き換えられ1、残り;の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進数への変換にはバイト数がかかるため、ベース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これは総当たり攻撃でした。しかし、それはほぼ1年前だったので、どのように正確に覚えていない。:)チャンスは、私がすべてを試みたことn*p%m0%m1です1p<100001<m0<10000 そして 1<m1<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は有効な出力であるため、2進数を他の文字に変更します。

^|@@@
 

すべての文字の前にスペースを挿入し、単語間に2つのスペースを挿入します。

 @?#
E

すべての文字がEであると仮定します。

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

ドットが続くと仮定して、すべての文字を翻訳します。たとえば、Eがあり、2番目のドット(Eを挿入したときに最初のドットが消費された)が表示される場合、それはIに変換されます。そして、ダッシュは次の段階で消費されます。その他の文字は削除されます(保持Lコストは1バイトです)。

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

ES6、268バイト

モールスのbase36表現からインデックス位置へのマッピング後にASCIIエンコードを使用します。私の最高のゴルフの日ではありませんが、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

Wolfram言語(Mathematica)、288バイト

データをファイルからバイナリとして読み込むことについて考えましたが、説明が難しくなります。Base 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にはモールス信号が組み込まれていませんか?
ザカリー

未だに!私はチェックした。
ケリーロウダー

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のED(モールス文字に関連する番号のリスト101011101- 349のためFなど)、これは範囲を有する圧縮さでA..Z,0..9ルックアップとして使用されます。このs///式は、7 0のすべての実行をスペースで置き換え、次に3 0のすべての実行またはワード境界\bで区切られたすべての数字の実行を、%hハッシュからの対応するキーで置き換えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.