文字数による最短コード。アルファベット文字(大文字と小文字)、数字、コンマ、ピリオド、疑問符のみを使用して文字列を入力し、モールス符号で文字列の表現を返します。モールス信号出力はダッシュ(-
、ASCII 0x2D)は長いビープ音(別名「dah」)とドット(.
、ASCII 0x2E)、短いビープ音(別名 'dit')。
各文字はスペース(' '
、ASCII 0x20)、各単語はスラッシュ(/
、ASCII 0x2F)。
モールス符号表:
代替テキストhttp://liranuna.com/junk/morse.gif
Input:
Hello world
Output:
.... . .-.. .-.. --- / .-- --- .-. .-.. -..
Input:
Hello, Stackoverflow.
Output:
.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- .-.-.-
コード数には入出力(つまり、完全なプログラム)が含まれます。
はい、 131!
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);}
while
ループとfor
ループのロジックを1つのfor
ループに結合し、c
変数の宣言を入力パラメーターとしてmain
定義に移動することで、さらに数文字を取り出しました。私が借りたこの後者の手法は、- 別の課題に対するストレッジャーの回答 です。
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です)。
getchar()
とputchar()
の代わりにgetch()
とputch()
c<0?1:
」を追加して、ASCII 32未満の文字(つまり、'\n'
)からのガベージを抑制します。 !"#$%&'()*+[\]^_
`{|}~
のいずれか、またはASCII 126を超えると、まだガベージが発生します。これにより、コードが完全に移植可能になります。コンパイル:
gcc -std = c89 -funsigned-char morse.c
-std=c89
はオプションです。ただし、-funsigned-char
は必要です。そうしないと、カンマと完全なストップのためにガベージが発生します。
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があり、文字ごとの入力を取り、モールス符号に変換し、no終了条件を持っています(ヒットする必要があります) Ctrl+Break)。しかし、Nice 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」は「.-..
」です。これをバイナリで表すには、最下位ビットである0010から始まる0、1、および2つの0が必要です。ガードビットにさらに1を1つタックすると、エンコードされたモールス符号:10010、または10進数18. +34オフセットを追加して52を取得します。これは、文字「4」のASCII値です。したがって、エンコードされた文字配列は、33番目の文字(インデックス32)として「4」を持っています。
この手法は、 ACoolie's 、 strager's で文字をエンコードするために使用される手法に似ています。(2)、 Miles's 、 pingw33n's 、 Alec's 、および Andrea's ソリューションですが、少し単純で、ビットごとに1つの操作のみが必要です(シフト/除算)ではなく、2(シフト/除算およびデクリメント)。
編集:
残りの実装を読んでみると、 Alec と Anon が、ガードビットを使用してこのエンコード方式を思いついたことがわかりました。 Anonの解決策は特に興味深いもので、Pythonのbin
関数を使用して、"0b"
プレフィックスと[3:]
でガードビットを取り除いたものです。
おまけとして、このバージョンではハイフン(-....-
)、スラッシュ(-..-.
)、コロン(---...
)、セミコロン(-.-.-.
)、イコール(-...-
)、アットマーク(.--.-.
)も処理できます。 8ビット文字が許可されている限り、これらの文字をサポートするために追加のコードバイトは必要ありません。コードに長さを追加しない限り、このバージョンではこれ以上の文字をサポートできません(より大/より小記号のモールス符号がない限り)。
古い実装がまだ興味深いと思い、テキストにはこのバージョンに適用できるいくつかの警告があるので、この投稿の以前のコンテンツを以下に残しました。
たぶん、おそらく、ユーザーインターフェースは不便ですよね?したがって、 strager から借りて、バッファリングされたエコーされた行入力を提供するgets()
を、バッファリングされていない、エコーされていない文字入力を提供するgetch()
に置き換えました。つまり、入力したすべての文字が画面上のモールス符号にすぐに変換されます。多分それはクールです。 stdinとコマンドライン引数のどちらでも機能しなくなりますが、かなり小さくなっています。
ただし、参照用に以下の古いコードを保持しています。これが新しいです。
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 ループを中断し、プログラムを終了します。
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);}
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のPython answer に基づいており、モールス信号を生成するための手法と同じ手法を使用しています。しかし、エンコード可能な文字を次々に格納してインデックスを見つけるのではなく、インデックスを次々に格納して、文字で検索しました( 私の以前の回答 と同様)。これにより、初期の実装者に問題を引き起こしていた終わり近くの長いギャップを防ぎます。
before のように、127より大きい文字を使用しました。これをASCIIのみに変換すると、3文字追加されます。長い文字列の最初の文字は\x9C
で置き換える必要があります。今回はオフセットが必要です。それ以外の場合、多数の文字は32未満であり、エスケープコードでmustを表す必要があります。
また、以前と同様に、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);}
Console.Write(params[0]);
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
"Hello world"
は"H E L L O / W O R L D"
になります|
)に変えます。最終バージョンでは、辞書は実行時の効率のために最適化されています。
ゴルフされたコードはループごとに1文字しか置き換えないため(コードの1文字を節約するため)、ループの数は入力の長さの5倍(アルファベットのみが使用される場合は入力の長さの3倍)に制限されます。ただし、g
をs///
操作に追加することにより、ループの数は3つに制限されます(アルファベットのみが使用されている場合は2つ)。
Hello 123
H E L L O / 1 2 3
II .] AI AI M- / AO UM SM
.... . .-.. .-.. --- / .-M- .A-- I.--
.... . .-.. .-.. --- / .---- ..--- ...--
_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()
を使用してデータを抽出します。スペースは不等式を使用して検出されることにも注意してください。 「カンマ未満」のすべての文字をスペースと見なします。
for
ループ、改行を含む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,
_
私はシンボルのコンパクトなコーディングを試していましたが、すでに使用されている暗黙のツリーよりも優れているかどうかはわかりません。そのため、他の誰かが使用できるように、ここにコーディングを示します。
次の文字列を考えます。
--..--..-.-.-..--...----.....-----.--/
これには、必要なシーケンスがすべてサブストリングとして含まれています。次のように、記号をオフセットと長さでcouldコーディングします。
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はこのトリックの短いバージョンを見つけました (そして、ここで少なくとも冗長性のいくつかをここで見ることができます)、Nice cの実装を行いました。 アレックは最初の(バギーで不完全な)バージョンでpython実装 を行いました。 ホッブズはかなりコンパクトなPerlバージョンを行いました 私はしませんでしたまったく理解しています。
'.- /'{~;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.'
.... . .-.. .-.. --- .-.-.- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- --..--
入力の最後の改行はサポートされていないため、次のようなものを使用してください
echo -n Hello, Stackoverflow| ../golfscript.rb morse.gs
' '/{{.32|"!etianmsurwdkgohvf!l!pjbxcyzq"?)"UsL?/'#! 08<>"@".,?0123456789"?=or
2base(;>{'.-'\=}%' '}%}%'/'*
文字は特殊なケースであり、小文字に変換され、バイナリの位置に並べられます。
それ以外はすべて変換テーブルによって行われます
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) }));
}
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()))
(変換テーブルをユニコードコードポイントにエンコードします。正常に機能し、Windows Vistaマシンでのテストでは、これらが正常に表示されます。)
不要なスペースと角かっこを削除して(リストcomps gen expsを作成して)、184文字まで削減するように編集されました。
もう一度編集します。ここで他の回答を見る前に、私が知らないほど多くのスペースを削除することが可能だったため、176まで下がっています。
'' .joinの代わりに '' .joinを使用し、スペースを個別に実行して、172(woo woo!)まで再度編集します。 (ええと!)
不完全なソリューションですが、多分誰かがそれから完全なソリューションを作ることができます。数字や句読点は処理しませんが、重量はわずか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))
別のツリーベースのソリューション。
#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));}}
wikipedia が間違っているように見えるか、何かを誤解している可能性があるため、ソースツリーにエラーがある可能性があります。
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"
収量
.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- .-.-.-
私のテクニックは今のところユニークかもしれません。アイデアは:
もう少しありますが、それが要点です。カンマ、ピリオド、スペースは0〜Zの範囲にないため、「一致」によって特別に処理されます。 0からZの範囲の一部の「未使用」文字(「;」など)は、それ自体がモールス文字ではない他のモールス翻訳の接尾辞として表で使用されます。
およそ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
(ただし数字はなく、単語はダブルスペースで区切られているだけです:/ ...)
これが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
W(n,p){while(n--)putch(".-.-.--.--..--..-.....-----..../"[p++]);}main(){
char*p,c,s[99];gets(s);for(p=s;*p;){c=*p++;c=toupper(c);c=c>90?35:c-32?
"È#À#¶µ´³²±°¹¸·#####Ê#@i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c-44]:63;c-35?
W(c>>5,c&31):0;putch(0);}}
これはstdinから入力を受け取ります。コマンドラインから入力すると、2文字追加されます。の代わりに:
...main(){char*p,c,s[99];gets(s);for(p=s;...
あなたが得る:
...main(int i,char**s){char*p,c;for(p=s[1];...
127以上の文字にWindows-1252コードページを使用していますが、他の人のブラウザでどのように表示されるかわかりません。少なくとも私のブラウザ(Google Chrome)では、2つの文字(「@」と「i」の間)が表示されないことに気づきました。ただし、ブラウザからコピーしてテキストエディタに貼り付けると、小さなボックスではありますが、表示されます。
ASCIIのみに変換できますが、これにより24文字が追加され、文字数が257に増えます。これを行うには、まず文字列の各文字を-64だけオフセットし、127より大きい文字数を最小限に抑えます。次に、 \x
[〜#〜] xx [〜#〜]文字は、必要に応じてエスケープします。これはこれを変更します:
...c>90?35:c-32?"È#À#¶µ´³²±°¹¸·#####Ê#@i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c-44]:63;
c-35?W(...
これに:
...c>90?99:c-32?"\x88#\x80#vutsrqpyxw#####\x8A#\0PA)\xE0N%Q\nU!O\5\1\66DE 1
\xE1*S$ICH"[c-44]+64:63;c-99?W(...
これは、コードのより適切にフォーマットされコメント化されたバージョンです。
/* writes `n` characters from internal string to stdout, starting with
* index `p` */
W(n,p){
while(n--)
/* warning for using putch without declaring it */
putch(".-.-.--.--..--..-.....-----..../"[p++]);
/* dmckee noticed (http://tinyurl.com/n4eart) the overlap of the
* various morse codes and created a 37-character-length string that
* contained the morse code for every required character (except for
* space). You just have to know the start index and length of each
* one. With the same idea, I came up with this 32-character-length
* string. This not only saves 5 characters here, but means that I
* can encode the start indexes with only 5 bits below.
*
* The start and length of each character are as follows:
*
* A: 0,2 K: 1,3 U: 10,3 4: 18,5
* B: 16,4 L: 15,4 V: 19,4 5: 17,5
* C: 1,4 M: 5,2 W: 4,3 6: 16,5
* D: 9,3 N: 1,2 X: 9,4 7: 25,5
* E: 0,1 O: 22,3 Y: 3,4 8: 24,5
* F: 14,4 P: 4,4 Z: 8,4 9: 23,5
* G: 5,3 Q: 5,4 0: 22,5 .: 0,6
* H: 17,4 R: 0,3 1: 21,5 ,: 8,6
* I: 20,2 S: 17,3 2: 20,5 ?: 10,6
* J: 21,4 T: 1,1 3: 19,5
*/
}
main(){ /* yuck, but it compiles and runs */
char *p, c, s[99];
/* p is a pointer within the input string */
/* c saves from having to do `*p` all the time */
/* s is the buffer for the input string */
gets(s); /* warning for use without declaring */
for(p=s; *p;){ /* begin with start of input, go till null character */
c = *p++; /* grab *p into c, increment p.
* incrementing p here instead of in the for loop saves
* one character */
c=toupper(c); /* warning for use without declaring */
c = c > 90 ? 35 : c - 32 ?
"È#À#¶µ´³²±°¹¸·#####Ê#@i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c - 44] : 63;
/**** OR, for the ASCII version ****/
c = c > 90 ? 99 : c - 32 ?
"\x88#\x80#vutsrqpyxw#####\x8A#\0PA)\xE0N%Q\nU!O\5\1\66DE 1\xE1"
"*S$ICH"[c - 44] + 64 : 63;
/* Here's where it gets hairy.
*
* What I've done is encode the (start,length) values listed in the
* comment in the W function into one byte per character. The start
* index is encoded in the low 5 bits, and the length is encoded in
* the high 3 bits, so encoded_char = (char)(length << 5 | position).
* For the longer, ASCII-only version, 64 is subtracted from the
* encoded byte to reduce the necessity of costly \xXX representations.
*
* The character array includes encoded bytes covering the entire range
* of characters covered by the challenge, except for the space
* character, which is checked for separately. The covered range
* starts with comma, and ends with capital Z (the call to `toupper`
* above handles lowercase letters). Any characters not supported are
* represented by the "#" character, which is otherwise unused and is
* explicitly checked for later. Additionally, an explicit check is
* done here for any character above 'Z', which is changed to the
* equivalent of a "#" character.
*
* The encoded byte is retrieved from this array using the value of
* the current character minus 44 (since the first supported character
* is ASCII 44 and index 0 in the array). Finally, for the ASCII-only
* version, the offset of 64 is added back in.
*/
c - 35 ? W(c >> 5, c & 31) : 0;
/**** OR, for the ASCII version ****/
c - 99 ? W(c >> 5, c & 31) : 0;
/* Here's that explicit check for the "#" character, which, as
* mentioned above, is for characters which will be ignored, because
* they aren't supported. If c is 35 (or 99 for the ASCII version),
* then the expression before the ? evaluates to 0, or false, so the
* expression after the : is evaluated. Otherwise, the expression
* before the ? is non-zero, thus true, so the expression before
* the : is evaluated.
*
* This is equivalent to:
*
* if(c != 35) // or 99, for the ASCII version
* W(c >> 5, c & 31);
*
* but is shorter by 2 characters.
*/
putch(0);
/* This will output to the screen a blank space. Technically, it's not
* the same as a space character, but it looks like one, so I think I
* can get away with it. If a real space character is desired, this
* must be changed to `putch(32);`, which adds one character to the
* overall length.
} /* end for loop, continue with the rest of the input string */
} /* end main */
これは、いくつかのPython実装を除いて、ここですべてを打ち負かします。これ以上短くすることはできないと思い続けますが、さらにいくつかの文字を削る方法を見つけます。改善の余地がある場合はお知らせください。
編集:
このルーチンは、ASCII 44(それぞれに空白スペースのみを出力))を超える無効な文字を拒否しますが、この値以下の無効な文字はチェックしません。これらを確認するにはこれを変更して、全長に5文字を追加します。
...c>90?35:c-32?"...
これに:
...c-32?c>90|c<44?35:"...
基本的に Andreaのソリューション と同じですが、完全なプログラムとして、愚かなトリックを使用して短くします。
_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'/',
_
(追加された改行はすべて削除できます)
または、2.6でbin()
関数を使用しない場合は、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'/',
_
(ここでも、追加された改行はすべて削除できます)
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バイトを文字にエンコードします。例として、Dは長さが3の場合は-..で、Eはです。これは、011と001としてエンコードされ、011001になります。さらに多くの文字をエンコード可能にし、エスケープを回避するために、合計に64が追加され、1011001-89、ASCII Y 。モールス信号以外の文字には長さ0が割り当てられます。l
の後半(\031
で始まる)は、モールス信号自体のビットであり、ドットは1でダッシュ0です。高ASCIIにならないように、このデータは7ビット/バイトでエンコードされます。
このコードは、最初にc
をサニタイズし、次にc
のモールス長(o
内)を計算してから、以前のすべての文字の長さを合計してb
、データへのビットインデックス。
最後に、ビットをループし、ドットとダッシュを印刷します。
長さ「7」は、スペースに遭遇したときに/を出力するための特別なフラグとして使用されます。
ブラケットを削除することで得られる小さな利益はおそらくあるでしょうが、私はより良い結果のいくつかからは程遠く、私は空腹です、それで...
static void Main()
{
Console.WriteLine(String.Join(" ", (from c in Console.ReadLine().ToUpper().ToCharArray()
select m[c]).ToArray()));
}
はい、だまされました。また、次のようにディクショナリを定義する必要があります(これにより、ゲームから吹き飛ばされるため、文字数を数える必要はありませんでした)。
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#実装を提供できますか?
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
説明:
"\264\202\317\0"
)は32ビットのモールス符号("--.-..-.-.-----.....--..--------"
)最初の26ビットのみが使用されます。これが「参照文字列」です。$m{'a'} = '.-'
et cetera、それで残っているのは、入力の文字を一致させ、ハッシュでそれらを調べ、出力をフォーマットすることだけです。最後の行は、Perlに削除を指示するShebangからの助けを借りて...入力の改行。入力の行を$_
、およびコードの実行が完了したら、$_
改行を追加して出力に戻ります。これは 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))
previous PHP entry を少し効率的になるように変更しました。:)
$a=array(32=>"/",44=>"--..--",1,".-.-.-",48=>"-----",".----","..---","...--","....-",".....","-....","--...","---..","----.",63=>"..--..",1,".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..");
foreach(str_split(strtoupper("hello world?"))as$k=>$v){echo $a[ord($v)]." ";}
コモドは2行で380文字を言っています-余分な行は単に読みやすくするためです。 ; D配列内に散在する1は、後で手動で配列の位置にジャンプする代わりに、配列の位置にデータを入力することで2バイトを節約するだけです。
1つ目と2つ目を比較します。違いははっきりと見えます。 :)
array(20=>"data",22=>"more data";
array(20=>"data",1,"more data";
ただし、最終的な結果は、コンテンツをループするのではなく、配列の位置を使用する限り正確です。これは、このゴルフコースでは行いません。
最終結果:578文字、380まで(198文字、または最大34.26%節約)。
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"
モールス信号をエンコードする3つ目の完全に異なる方法を次に示します。
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))
これを印刷可能な文字のセットにマップする方法を理解できれば、かなりの数の文字を節約できます。これがおそらく私の最もdirectソリューションですが、それが最も読みやすいかどうかはわかりません。
さて、今私は無駄にしていますwayこれにはあまりにも多くの時間。
他の回答のいくつかに基づいています。
編集:ツリーを縮小しました(そうです)。
#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);}}
ハスケル
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 からの引用です。
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))
制限:
ルールは最小数文字を要求し、最小数バイトを要求していないため、印刷可能領域の外に進んでよければ、少なくとも1つのルックアップテーブルを小さく(半分)できますASCII文字。
編集:単純に選ばれた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に次ぐものになると思います。:-)
char*p[36]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
main(){int c;while((c=tolower(getchar()))!=10)printf("%s ",c==46?".-.-.-":c==44?"--..--":c==63?"..--..":c==32?"/":*(p+(c-97)));}
[〜#〜] 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 [〜#〜]、標準入力を使用して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);}}
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
C、533文字
いくつかのコメントからアドバイスをもらい、標準入力に切り替えました。さらに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);
}
これは不完全ですカンマ、フルストップ、クエリをまだ処理しないため。
#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ビット以外の文字は追加しませんでした。