将字符串转换为摩尔斯电码

时间:2009-08-29 22:54:30

标签: language-agnostic code-golf

挑战

按字符数排序的最短代码,它将仅使用字母字符(大写和小写),数字,逗号,句点和问号输入字符串,并返回摩尔斯电码中字符串的表示形式。 摩尔斯电码代码输出应包括一个短划线(-,ASCII 0x2D)用于长哔声(AKA'dah')和一个点(.,ASCII 0x2E)用于短蜂鸣声(AKA'dit') )。

每个字母应以空格(' ',ASCII 0x20)分隔,每个字应以正斜杠(/,ASCII 0x2F)分隔。

摩尔斯电码表:

alt text http://liranuna.com/junk/morse.gif

测试用例:

Input:
    Hello world

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

Input:
    Hello, Stackoverflow.

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

代码计数包括输入/​​输出(即完整程序)。

32 个答案:

答案 0 :(得分:70)

答案 1 :(得分:48)

使用Morse Code Font

Console.Write(params[0]);

答案 2 :(得分: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. 提取莫尔斯词典。每个符号都是根据两个字符定义的,可以是字面点或短划线,也可以是对另一个定义字符值的引用。 E和T包含伪字符以避免解码器;我们稍后会删除它们。
  2. 读取并格式化输入。 "Hello world"变为"H E L L O / W O R L D"
  3. 下一步取决于输入和输出字典是不同的,因此将输入中的点转换为未使用的字符(竖线,|
  4. 将莫尔斯字典中输入的任何字符替换为字典中的值,直到没有替换为止。
  5. 删除步骤1中提到的虚拟字符。
  6. 打印输出。
  7. 在最终版本中,字典针对运行时效率进行了优化:

    • 所有单符号字符(E和T)和双符号字符(A,I,M和N)直接定义并一次解码。
    • 所有三个符号字符均以双符号字符和文字符号定义,两次解码。
    • 所有四个符号字符均以两个双符号字符定义,两次传递解码,三次替换。
    • 五个和六个符号的字符(数字和标点符号)分三次解码,分别有四个或五个替换。

    由于高尔夫代码每个循环只替换一个字符(以保存一个字符的代码!),循环次数限制为输入长度的五倍(如果仅使用字母,则为输入长度的三倍) 。但是通过向g操作添加s///,循环次数限制为三次(如果仅使用字母,则为两次)。

    转换示例:

    Hello 123
    H E L L O / 1 2 3
    II .] AI AI M- / AO UM SM
    .... . .-.. .-.. --- / .-M- .A-- I.--
    .... . .-.. .-.. --- / .---- ..--- ...--
    

答案 3 :(得分: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's C implementation,但不以相反的顺序存储这些位,并使用bin()来提取数据而不是算术。另请注意,使用不等式检测空格;它认为每个字符“小于逗号”都是一个空格。

Python 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,

答案 4 :(得分: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 found a shorter version of this trick(现在我现在可以看到至少一些冗余)并做了很好的c实现。 Alec did a python implementation第一个(错误和不完整)版本。 Hobbs did a pretty compact perl version我完全不理解。

答案 5 :(得分: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.'
.... . .-.. .-.. --- .-.-.- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- --..-- 

答案 6 :(得分:5)

C#266 chars

转换为C#的131 char 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) }));
}

答案 7 :(得分:5)

Golfscript - 106个字符 - 没有有趣的字符:)

输入结尾处的换行符不受支持,因此请使用类似

的内容

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

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

字母是一种特殊情况,并转换为小写字母并以二进制位置排序 其他一切都由翻译表完成

答案 8 :(得分:5)

Python 3 One Liner: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计算机上的测试中显示得很好。)

编辑通过删除一些不必要的空格和括号(使列表comps gen exps)减少到184个字符。

再次编辑:在看到其他答案之前,删除了更多我甚至不知道的空格 - 所以低至176。

使用'.join而不是''.join再次编辑到172(呜呜!)并单独执行空格。 (杜!)

答案 9 :(得分:4)

的Python

不完整的解决方案,但也许有人可以从中获得完整的解决方案。不处理数字或标点符号,但重量只有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))

答案 10 :(得分: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个字符。它将从命令行读取输入,一次一行,并将相应的输出发送回输出流。压缩版本如下,只有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

答案 11 :(得分: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));}}

可能是源代码树中的错误,因为wikipedia似乎有错误或者我误解了某些内容。

答案 12 :(得分: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

(没有数字,单词只用双空格分隔:/ ...)

答案 13 :(得分:3)

C(233个字符)

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];...

我正在使用Windows-1252代码页来处理127以上的字符,我不确定它们会在其他人的浏览器中出现。我注意到,至少在我的浏览器中(谷歌浏览器),两个字符(“@”和“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:"...

答案 14 :(得分: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个字符
  • 因此我们可以编码一个位(短划线或点)加上86个字符范围内的“下一个字符”
  • 范围ascii(32-117)全部是“可打印的”,可以作为这个86-char范围
  • 所以字符串文字沿着这些行编码一个表

还有一点,但这是要点。逗号,句号和空格不在0..Z范围内,因此它们由“匹配”专门处理。 0..Z(如';')范围内的一些“未使用”字符在表格中用作其他莫尔斯翻译的后缀,这些翻译本身并不是莫尔斯字母。

答案 15 :(得分: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之间所有字节的长度,包括两个字节到字符。例如,D是 - ..长度为3,E是。这个编码为011和001,给出011001。为了使更多的字符可编码并避免转义,然后将64添加到总数中,得到1011001 - 89,ASCII Y.非莫尔字符分配一个长度l的后半部分(以\031开头)是摩尔斯电码本身的位,点为1,短划线为0.为避免进入高位ASCII,此数据为编码7位/字节。

代码首先清理c,然后计算出c的莫尔斯长度(在o中),然后将所有先前字符的长度相加以生成b },比特索引到数据。

最后,它循环通过位,打印点和破折号。

长度'7'用作打印/遇到空格时的特殊标志。

移除括号可能会有一些微小的收获,但我离开了一些更好的结果而且我很饿,所以......

答案 16 :(得分:2)

Perl,206个字符,使用dmckee的想法

这比我提交的第一个更长,但我仍然认为它是有趣的。和/或可怕的。我不肯定。这利用了dmckee的编码思想,以及我看到的其他几个好主意。最初我认为“固定字符串中的长度/偏移”事物不能比我的其他解决方案中的方案更少,每个字符串使用固定的两个字节(以及所有可打印的字节)。事实上,我确实设法将数据降低到相当少(每个字符一个字节,加上四个字节来存储我们正在索引的26位模式)但是尽管我付出了最大的努力,但再次获取它的代码更长打高尔夫吧。 (不太复杂,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位。这是“参考字符串”。
  • 数据字符串的其余部分存储表示每个字符的引用字符串的起始位置和子串长度 - 每个字符一个字节,顺序为(A,B,... Z,0,1,... .. 9,“。”,“,”,“?”)。这些值被编码为23 *(长度-1)+ pos,解码器将其反转。最后一个起始位置当然是22。
  • 所以unpack完成了提取数据的一半工作,第三行(如此处所示)完成其余部分,现在我们有一个带$m{'a'} = '.-'等的哈希,所以剩下的就是匹配字符输入,在哈希中查找它们,并格式化输出,最后一行做的...在shebang的帮助下,告诉perl删除输入的换行符,在{{1}中输入输入行当代码完成运行时,将$_写回输出,再次添加换行符。

答案 17 :(得分:2)

C#使用Linq(133个字符)

    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#实现,这也很容易理解和维护吗?

答案 18 :(得分: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))

答案 19 :(得分:2)

Python 2; 171个字符

基本上与Andrea's solution相同,但作为一个完整的程序,并使用愚蠢的技巧使其缩短。

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'/',

(同样,添加的新行都可以删除)

答案 20 :(得分:1)

这是编码摩尔斯电码的第三种完全不同的方式:

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

如果你能想出一种方法将它映射到一组可打印的字符上,你可以保存很多字符。这可能是我最直接的解决方案,但我不知道它是否是最具可读性的。

好的,现在我浪费了很多时间

答案 21 :(得分:1)

这是另一种基于dmckee工作的方法,展示了Python的可读性:

的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'字符,我懒得添加它。我想你只需改变“??”部分,并在第二个字符串文字的末尾添加“ - ”
  • 它不会在单词之间加上'/';再次,懒惰

由于规则要求最少的字符,而不是最少的字节,如果你愿意,你可以使我的查询表中至少有一个更小(减半)在可打印的ASCII字符之外。

编辑:如果我使用天真选择的Unicode字符,但只是将它们保存在源文件中的转义ASCII中,它仍然会变得更短,因为解码器更简单:

的Python

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。 : - )

答案 22 :(得分:1)

C89(293个字符)

基于其他一些答案。

编辑:缩小树(yay)。

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

答案 23 :(得分:1)

<强>的Haskell

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

答案 24 :(得分:1)

PHP

我修改了previous PHP entry以提高效率。 :)

$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个字节。

考虑第一个与第二个。差异清晰可见。 :)

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

然而,最终结果与您使用数组位置完全一样,而不是循环遍历内容,我们在此高尔夫球场上没有这样做。

最终结果:578个字符,最低为380(198个字符,或节省约34.26%)。

答案 25 :(得分: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"

答案 26 :(得分: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);
}

答案 27 :(得分: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)));}

答案 28 :(得分: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

答案 29 :(得分:0)

C89(388个字符)

这是不完整的,因为它还没有处理逗号,fullstop和查询。

#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(' ');}}

包装是为了便于阅读。只需要两个换行符(一个用于#define,一个用于其他换行符,可以是一个空格)。我添加了一些非标准字符,但没有添加非7位字符。

答案 30 :(得分: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] . " ";}

答案 31 :(得分:0)

C ,448个字节,使用cmdline参数:

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