57

チャレンジ

文字数による最短のコード。アルファベット文字(大文字と小文字)、数字、コンマ、ピリオド、疑問符のみを使用して文字列を入力し、モールス信号で文字列の表現を返します。モールス信号の出力は、長いビープ音(AKA'dah')の場合はダッシュ( 、ASCII 0x2D)で構成され、短いビープ音(AKA' dit')の場合-はドット( 、ASCII 0x2E)で構成されます。.

各文字はスペース(' '、ASCII 0x20)で区切る必要があり、各単語はスラッシュ(/、ASCII 0x2F)で区切る必要があります。

モールス信号表:

代替テキストhttp://liranuna.com/junk/morse.gif

テストケース:

Input:
    Hello world

Output:
    .... . .-.. .-.. --- / .-- --- .-. .-.. -..

Input:
    Hello, Stackoverflow.

Output:
    .... . .-.. .-.. --- --..-- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- .-.-.-

コードカウントには、入力/出力(つまり、プログラム全体)が含まれます。

4

32 に答える 32

70

C (131 文字)

はい、13 1 !

main(c){for(;c=c?c:(c=toupper(getch())-32)?
"•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5"
[c-12]-34:-3;c/=2)putch(c/2?46-c%2:0);}

whileandforループのロジックを 1 つのループに結合し、変数forの宣言を入力パラメーターとして定義に移動することで、さらにいくつかの文字を探し出しました。この後者のテクニックは、ストレンジャーの別の課題への回答から借りました。cmain


GCC または ASCII のみのエディターでプログラムを検証しようとしている場合は、次の少し長いバージョンが必要になる場合があります。

main(c){for(;c=c?c:(c=toupper(getchar())-32)?c<0?1:
"\x95#\x8CKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5"
[c-12]-34:-3;c/=2)putchar(c/2?46-c%2:32);}

このバージョンは、次の変更により 17 文字長くなります (比較的大きな 148 文字)。

  • +4:ポータブルgetchar()putchar()ない代わりgetch()putch()
  • +6: 非 ASCII 文字の代わりに 2 つの文字のエスケープ コード
  • +1: 空白文字の場合は 0 ではなく 32
  • +6: c<0?1:ASCII 32 未満の文字 (つまり から'\n') からのガベージを抑制するために " " を追加しました。!"#$%&'()*+[\]^_`のいずれか{|}~、またはASCII 126を超えるものからは、引き続きガベージが取得されます。

これにより、コードは完全に移植可能になります。コンパイル:

gcc -std=c89 -funsigned-char morse.c

-std=c89オプションです。ただし、が必要です。-funsigned-charそうしないと、コンマとピリオドのゴミが表示されます。


135文字

c;main(){while(c=toupper(getch()))for(c=c-32?
"•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5"
[c-44]-34:-3;c;c/=2)putch(c/2?46-c%2:0);}

私の意見では、この最新バージョンは視覚的にもはるかに魅力的です。いいえ、移植性がなく、範囲外の入力に対して保護されなくなりました。また、UI がかなり悪く、1 文字ずつ入力してモールス符号に変換し、終了条件がありませんCtrl( +を押す必要がありますBreak)。しかし、優れた UI を備えた移植可能で堅牢なコードは必須ではありませんでした。

コードの可能な限り簡単な説明は次のとおりです。

main(c){
    while(c = toupper(getch())) /* well, *sort of* an exit condition */
        for(c =
            c - 32 ? // effectively: "if not space character"
            "•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5"[c - 44] - 34
            /* This array contains a binary representation of the Morse Code
             * for all characters between comma (ASCII 44) and capital Z.
             * The values are offset by 34 to make them all representable
             * without escape codes (as long as chars > 127 are allowed).
             * See explanation after code for encoding format.
             */
            : -3; /* if input char is space, c = -3
                   * this is chosen because -3 % 2 = -1 (and 46 - -1 = 47)
                   * and -3 / 2 / 2 = 0 (with integer truncation)
                   */
            c; /* continue loop while c != 0 */
            c /= 2) /* shift down to the next bit */
                putch(c / 2 ? /* this will be 0 if we're down to our guard bit */
                    46 - c % 2 /* We'll end up with 45 (-), 46 (.), or 47 (/).
                                * It's very convenient that the three characters
                                * we need for this exercise are all consecutive.
                                */
                    : 0 /* we're at the guard bit, output blank space */
                );
}

コード内の長い文字列の各文字には、1 つのテキスト文字のエンコードされたモールス符号が含まれています。エンコードされた文字の各ビットは、ダッシュまたはドットを表します。1 はダッシュを表し、0 はドットを表します。最下位ビットは、モールス符号の最初のダッシュまたはドットを表します。最後の「ガード」ビットは、コードの長さを決定します。つまり、エンコードされた各文字の最上位 1 ビットはコードの終わりを表し、出力されません。このガード ビットがないと、末尾にドットがある文字は正しく印刷されません。

たとえば、文字「L」は.-..モールス信号の「 」です。これを 2 進数で表すには、最下位ビット 0010 から始まる 0、1、およびさらに 2 つの 0 が必要です。ガード ビットにもう 1 つ追加すると、符号化されたモールス符号が得られます: 10010、または 10 進数18. +34 オフセットを追加して、文字「4」の ASCII 値である 52 を取得します。したがって、エンコードされた文字配列には、33 番目の文字 (インデックス 32) として「4」があります。

この手法は、ACoolie のstrager の(2)Miles のpingw33n のAlec の、およびAndrea のソリューションで文字をエンコードするために使用される手法と似ていますが、ビットごとに 2 つの演算 (シフト/除算) ではなく 1 つの演算 (シフト/除算) しか必要としないため、わずかに単純です。 /除算とデクリメント)。

編集:
残りの実装を読んでみると、 AlecAnonが私より前にガード ビットを使用してこのエンコード方式を思いついたことがわかります。Anon のソリューションは特に興味深いもので、Alec と私が行ったように、ループ、AND、シフトするのではなく、 Python のbin関数を使用し、"0b"プレフィックスとガード ビットをで取り除きます。[3:]

おまけとして、このバージョンでは、ハイフン ( -....-)、スラッシュ ( -..-.)、コロン ( ---...)、セミコロン ( -.-.-.)、等号 ( -...-)、およびアットマーク ( ) も処理され.--.-.ます。8 ビット文字が許可されている限り、これらの文字をサポートするために追加のコード バイトは必要ありません。このバージョンでは、コードに長さを追加しない限り、これ以上文字をサポートできません (大なり小なり記号用のモールス符号がない限り)。

古い実装も興味深いものであり、テキストにはこのバージョンに当てはまる注意事項があるため、この投稿の以前の内容を以下に残しました。


わかりました、おそらく、ユーザー インターフェイスは最悪ですよね?そのため、 stragerから借りて、gets()バッファリングされた、エコーされた行入力を提供する を、バッファリングされていない、エコーされていない文字入力を提供するに置き換えましgetch()た。これは、入力したすべての文字が画面上で即座にモールス符号に変換されることを意味します。たぶんそれはクールです。標準入力でもコマンドライン引数でも機能しなくなりましたが、非常に小さいです。

ただし、参照用に古いコードを以下に残しておきます。これが新しいものです。

新しいコード、境界チェック付き、171 文字:

W(i){i?W(--i/2),putch(46-i%2):0;}c;main(){while(c=toupper(getch())-13)
c=c-19?c>77|c<31?0:W("œ*~*hXPLJIYaeg*****u*.AC5+;79-@6=0/8?F31,2:4BDE"
[c-31]-42):putch(47),putch(0);}

Enterループを中断し、プログラムを終了します。

新しいコード、境界チェックなし、159 文字:

W(i){i?W(--i/2),putch(46-i%2):0;}c;main(){while(c=toupper(getch())-13)
c=c-19?W("œ*~*hXPLJIYaeg*****u*.AC5+;79-@6=0/8?F31,2:4BDE"[c-31]-42):
putch(47),putch(0);}

以下は、古い 196/177 コードに従い、いくつかの説明があります。

W(i){i?W(--i/2),putch(46-i%2):0;}main(){char*p,c,s[99];gets(s);
for(p=s;*p;)c=*p++,c=toupper(c),c=c-32?c>90|c<44?0:W(
"œ*~*hXPLJIYaeg*****u*.AC5+;79-@6=0/8?F31,2:4BDE"[c-44]-42):
putch(47),putch(0);}

これはAndrea's Python answerに基づいており、モールス信号を生成するためにその回答と同じ手法を使用しています。しかし、エンコード可能な文字を次々に格納してそのインデックスを見つける代わりに、インデックスを次々に格納して文字ごとに検索します (以前の回答と同様に)。これにより、以前の実装者に問題を引き起こした、終わり近くの長いギャップが回避されます。

と同じように、127 より大きい文字を使用しました。これを ASCII のみに変換すると、3 文字追加されます。長い文字列の最初の文字は に置き換える必要があります\x9C。今回はオフセットが必要です。それ以外の場合、多数の文字が 32 未満であり、エスケープ コードで表す必要があります。

また、以前と同様に、stdin の代わりにコマンドライン引数を処理すると 2 文字が追加され、コード間に実スペース文字を使用すると 1 文字が追加されます。

一方、ここにある他のルーチンのいくつかは、[ ,.0-9\?A-Za-z] の許容範囲外の入力を処理しません。このような処理がこのルーチンから削除された場合、19 文字が削除され、合計で 177 文字まで減少する可能性があります。しかし、これが行われ、このプログラムに無効な入力が与えられると、クラッシュして燃える可能性があります。

この場合のコードは次のようになります。

W(i){i?W(--i/2),putch(46-i%2):0;}main(){char*p,s[99];gets(s);
for(p=s;*p;p++)*p=*p-32?W(
"œ*~*hXPLJIYaeg*****u*.AC5+;79-@6=0/8?F31,2:4BDE"
[toupper(*p)-44]-42):putch(47),putch(0);}
于 2009-08-31T02:41:22.810 に答える
47

モールス信号フォントを使用していますか?

Console.Write(params[0]);
于 2009-08-29T23:01:07.007 に答える
23

Perl、170文字(熟練したゴルファーの助けを借りてmauke)。明確にするためにラップされています。すべての改行は削除可能です。

$_=uc<>;y,. ,|/,;s/./$& /g;@m{A..Z,0..9,qw(| , ?)}=
".-NINNN..]IN-NII..AMN-AI---.M-ANMAA.I.-].AIAA-NANMMIOMAOUMSMSAH.B.MSOIONARZMIZ"
=~/../g;1while s![]\w|,?]!$m{$&}!;print

説明:

  1. モールス信号辞書を抽出します。各記号は、文字通りのドットまたはダッシュ、あるいは別の定義された文字の値への参照のいずれかである2つの文字で定義されます。EとTには、デコーダーの非同期化を回避するためのダミー文字が含まれています。後で削除します。
  2. 入力を読み取り、フォーマットします。"Hello world"になります"H E L L O / W O R L D"
  3. 次のステップは、入力辞書と出力辞書が異なることに依存しているため、入力のドットを未使用の文字に変換します(垂直バー、|
  4. モールス信号辞書で発生する入力の文字を、置換が発生しなくなるまで辞書の値に置き換えます。
  5. 手順1で説明したダミー文字を削除します。
  6. 出力を印刷します。

最終バージョンでは、辞書は実行時の効率のために最適化されています。

  • すべての1シンボル文字(EおよびT)および2シンボル文字(A、I、M、およびN)は直接定義され、1回のパスでデコードされます。
  • すべての3シンボル文字は、2シンボル文字とリテラルシンボルで定義され、2つのパスでデコードされます。
  • すべての4シンボル文字は、2つの2シンボル文字で定義され、3つの置換を使用して2つのパスでデコードされます。
  • 5記号と6記号の文字(数字と句読点)は3つのパスでデコードされ、それぞれ4つまたは5つの置換が行われます。

ゴルフコードはループごとに1文字しか置き換えないため(コードの1文字を節約するために!)、ループの数は入力の長さの5倍(アルファベットのみを使用する場合は入力の長さの3倍)に制限されます。ただし、演​​算にaを追加するgと、s///ループの数は3つに制限されます(アルファベットのみを使用する場合は2つ)。

変換例:

Hello 123
H E L L O / 1 2 3
II .] AI AI M- / AO UM SM
.... . .-.. .-.. --- / .-M- .A-- I.--
.... . .-.. .-.. --- / .---- ..--- ...--
于 2009-08-29T23:25:43.400 に答える
16

Pythonリスト内包表記、159文字のワンライナー

for c in raw_input().upper():print c<","and"/"or bin(ord("•ƒwTaQIECBRZ^`šŒ#S#n|':<.$402&9/6)(18?,*%+3-;=>"[ord(c)-44])-34)[3:].translate(" "*47+"/.-"+" "*206),

P DaddyのC実装と同様のデータパッキングを使用しますが、ビットを逆の順序で格納せずbin()、算術ではなくデータを抽出するために使用します。スペースは不等式を使用して検出されることにも注意してください。「コンマ未満」のすべての文字をスペースと見なします。

Pythonforループ、改行を含む205文字

for a in raw_input().upper():
 q='_ETIANMSURWDKGOHVF_L_PJBXCYZQ__54_3___2__+____16=/_____7___8_90'.find(a);s=''
 while q>0:s='-.'[q%2]+s;q=~-q/2
 print['/','--..--','..--..','.-.-.-',''][' ,?.'.find(a)]+s,
于 2009-08-29T23:23:10.940 に答える
7

シンボルのコンパクトなコーディングをいじっていましたが、既に使用されている暗黙的なツリーよりも優れているかどうかわからないため、他の誰かが使用できる場合に備えて、ここでコーディングを提示します。

次の文字列を考えてみましょう。

 --..--..-.-.-..--...----.....-----.--/

これには、必要なすべてのシーケンスが部分文字列として含まれています。次のように、オフセットと長さでシンボルをコーディングできます。

       ET  RRRIIGGGJJJJ    
--..--..-.-.-..--...----.....-----.--/
          CCCC  DD WWW       00000
,,,,,,   AALLLL BBBB        11111
--..--..-.-.-..--...----.....-----.--/
  ??????  KKK  MMSSS       22222   
        FFFF  PPPP        33333
--..--..-.-.-..--...----.....-----.--/
        UUU XXXX         44444       
          NN  PPPP  OOO 55555
--..--..-.-.-..--...----.....-----.--/
               ZZZZ    66666
                      77777      YYYY
--..--..-.-.-..--...----.....-----.--/
       ......        88888 HHHH
                    99999 VVVV  QQQQ
--..--..-.-.-..--...----.....-----.--/

最後の文字 (「/」) で開始および終了するスペース (つまり、単語の境界) を使用します。良い方法を見つけたら、ぜひ使ってみてください。

もちろん、短いシンボルのほとんどには、いくつかの可能なコーディングがあります。


P Daddy は、このトリックの短いバージョンを見つけ(そして、ここで少なくとも冗長性の一部を見ることができます)、素敵な c 実装を行いました。Alec は、最初の (バグがあり不完全な) バージョンで Python の実装を行いました。Hobbs は、私がまったく理解できない非常にコンパクトな perl バージョンを作成しました。

于 2009-08-30T01:40:44.900 に答える
6

J、124 130 134文字

'.- /'{~;2,~&.>(]`(<&3:)@.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-@B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper

JがCに勝った!素晴らしい!

使用法:

   '.- /'{~;2,~&.>(]`(<&3:)@.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-@B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper 'Hello World'
.... . .-.. .-.. --- / .-- --- .-. .-.. -.. 

   '.- /'{~;2,~&.>(]`(<&3:)@.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-@B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper 'Hello, Stackoverflow.'
.... . .-.. .-.. --- .-.-.- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- --..-- 
于 2010-05-11T16:53:56.597 に答える
5

C#266文字

C#に変換された131文字のCソリューションは、266文字になります。

foreach(var i in Encoding.ASCII.GetBytes(args[0].ToUpper())){var c=(int)i;for(c=(c-32!=0)?Encoding.ASCII.GetBytes("•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5")[c-44]-34:-3;c!=0;c/=2)Console.Write(Encoding.ASCII.GetChars(new byte[]{(byte)((c/2!=0)?46-c%2:0)}));}

これは次のように読みやすくなります。

foreach (var i in Encoding.ASCII.GetBytes(args[0].ToUpper()))
{
    var c = (int)i;
    for (c = ((c - 32) != 0) ? Encoding.ASCII.GetBytes("•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&@/4)'18=,*%.:0;?5")[c - 44] - 34 : -3
        ; c != 0
        ; c /= 2)
        Console.Write(Encoding.ASCII.GetChars(new byte[] { (byte)((c / 2 != 0) ? 46 - c % 2 : 0) }));
}
于 2009-10-11T22:56:01.350 に答える
5

Python 3 ワンライナー: 172 文字

print(' '.join('/'if c==' 'else''.join('.'if x=='0'else'-'for x in bin(ord("ijÁĕÁÿïçãáàðøüþÁÁÁÁÁČÁÅ×ÚÌÂÒÎÐÄ×ÍÔÇÆÏÖÝÊÈÃÉÑËÙÛÜ"[ord(c)-44])-192)[3:])for c in input().upper()))

(変換テーブルを Unicode コード ポイントにエンコードします。正常に動作し、Windows Vista マシンでのテストでは正常に表示されます。)

いくつかの不要なスペースと括弧を削除して 184 文字に削減するように編集しました (リスト構成を gen exp にします)。

もう一度編集:ここで他の回答を見る前に、私が知らなかったより多くのスペースが削除されました-176まで。

''.join の代わりに ''.join を使用し、スペースを別々に使用して、172 (woo woo!) まで再度編集します。(当たり前!)

于 2009-08-31T01:49:44.990 に答える
5

Golfscript - 106 文字 - おかしな文字はありません :)

入力の末尾の改行はサポートされていないため、このようなものを使用してください

echo -n Hello, Stackoverflow| ../golfscript.rb morse.gs

' '/{{.32|"!etianmsurwdkgohvf!l!pjbxcyzq"?)"UsL?/'#! 08<>"@".,?0123456789"?=or
2base(;>{'.-'\=}%' '}%}%'/'*

文字は特殊なケースであり、小文字に変換され、バイナリ位置で並べられます。
他のすべては変換テーブルによって行われます

于 2009-11-09T21:40:37.097 に答える
4

パイソン

不完全なソリューションですが、誰かが完全なソリューションを作成できるかもしれません。数字や句読点を処理しませんが、重さはわずか 154 文字です。

def e(l):
 i='_etianmsurwdkgohvf_l_pjbxcyzq'.find(l.lower());v=''
 while i>0:v='-.'[i%2]+v;i=(i-1)/2;return v or '/'
def enc(s):return ' '.join(map(e,s))
于 2009-08-30T00:46:29.687 に答える
3

REBOL (118文字)

約10年前の実装

foreach c ask""[l: index? find" etinamsdrgukwohblzfcpövxäqüyj"c while[l >= 2][prin pick"-."odd? l l: l / 2]prin" "]

引用元: http://www.rebol.com/oneliners.html

(数字はありませんが、単語はダブルスペースで区切られているだけです:/ ...)

于 2010-02-02T01:04:09.250 に答える
3

F#、256 文字

let rec D i=if i=16 then" "else
 let x=int"U*:+F8c]uWjGbJ0-0Dnmd0BiC5?\4o`h7f>9[1E=pr_".[i]-32
 if x>43 then"-"+D(x-43)else"."+D x
let M(s:string)=s.ToUpper()|>Seq.fold(fun s c->s+match c with
|' '->"/ "|','->"--..-- "|'.'->".-.-.- "|_->D(int c-48))""

例えば

M("Hello, Stack.") |> printfn "%s"

収量

.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- .-.-.-

私のテクニックはこれまでのところユニークかもしれないと思います。アイデアは次のとおりです。

  • 私たちが望むもののほとんどをカバーする文字のASCII範囲があります(0..Z)
  • この範囲には 43 文字しかありません
  • したがって、1 ビット (ダッシュまたはドット) と「次の文字」を 86 文字の範囲でエンコードできます。
  • ascii(32-117) の範囲はすべて「印刷可能」であり、この 86 文字の範囲として使用できます
  • したがって、文字列リテラルはこれらの行に沿ってテーブルをエンコードします

もう少しありますが、それが要点です。カンマ、ピリオド、およびスペースは 0..Z の範囲にないため、「一致」によって特別に処理されます。範囲 0..Z (「;」など) の一部の「未使用」文字は、それ自体モールス「文字」ではない他のモールス変換のサフィックスとしてテーブルで使用されます。

于 2009-08-30T20:58:39.343 に答える
3

これは、VB.Net のコンソール アプリケーションとしての私の貢献です。

Module MorseCodeConverter

    Dim M() As String = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."}

    Sub Main()
        Dim I, O
        Dim a, b

        While True
            I = Console.ReadLine()
            O = ""

            For Each a In I
                b = AscW(UCase(a))
                If b > 64 And b < 91 Then
                    O &= M(b - 65) & " "
                ElseIf b > 47 And b < 58 Then
                    O &= M(b - 22) & " "
                ElseIf b = 46 Then
                    O &= ".-.-.- "
                ElseIf b = 44 Then
                    O &= "--..-- "
                ElseIf b = 63 Then
                    O &= "..--.. "
                Else
                    O &= "/"
                End If

            Next

            Console.WriteLine(O)
        End While


    End Sub

End Module

読みやすいように空白を残しました。合計 1100 文字。コマンド ラインから入力を 1 行ずつ読み取り、対応する出力を出力ストリームに送り返します。632 文字のみの圧縮バージョンを以下に示します。

Module Q
    Dim M() As String={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."}
    Sub Main()
        Dim I,O,a,b:While 1:I=Console.ReadLine():O="":For Each a In I:b=AscW(UCase(a)):If b>64 And b<91 Then:O &=M(b-65)&" ":ElseIf b>47 And b<58 Then:O &=M(b-22)&" ":ElseIf b=46 Then:O &=".-.-.- ":ElseIf b=44 Then:O &="--..-- ":ElseIf b=63 Then:O &= "..--.. ":Else:O &="/":End IF:Next:Console.WriteLine(O):End While
    End Sub
End Module
于 2009-08-30T02:28:20.610 に答える
3

C (248 文字)

別のツリーベースのソリューション。

#define O putchar
char z[99],*t=
" ETINAMSDRGUKWOHBL~FCPJVX~YZQ~~54~3~~~2~~+~~~~16=/~~.~~7,~~8~90";c,p,i=0;
main(){gets(z);while(c=z[i++]){c-46?c-44?c:O(45):O(c);c=c>96?c-32:c;p=-1;
while(t[++p]!=c);for(;p;p/=2){O(45+p--%2);}c-32?O(32):(O(47),O(c));}}

ウィキペディアが間違っているように見えるか、何かを誤解した可能性があるため、ソースツリーのエラーである可能性があります。

于 2009-08-30T03:03:58.963 に答える
2

C、338文字

338 をインデントし、すべての削除可能な改行を削除:

#define O putchar
#define W while
char*l="x@@@@@ppmmmmm@@FBdYcbcbSd[Kcd`\31(\b1g_<qCN:_'|\25D$W[QH0";
int c,b,o;
main(){
  W(1){
    W(c<32)
      c=getchar()&127;
    W(c>96)
      c^=32;
    c-=32;
    o=l[c/2]-64;
    b=203+(c&1?o>>3:0);
    o=c&1?o&7:o>>3;
    W(o>6)
      O(47),o=0;
    c/=2;
    W(c--)
      b+=(l[c]-64&7)+(l[c]-64>>3);
    b=(((l[b/7]<<7)+l[b/7+1])<<(b%7))>>14-o;
    W(o--)
      O(b&(1<<o)?46:45);
    O(32);
  }
}

これは、他の人が採用しているツリー アプローチに基づくものではありません。代わりに、l最初に 32 から 95 までのすべてのバイトの長さ (2 バイトを含む) を 1 文字にエンコードします。例として、長さ 3 の場合、D は -.. であり、E は です。これは 011 と 001 としてエンコードされ、011001 になります。さらに多くの文字をエンコード可能にし、エスケープを避けるために、64 が合計に追加され、1011001 - 89、ASCII Y になります。非モールス文字には長さが割り当てられます。の後半l( で始まる\031) は、ドットが 1 でダッシュが 0 のモールス符号自体のビットです。上位 ASCII になるのを避けるために、このデータは 7 ビット/バイトでエンコードされます。

コードは最初に をサニタイズし、次に(in )cのモールス長を計算し、それから前のすべての文字の長さを合計して、データのビット インデックスを生成します。cob

最後に、ビットをループし、ドットとダッシュを出力します。

長さ '7' は、スペースに遭遇したときに / を出力するための特別なフラグとして使用されます。

ブラケットを削除することで得られる小さな利益はおそらくいくつかありますが、私はいくつかのより良い結果からは程遠いものであり、お腹が空いているので...

于 2009-08-30T20:04:39.187 に答える
2

Perl、206 文字、dmckee のアイデアを使用

これは私が提出した最初のものよりも長いですが、それでも面白いと思います。および/またはひどい。まだ分​​からない。これは、dmckee のコーディングのアイデアと、私が見た他のいくつかの優れたアイデアを利用しています。最初は、「固定文字列の長さ/オフセット」のことは、1文字あたり固定の2バイト(およびすべての印刷可能なバイト)を使用する他のソリューションのスキームよりも少ないデータになるとは思いませんでした。実際、データをかなり少なくすることができました (1 文字あたり 1 バイトに加えて、インデックスを作成する 26 ビット パターンを格納するための 4 バイト)。それをゴルフする。(それほど複雑ではありませんが、IMOですが、とにかく長くなります)。

とにかく、206文字。改行は、最初の行を除いて削除できます。

#!perl -lp
($a,@b)=unpack"b32C*",
"\264\202\317\0\31SF1\2I.T\33N/G\27\308XE0=\x002V7HMRfermlkjihgx\207\205";
$a=~y/01/-./;@m{A..Z,0..9,qw(. , ?)}=map{substr$a,$_%23,1+$_/23}@b;
$_=join' ',map$m{uc$_}||"/",/./g

説明:

  • データには 2 つの部分があります。最初の 4 バイト ( "\264\202\317\0") はモールス信号 ( "--.-..-.-.-----.....--..--------") の 32 ビットを表しますが、最初の 26 ビットのみが使用されます。これが「参照文字列」です。
  • データ文字列の残りの部分には、各文字 (A、B、... Z、0、1、... 9 の順序で 1 文字あたり 1 バイト) を表す参照文字列の部分文字列の開始位置と長さが格納されます。 、「.」、「、」、「?」)。値は 23 * (長さ - 1) + pos としてコード化され、デコーダーはそれを逆にします。最後の開始位置はもちろん 22 です。
  • したがって、アンパックはデータを抽出する作業の半分を行い、3 行目 (ここで表示) が残りを$m{'a'} = '.-'行います。ハッシュ、および出力のフォーマット、最後の行が行う...シバンの助けを借りて、perlに入力の改行を削除し、入力の行を入れ$_、コードの実行が完了したら、出力に書き$_戻すように指示します改行が再び追加されます。
于 2009-08-31T08:18:31.347 に答える
2

Linq を使用した C# (133 文字)

    static void Main()
    {
        Console.WriteLine(String.Join(" ", (from c in Console.ReadLine().ToUpper().ToCharArray()
                                            select m[c]).ToArray()));
    }

OK、だましました。また、次のように辞書を定義する必要があります (文字数を数えることは気にしませんでした。これは私をゲームから吹き飛ばしてしまうからです)。

    static Dictionary<char, string> m = new Dictionary<char, string>() {
            {'A', ".-"},
            {'B', "-.."},
            {'C', "-.-."},
            {'D', "-.."},
            {'E', "."},
            {'F', "..-."},
            {'G', "--."},
            {'H', "...."},
            {'I', ".."},
            {'J', ".---"},
            {'K', "-.-"},
            {'L', ".-.."},
            {'M', "--"},
            {'N', "-."},
            {'O', "---"},
            {'P', ".--."},
            {'Q', "--.-"},
            {'R', ".-."},
            {'S', "..."},
            {'T', "-"},
            {'U', "..-"},
            {'V', "...-"},
            {'W', ".--"},
            {'X', "-..-"},
            {'Y', "-.--"},
            {'Z', "--.."},
            {'0', "-----"},
            {'1', ".----"},
            {'2', "..---"},
            {'3', "...--"},
            {'4', "....-"},
            {'5', "....."},
            {'6', "-...."},
            {'7', "--..."},
            {'8', "---.."},
            {'9', "----."},
            {' ', "/"},
            {'.', ".-.-.-"},
            {',', "--..--"},
            {'?', "..--.."},
        };

それでも、誰かがこれと同じくらい理解しやすく保守しやすい、より簡潔な C# 実装を提供できますか?

于 2009-08-31T04:37:53.773 に答える
2

Python (210 文字)

これは、 Alecのものに基づく完全なソリューションです。

def e(l):
 i=(' etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'%tuple('_'*5)).find(l.lower());v=''
 while i>0:v='-.'[i%2]+v;i=(i-1)/2
 return v or '/'
def enc(s):return ' '.join(map(e,s))
于 2009-08-30T13:43:02.677 に答える
2

パイソン 2; 171文字

基本的にアンドレアのソリューションと同じですが、完全なプログラムとして、愚かなトリックを使用して短くします。

for c in raw_input().lower():print"".join(".-"[int(d)]for d in bin(
('  etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'
%(('',)*5)).find(c))[3:])or'/',

(追加された改行はすべて削除できます)

または、bin()2.6 でこの関数を使用したくない場合は、176 でそれを行うことができます。

for c in raw_input():C=lambda q:q>0and C(~-q/2)+'-.'[q%2]or'';print C(
(' etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'%
(('',)*5)).find(c.lower()))or'/',

(繰り返しますが、追加された改行はすべて削除できます)

于 2009-08-30T03:02:03.897 に答える
1

モールス信号をエンコードする3番目の完全に異なる方法は次のとおりです。

Python

232文字

def d(c):
 o='';b=ord("Y_j_?><80 !#'/_____f_\x06\x11\x15\x05\x02\x15\t\x1c\x06\x1e\r\x12\x07\x05\x0f\x16\x1b\n\x08\x03\r\x18\x0e\x19\x01\x13"[ord(c.upper())-44])
 while b!=1:o+='.-'[b&1];b/=2
 return o
e=lambda s:' '.join(map(d,s))

これを印刷可能な文字のセットにマップする方法を理解できれば、かなりの数の文字を節約できます。これがおそらく私の最も直接的な解決策ですが、それが最も読みやすいかどうかはわかりません。

OK、今私はこれにあまりにも多くの時間を無駄にました。

于 2009-08-30T18:41:33.190 に答える
1

C89(293文字)

他のいくつかの答えに基づいています。

編集:木を縮めます(イェーイ)。

#define P putchar
char t['~']="~ETIANMSURWDKGOHVF~L~PJBXCYZQ~~54~3",o,q[9],Q=10;main(c){for(;Q;)t[
"&./7;=>KTr"[--Q]]="2167890?.,"[Q];while((c=getchar())>=0){c-=c<'{'&c>96?32:0;c-
10?c-32?0:P(47):P(10);for(o=1;o<'~';++o)if(t[o]==c){for(;o;o/=2)q[Q++]=45+(o--&1
);for(;Q;P(q[--Q]));break;}P(32);}}
于 2009-08-30T01:55:56.880 に答える
1

Bashは、私が少し前に書いたスクリプト (タイムスタンプは昨年のものです) で、1661 文字にもなります。本当に楽しいだけです:)

#!/bin/sh
txt=''
res=''
if [ "$1" == '' ]; then
    read -se txt
else
    txt="$1"
fi;
len=$(echo "$txt" | wc -c)
k=1
while [ "$k" -lt "$len" ]; do
    case "$(expr substr "$txt" $k 1 | tr '[:upper:]' '[:lower:]')" in
        'e')    res="$res"'.' ;;
        't')    res="$res"'-' ;;
        'i')    res="$res"'..' ;;
        'a')    res="$res"'.-' ;;
        'n')    res="$res"'-.' ;;
        'm')    res="$res"'--' ;;
        's')    res="$res"'...' ;;
        'u')    res="$res"'..-' ;;
        'r')    res="$res"'.-.' ;;
        'w')    res="$res"'.--' ;;
        'd')    res="$res"'-..' ;;
        'k')    res="$res"'-.-' ;;
        'g')    res="$res"'--.' ;;
        'o')    res="$res"'---' ;;
        'h')    res="$res"'....' ;;
        'v')    res="$res"'...-' ;;
        'f')    res="$res"'..-.' ;;
        'l')    res="$res"'.-..' ;;
        'p')    res="$res"'.--.' ;;
        'j')    res="$res"'.---' ;;
        'b')    res="$res"'-...' ;;
        'x')    res="$res"'-..-' ;;
        'c')    res="$res"'-.-.' ;;
        'y')    res="$res"'-.--' ;;
        'z')    res="$res"'--..' ;;
        'q')    res="$res"'--.-' ;;
        '5')    res="$res"'.....' ;;
        '4')    res="$res"'....-' ;;
        '3')    res="$res"'...--' ;;
        '2')    res="$res"'..---' ;;
        '1')    res="$res"'.----' ;;
        '6')    res="$res"'-....' ;;
        '7')    res="$res"'--...' ;;
        '8')    res="$res"'---..' ;;
        '9')    res="$res"'----.' ;;
        '0')    res="$res"'-----' ;;
    esac;
    [ ! "$(expr substr "$txt" $k 1)" == " " ] && [ ! "$(expr substr "$txt" $(($k+1)) 1)" == ' ' ] && res="$res"' '
    k=$(($k+1))
done;
echo "$res"
于 2010-03-20T13:54:45.307 に答える
1

ハスケル

type MorseCode = String

program :: String
program = "__5__4H___3VS__F___2 UI__L__+_ R__P___1JWAE"
     ++ "__6__=B__/_XD__C__YKN__7_Z__QG__8_ __9__0 OMT "

decode :: MorseCode -> String
decode = interpret program
    where
    interpret         = head . foldl exec []
    exec xs       '_' = undefined : xs
    exec (x:y:xs)  c  = branch    : xs
        where
        branch (' ':ds) = c : decode ds
        branch ('-':ds) = x ds
        branch ('.':ds) = y ds
        branch []       = [c]

たとえば、 をdecode "-- --- .-. ... . -.-. --- -.. ."返します"MORSE CODE"

このプログラムは、優れた記事Fun with Morse Codeからの抜粋です。

于 2009-09-03T11:38:46.317 に答える
1

これは、dmckee の研究に基づく別のアプローチであり、Python がいかに読みやすいかを示しています。

パイソン

244文字

def h(l):p=2*ord(l.upper())-88;a,n=map(ord,"AF__GF__]E\\E[EZEYEXEWEVEUETE__________CF__IBPDJDPBGAHDPC[DNBSDJCKDOBJBTCND`DKCQCHAHCZDSCLD??OD"[p:p+2]);return "--..--..-.-.-..--...----.....-----.-"[a-64:a+n-128]
def e(s):return ' '.join(map(h,s))

制限:

  • dmckee の文字列には「Y」文字がありませんでした。追加するのが面倒でした。「??」を変えるだけでいいと思います。部分、および 2 番目の文字列リテラルの末尾に「-」を追加します
  • 単語の間に「/」を入れません。再び、怠け者

ルールでは、最小バイト数ではなく最小文字数が求められていたため、印刷可能な ASCII 文字の外に出たい場合は、ルックアップ テーブルの少なくとも 1 つを (半分に) 小さくすることができます。

編集:単純に選択された Unicode 文字を使用し、ソース ファイルでエスケープされた ASCII のままにしておくと、デコーダが単純になるため、少し短くなります。

パイソン

240文字

def h(l):a,n=divmod(ord(u'\x06_7_\xd0\xc9\xc2\xbb\xb4\xad\xa6\x9f\x98\x91_____\x14_AtJr2<s\xc1d\x89IQdH\x8ff\xe4Pz9;\xba\x88X_f'[ord(l.upper())-44]),7);return "--..--..-.-.-..--...----.....-----.-"[a:a+n]
def e(s):return ' '.join(map(h,s))

また、プログラムの意図がより明確になると思います。

これを UTF-8 で保存した場合、プログラムは 185 文字にまで短縮され、完全な Python ソリューションの中で最も短くなり、Perl に次いで 2 番目になると思います。:-)

于 2009-08-30T06:16:30.560 に答える
1

PHP

以前の PHP エントリを少し効率的にするように変更しました。:)

$a=array(32=>"/",44=>"--..--",1,".-.-.-",48=>"-----",".----","..---","...--","....-",".....","-....","--...","---..","----.",63=>"..--..",1,".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..");
foreach(str_split(strtoupper("hello world?"))as$k=>$v){echo $a[ord($v)]." ";}

Komodo は 2 行で 380 文字と言います - 余分な行は読みやすくするためです。;D 配列に点在する 1 は、その後手動で配列位置にジャンプする代わりに、その配列位置にデータを入力することで 2 バイトを節約するためのものです。

最初と 2 番目を考えてみましょう。違いは明らかです。:)

array(20=>"data",22=>"more data";
array(20=>"data",1,"more data";

ただし、最終的な結果は、コンテンツをループするのではなく、配列の位置を使用する限り正確です。これは、このゴルフ コースでは行いません。

最終結果: 578 文字から 380 文字 (198 文字、または ~34.26% の節約) まで。

于 2009-09-14T09:46:02.413 に答える
0

phpで私ができる最善のことは、次のとおりです。615文字、値の配列ははるかに効率的に処理できると思いますが、指定せずに配列に数値ではなくアルファベットのキーを使用させる方法を見つけることができませんでした彼ら。

それでも、他の人が使用できるようにするため(「笑うための」は有効な使用法だと思います...):

$alphabet = array(' '=>"/",'a'=>".-",'b'=>"-...",'c'=>"-.-.",'d'=>"-..",'e'=>".",'f'=>"..-.",'g'=>"--.",'h'=>"....",'i'=>"..",'j'=>".---",'k'=>"-.-",'l'=>".-..",'m'=>"--",'n'=>"-.",'o'=>"---",'p'=>".--.",'q'=>"--.-",'r'=>".-.",'s'=>"...",'t'=>"-",'u'=>"..-",'v'=>"...-",'w'=>".--",'x'=>"-..-",'y'=>"-.--",'z'=>"--..",'0'=>"-----",'1'=>".----",'2'=>"..---",'3'=>"...--",'4'=>"....-",'5'=>".....",'6'=>"-....",'7'=>"--...",'8'=>"---..",'9'=>"----.",'.'=>".-.-.-",','=>"--..--",'?'=>"..--..");
$text = strtolower("hello world?");
$textArray = str_split($text);
foreach($textArray as $k=>$v) {echo $alphabet[$v] . " ";}

貼り付けたコードや文字数に開始/終了タグを含めていないことを念頭に置いてください。それが不正行為であるかどうかはわかりませんが、完全な開示の精神で言及されています。


Salarymanのコメントに応じて編集され、不要な変数' $textArray'を削除し、変数名を短縮して、次のようになりました(576文字)。

$a = array(' '=>"/",'a'=>".-",'b'=>"-...",'c'=>"-.-.",'d'=>"-..",'e'=>".",'f'=>"..-.",'g'=>"--.",'h'=>"....",'i'=>"..",'j'=>".---",'k'=>"-.-",'l'=>".-..",'m'=>"--",'n'=>"-.",'o'=>"---",'p'=>".--.",'q'=>"--.-",'r'=>".-.",'s'=>"...",'t'=>"-",'u'=>"..-",'v'=>"...-",'w'=>".--",'x'=>"-..-",'y'=>"-.--",'z'=>"--..",'0'=>"-----",'1'=>".----",'2'=>"..---",'3'=>"...--",'4'=>"....-",'5'=>".....",'6'=>"-....",'7'=>"--...",'8'=>"---..",'9'=>"----.",'.'=>".-.-.-",','=>"--..--",'?'=>"..--..");
$t=str_split(strtolower("hello world?"));
foreach($textArray as $k=>$v) {echo $a[$v] . " ";}
于 2009-08-30T01:51:40.473 に答える
0

VBA / VB6 (576文字)

注:明示的なオプションはありません

Function MC(S)
For I = 1 To Len(S): C = UCase(Mid(S, I, 1)): MC = MC & IIf(C = " ", "/", "") & IIf(InStr("AEFHIJLPRSUVW12345.?", C), ".", IIf(InStr("BCDGKMNOQTXYZ06789,", C), "-", "")) & IIf(InStr("BCDFHIKNSUVXY23456?", C), ".", IIf(InStr("AGJLMOPQRWZ01789,.", C), "-", "")) & IIf(InStr("BDGHLQRSVXZ34567,.", C), ".", IIf(InStr("CFJKOPUWY01289?", C), "-", "")) & IIf(InStr("CFHLPZ45678,", C), ".", IIf(InStr("JQVXY01239.?", C), "-", "")) & IIf(InStr("56789.?", C), ".", IIf(InStr("01234,", C), "-", "")) & IIf(C = "?", ".", IIf(InStr(".,", C), "-", "")) & " ": Next
End Function
于 2009-09-25T20:18:00.773 に答える
0

C(381文字)

char*p[36]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
main(){int c;while((c=tolower(getchar()))!=10)printf("%s ",c==46?".-.-.-":c==44?"--..--":c==63?"..--..":c==32?"/":*(p+(c-97)));}
于 2009-08-30T01:10:57.867 に答える
0

C、コマンドライン引数を使用した448バイト:

char*a[]={".-.-.-","--..--","..--..","/",".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."},*k=".,? ",*s,*p,x;main(int _,char**v){for(;s=*++v;putchar(10))for(;x=*s++;){p=strchr(k,x);printf("%s ",p?a[p-k]:isdigit(x)?a[x-18]:isalpha(x=toupper(x))?a[x-61]:0);}}

C、stdinを使用して416バイト:

char*a[]={".-.-.-","--..--","..--..","/",".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."},*k=".,? ",*p,x;main(){while((x=toupper(getchar()))-10){p=strchr(k,x);printf("%s ",p?a[p-k]:isdigit(x)?a[x-18]:isalpha(x)?a[x-61]:0);}}
于 2009-08-30T01:13:17.117 に答える
0

C、533文字

私はいくつかのコメントからアドバイスを受け、stdinに切り替えました。さらに70人のキャラクターを大まかに殺しました。

#include <stdio.h>
#include <ctype.h>
char *u[36] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
main(){
char*v;int x;char o;
do{
o = toupper(getc(stdin));v=0;if(o>=65&&o<=90)v=u[o-'A'];if(o>=48&&o<=57)v=u[o-'0'+26];if(o==46)v=".-.-.-";if(o==44)v="--..--";if(o==63)v="..--..";if(o==32)v="/";if(v)printf("%s ", v);} while (o != EOF);
}
于 2009-08-29T23:44:23.253 に答える
0

C89 (388 文字)

コンマ、フルストップ、およびクエリをまだ処理していないため、これは不完全です。

#define P putchar
char q[10],Q,tree[]=
"EISH54V 3UF    2ARL   + WP  J 1TNDB6=X/ KC  Y  MGZ7 Q  O 8  90";s2;e(x){q[Q++]
=x;}p(){for(;Q--;putchar(q[Q]));Q=0;}T(int x,char*t,int s){s2=s/2;return s?*t-x
?t[s2]-x?T(x,++t+s2,--s/2)?e(45):T(x,t,--s/2)?e(46):0:e(45):e(46):0;}main(c){
while((c=getchar())>=0){c-=c<123&&c>96?32:0;if(c==10)P(10);if(c==32)P(47);else
T(c,tree,sizeof(tree)),p();P(' ');}}

読みやすくするためにラップされています。必要な改行は 2 つだけです (1 つは #define 用、もう 1 つはスペースの可能性があります)。非標準文字をいくつか追加しましたが、7 ビット以外の文字は追加しませんでした。

于 2009-08-30T00:16:25.183 に答える