莫尔斯电码到标准输出


13

这个问题涉及将摩尔斯电码的输入作为。(句点)和-(减号),并用空格分隔输入。您的任务是将代码转换为标准输出。您可以假定唯一的输入包含在国际摩尔斯电码字母表中找到的字符符号,可以在以下位置找到:http : //en.wikipedia.org/wiki/Morse_code#Letters.2C_numbers.2C_punctuation

所有输出应使用小写字母。双精度空格应解释为单词空格。

输入样例:

. -..- .- -- .--. .-.. . .-.-.-  ... --- ...

输出:

example. sos

两周后获胜的最短代码。


您只说“字符符号”是字符符号吗?
Sinkingpoint 2014年

@Quirliom该链接中的所有“符号”都是字符。您可以在String中放入的任何字符都是字符(基本上是这样)。然而,问题的那部分基本上是说莫尔斯电的每一点都是有效的。
贾斯汀

@Quirliom是的,每个摩尔斯“字符”,例如.-代表“ a”和“。”。因为“ e”有效。无需处理非摩尔斯字符。

字母空间和单词空间呢?前者有一个空间,后者有两个(或更多)空间?
Paul R

Answers:


8

Mathematica 62

Mathematica让我们作弊

f=ToLowerCase@StringDrop[WolframAlpha[". .- "<>#,"Result"],2]&

f@"."
f@". -..- .- -- .--. .-.. . .-.-.-"
f@".... .- ...- .  -.-- --- ..-  -- --- --- . -..  - --- -.. .- -.-- ..--.."

Ë

例。

你今天有心情吗?

前两个符号..-是正确解释小代码所必需的。


这缺少到小写的转换。
彼得·泰勒

@PeterTaylor可以很容易地将其修改 f=ToLowerCase@StringDrop[WolframAlpha[". .- "<>#,"Result"],2]&为小写。
ybeltukov 2014年

使用Wolfram Alpha api是否不需要应用程序ID?如果是这样,那不应该增加字符数吗?不过很聪明的解决方案。
比约恩·林奎斯特

@BjörnLindqvist只需在Mathematica中精确评估此命令,它就可以了。
ybeltukov 2014年

23

德拉特,我希望能在GolfScripters到达之前到达这里:-(

hoo ...

C:228个字符:

char n,t,m[9],*c=" etianmsurwdkgohvf l pjbxcyzq  54 3   2& +    16=/   ( 7   8 90    $       ?_    \"  .    @   '  -        ;! )     ,    :";
main(){while(scanf("%s",m)>0){for(t=m[6]=n=0;m[n];n++)t+=t+1+(m[n]&1);putchar(c[t]);}}

我以为我会对此做一个解释。

根据中的树数据解析输入数据*c,可以将其扩展如下(·用于表示一个空节点):

                     dot <-- (start) --> dash
                e                               t
        i               a               n               m
    s       u       r       w       d       k       g       o
  h   v   f   ·   l   ·   p   j   b   x   c   y   z   q   ·   ·
 5 4 · 3 · · · 2 & · + · · · · 1 6 = / · · · ( · 7 · · · 8 · 9 0
····$·······?_····"··.····@···'··-········;!·)·····,····:·······

从树的顶部开始,向下移动,同时向左移动一个点,向右移动一个短划线。然后在输入字符串结束时(即,遇到空白字符时)输出您碰巧遇到的任何字符。因此,例如,三个点和线将带你v通过eis。无需显式检查点(ASCII \x2e)和破折号(ASCII \x2d),我们只需要检查最后一位(m[n]&1),即0代表.1 -

六行足以编码除以外的所有内容,除外$,后者具有7个点/破折号:...-..-,但由于保证输入数据有效,因此可以通过将输入截断为6个字符(m[6]=0)并解释...-..$来轻松解决。我们还可以从树数据中删除最后7个字节,因为它们都是空的,并且如果输入有效,则不需要。


1
丢弃6个字符代码的最后一个字符并缩短查找表的不错技巧。
彼得·泰勒

2
对于讨论的清晰性和算法的质量,我都表示赞成。辛苦了
Michael Stern 2014年

看看是否可以通过逐个字符地处理而不是读取整个字符串c来删节几个字符。可以内联。也许您可以使用模和偏移量来尝试将较高的值压在一起;这就是我在解决方案中所做的。无论如何,辛苦了!
FireFly 2014年

8

GolfScript(116 113 97个字符)

这包括在查找表中使用的不可打印字符,因此我将其作为xxd输出:

0000000: 6e2d 2720 272f 7b60 7b5c 6261 7365 2035
0000010: 3925 2210 a9cd 238d 57aa 8c17 d25c d31b
0000020: 432d 783e 277a 3823 e146 e833 6423 23ac
0000030: e72a 39d5 021c 4e33 3b30 3138 dc51 2044
0000040: 3aa7 d001 df4b 2032 333f 36ae 51c3 223d
0000050: 7d2b 5b35 2d34 5d2f 2b32 3333 257d 256e
0000060: 2b

这将解码为与

n-' '/{`{\base 59%"\x10\xA9\xCD#\x8DW\xAA\x8C\x17\xD2\\\xD3\eC-x>'z8#\xE1F\xE83d##\xAC\xE7*9\xD5\x02\x1CN3;018\xDCQ D:\xA7\xD0\x01\xDFK 23?6\xAEQ\xC3"=}+[5-4]/+233%}%n+

这本质上是

n-' '/{`{\base 59%"MAGIC STRING"=}+[5-4]/+233%}%n+

这基于一个用于生成最小完美哈希函数的最佳算法的核心思想使用了(非最小)完美哈希捷克,哈瓦斯和马耶夫斯基;1992年。他们的基本思想是使用两个哈希函数f1f2以及一个查找表g,而完美的哈希是(g[f1(str)] + g[f2(str)]) % m(这里m是我们希望区分的字符串数);聪明的一点是他们建立的方式g。将所有值f1(str)和感兴趣的f2(str)字符串str视为无向图中的节点,并在f1(str)和之间添加一条边f2(str)对于每个字符串。它们不仅要求每个边都不同,而且要求图是非循环的。那么将权重分配给节点(即填充查找表g)只是DFS,这样每个边都有所需的总和即可。

Czech等人生成随机函数,f1f2通过查找表将其表示出来,但这显然不好:我使用简单的基本转换(具有从-10到9的两个不同基数)搜索了合适的哈希值。我还放宽了非循环的要求。我不想将字符串分配给从0到54的值,而是分配给相应的ASCII码,因此,(g[f1(str)] + g[f2(str)]) % m我不想将它们分配给(g[f1(str)] + g[f2(str)]) % Nsome N > 'z'。但这允许自由尝试各种变量,N并查看它们是否允许有效的查找表g,而不管是否存在循环。与Czech等人不同,我不在乎是否寻找完美的哈希函数是O(n ^ 4)。

-4base5basemod 生成的图形59为:

通过点进行点微调的图形

除了最大的连接组件(长度为三个周期)之外,这是相当不错的。我们必须N=233先找到一个g一致的值。


查找表的其他可能编码:差异编码将无济于事,因为没有结构。可能有可能通过将编码编码为置换来利用值的非重复性,但是需要分别处理间隙(54个输出字符=> 30字节的熵,再加上解码;如果编码,则行程至少需要15个字节作为直接的基本转换;可能有可能在当前的总共92个字节上进行改进),或者我们置换了138个项目(超过98个字节的熵,加上解码)。
彼得·泰勒

由于它是一个非前缀代码,因此我们不能轻易地将繁琐的工作留给zlib实现。
彼得·泰勒

4

C,169个字符

我找不到更好的哈希函数。

(我发布了未最小化的代码,但计数为最小化;要最小化,只需:%s/ //g | %j!在vim中这样做,然后在字符串文字中放回空格。)

c, v = 1;

main() {
  while (c = getchar(), ~c)
    v = c < 33? putchar(
      "& etianmsurwdkgohvf.l.pjbxcyzq..54.3.;!2).+...,16=/:..(.7.?_8.9o\"...$...@...'..-"[v < 64? (v != 40)*v : v % 51 + 33]
    ), 1 : v * 2 + c % 2;
}

测试运行

morse.in只是莫尔斯语中的整个字母在单独的行上):

% clang morse.c && ./a.out </tmp/morse.in
abcdefghijklmnopqrstuvwxyzO123456789.,?'!/()&:;=+-_"$@
% ./a.out <<<'. -..- .- -- .--. .-.. . .-.-.-  ... --- ...'
example. sos

说明

这是相当简单的。c < 33找到一个空白/分隔符(\n,EOF,...)。c % 2将点或破折号转换成一点。想法是简单地通过将每个字符解释为二进制数字(在为前缀加上1以处理可变长度之后)来为每个字符创建唯一数字(这种解释就是其中的v*2 + c%2一部分)。然后,我得到了一个137个字符的LUT,并通过对所得值进行哈希处理(v < 64? v : v % 51 + 33通过试错法找到常量,并查看分布并试图找到一个巨大的缺口)来对其进行压缩。不幸的是,此哈希函数只有一次冲突,这就是为什么我必须对40 → '&'映射进行特殊情况的原因。


4

R,145字节

将点转换为2,将破折号转换为1,并以三进制形式解释数字并采用mod 89,这给出了我们可以在哈希表中使用的唯一数字。存在13(111 base-3)表示加1,因为ASCII 13在TIO中不起作用。

cat(c(letters,0:9,".")[match(strtoi(chartr(".-","12",scan(,"",t=scan(,""))),3)%%89+1,utf8ToInt('DG,)62	5N*EHMAI.%"!4=@'))],sep='')

在线尝试!

R,236字节(非竞争)

不会具有竞争力,但是它可以让我们在R中展示一些有趣的东西:将莫尔斯电码树存储在带引号的语言结构中,m并使用[[可以递归地应用于列表。例如m[[c(2,2,3,2)]]检索点,点,破折号,点或“ f”。

m=quote(.(e(i(s(h(5,4),v(,3)),u(f,M(,2))),a(r(l,.(.(,.),)),w(p,j(,1)))),t(n(d(b(6),x),k(c,y)),m(g(z(7),q),o(D(8),S(9,0))))))
for(w in scan(,"",t=scan(,"")))
cat(chartr("MDS","-. ","if"(is.symbol(z<-m[[(utf8ToInt(w)==45)+2]]),z,z[[1]])))

在线尝试!


1

Powershell,193个字节

$n=1
-join("$args "|% t*y|%{if($_-32){$n=$n*2+($_-ne'.')}else{("  etianmsurwdkgohvf l pjbxcyzq  54 3   2& +~16=/   ( 7   8 90~~~?~ `"  .~@   '  -~~;! )~ ,~:~~~~$"-replace'~','    ')[$n]
$n=1}})

减少高尔夫测试脚本:

$f = {

$n=1
-join(
    "$args "|% t*y|%{
        if($_-32){
            $n=$n*2+($_-ne'.')
        }else{
            ("  etianmsurwdkgohvf l pjbxcyzq  54 3   2& +~16=/   ( 7   8 90~~~?~ `"  .~@   '  -~~;! )~ ,~:~~~~$"-replace'~','    ')[$n]
            $n=1
        }
    }
)

}

@(
    ,("example. sos",". -..- .- -- .--. .-.. . .-.-.-  ... --- ...")
    ,("0123456789abcdefghijklmnopqrstuvwxyz","----- .---- ..--- ...-- ....- ..... -.... --... ---.. ----. .- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..")
    ,("hello world", ".... . .-.. .-.. ---  .-- --- .-. .-.. -..")
) | % {
    $expected,$s = $_
    $result = &$f $s
    "$($result-eq$expected): $result"
}

输出:

True: example. sos
True: 0123456789abcdefghijklmnopqrstuvwxyz
True: hello world

0

JavaScript(165字节,仅实现四个平面。)

n=''.replace(/\./g,1).replace(/-/g,0).split(' ')
l='|te|mnai|ogkdwrus|cöqzycxbjpälüfvh'.split('|')
r=''
for(i in n){r+=l[n[i].length][parseInt(n[i],2)]}
alert(r)

应将输入分配给n,执行以下代码以获取输出:

n='. -..- .- -- .--. .-.. .'.replace(/\./g,1).replace(/-/g,0).split(' ')
l='|te|mnai|ogkdwrus|cöqzycxbjpälüfvh'.split('|')
r=''
for(i in n) {r+=l[n[i].length][parseInt(n[i],2)]}
alert(r)

这不仅是一个不完整的实现,而且甚至不起作用。Fiddle + Chrome给出了error Cannot read property '42' of undefined,并且IdeOne也报告了一个错误(尽管没有有用的消息)。
彼得·泰勒

尝试修复它:)
Timtech

@PeterTaylor据说它仅支持4个平面,即最多可以填充4个字符的莫尔斯电码,因此它不能接受. -..- .- -- .--. .-.. . .-.-.-作为输入,因为最后一个代码是6个字符。在示例脚本中,我忽略了它,并使用了. -..- .- -- .--. .-..alert(example)。
aularon 2014年

这是第二个代码的小提琴:jsfiddle.net/aularon/AHY4e/1
aularon 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.