Mã Morse cho đầu ra tiêu chuẩn


13

Câu hỏi này liên quan đến việc lấy đầu vào trong mã Morse như. (dấu chấm) và - (ký hiệu trừ), có khoảng trắng để phân tách đầu vào. Nhiệm vụ của bạn là chuyển đổi mã thành đầu ra tiêu chuẩn. Bạn có thể giả sử rằng đầu vào duy nhất chứa các ký hiệu ký tự được tìm thấy trong bảng chữ cái Mã Morse quốc tế, được tìm thấy ở đây: http://en.wikipedia.org/wiki/Morse_code#Letters.2C_numbers.2C_puncinating .

Tất cả đầu ra nên sử dụng chữ thường. Một không gian đôi nên được hiểu là một không gian từ.

Đầu vào mẫu:

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

Đầu ra:

example. sos

Mã ngắn nhất sau hai tuần chiến thắng.


Bạn chỉ nói 'ký hiệu nhân vật' là ký tự ký hiệu?
Điểm chìm

@Quirliom Tất cả các "biểu tượng" trong liên kết đó là các ký tự. Bất cứ điều gì bạn có thể đặt trong Chuỗi là một ký tự (tốt, về cơ bản). Tuy nhiên, phần đó của câu hỏi về cơ bản là nói rằng mọi bit của morse sẽ có giá trị.
Justin

@Quirliom Có, mọi 'nhân vật' của Morse, chẳng hạn như .- cho 'a' và. cho 'e' là hợp lệ. Không có nhân vật không phải Morse cần được xử lý.

Còn không gian chữ và không gian từ thì sao? Một không gian cho cái trước và hai (hoặc nhiều hơn) cho cái sau?
Paul R

Câu trả lời:


8

Toán học 62

Mathematica cho phép chúng ta gian lận

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

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

e

thí dụ.

hôm nay bạn có nói không

Hai ký hiệu đầu tiên ..-cần thiết để giải thích chính xác các mã nhỏ.


Điều này là thiếu chuyển đổi sang chữ thường.
Peter Taylor

@PeterTaylor Nó có thể dễ dàng sửa đổi f=ToLowerCase@StringDrop[WolframAlpha[". .- "<>#,"Result"],2]&cho trường hợp thấp hơn.
ybeltukov

Không sử dụng api Wolfram Alpha có yêu cầu id ứng dụng không? Nếu vậy, không nên thêm vào số lượng nhân vật? Tuy nhiên giải pháp rất thông minh.
Bjorn Lindqvist

@ BjornLindqvist Chỉ cần đánh giá chính xác lệnh này trong Mathematica , nó sẽ ổn.
ybeltukov

23

Drat, tôi đã hy vọng đến đây trước khi các GolfScript đến :-(

Dù sao ...

C: 228 ký tự:

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

Tôi nghĩ rằng tôi muốn thêm một lời giải thích về cách thức này hoạt động.

Dữ liệu đầu vào được phân tích cú pháp theo dữ liệu cây *c, có thể được mở rộng như sau (sử dụng ·để thể hiện một nút trống):

                     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
····$·······?_····"··.····@···'··-········;!·)·····,····:·······

Bắt đầu từ ngọn cây, di chuyển xuống bên trái trong khi di chuyển sang trái để chấm và sang phải cho dấu gạch ngang. Sau đó xuất bất kỳ ký tự nào bạn xảy ra khi chuỗi đầu vào kết thúc (nghĩa là khi gặp phải một ký tự khoảng trắng). Vì vậy, ví dụ, ba dấu chấm và một dấu gạch ngang sẽ đưa bạn đến vqua e, is. Thay vì kiểm tra rõ ràng các dấu chấm (ASCII \x2e) và dấu gạch ngang (ASCII \x2d), chúng ta chỉ cần kiểm tra bit cuối cùng ( m[n]&1), là 0 cho .và 1 cho -.

Sáu hàng là đủ để mã hóa tất cả mọi thứ ngoại trừ $, trong đó có 7 chấm / dấu gạch ngang: ...-..-, nhưng kể từ khi dữ liệu đầu vào được đảm bảo có giá trị, điều này có thể dễ dàng được sửa chữa bằng cách cắt xén đầu vào lúc 6 ký tự ( m[6]=0) và giải thích ...-..như $để thay thế. Chúng tôi cũng có thể cắt 7 byte cuối cùng khỏi dữ liệu cây, vì chúng đều trống và không cần thiết nếu đầu vào hợp lệ.


1
Thủ thuật hay để loại bỏ ký tự cuối cùng của mã 6 ký tự và rút ngắn bảng tra cứu.
Peter Taylor

2
Tôi đang bỏ phiếu nhiều vì sự rõ ràng của các cuộc thảo luận về chất lượng của thuật toán. Làm tốt lắm.
Michael Stern

Xem nếu bạn có thể cạo một vài ký tự bằng cách xử lý từng ký tự thay vì đọc toàn bộ một chuỗi. cCó thể được nội tuyến. Có lẽ bạn có thể sử dụng modulo & một phần bù để cố gắng ghép các giá trị cao hơn lại với nhau; đây là những gì tôi làm trong giải pháp của tôi Dù sao, công việc tốt đẹp!
FireFly

8

GolfScript ( 116 113 97 ký tự)

Điều này bao gồm các ký tự không in được sử dụng trong bảng tra cứu, vì vậy tôi đưa ra dưới dạng đầu ra 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

Điều này giải mã thành một chương trình tương đương với

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+

mà thực chất là

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

Điều này sử dụng hàm băm hoàn hảo (không tối thiểu) dựa trên ý tưởng cốt lõi của Thuật toán tối ưu để tạo các hàm băm hoàn hảo tối thiểu; Séc, Havas và Majewski; 1992 . Ý tưởng cơ bản của họ là bạn sử dụng hai hàm băm f1f2cùng với bảng tra cứu gvà hàm băm hoàn hảo là (g[f1(str)] + g[f2(str)]) % m( msố chuỗi chúng ta muốn phân biệt); bit thông minh là cách họ xây dựng g. Xem xét tất cả các giá trị f1(str)f2(str)cho các chuỗi strquan tâm dưới dạng các nút trong biểu đồ không bị chặn và thêm cạnh giữa f1(str)f2(str)cho mỗi chuỗi. Họ yêu cầu không chỉ mỗi cạnh phải khác biệt, mà đồ thị phải có tính chu kỳ; sau đó, nó chỉ là một DFS để gán trọng số cho các nút (tức là để điền vào bảng tra cứu g) sao cho mỗi cạnh có tổng cần thiết.

Séc et al tạo ra các hàm ngẫu nhiên f1f2được thể hiện thông qua các bảng tra cứu, nhưng rõ ràng là không tốt: Tôi đã tìm kiếm một hàm băm phù hợp bằng cách sử dụng các chuyển đổi cơ bản đơn giản với hai cơ sở riêng biệt từ -10 đến 9. Tôi cũng nới lỏng yêu cầu theo chu kỳ. Tôi không muốn gán các chuỗi cho các giá trị từ 0 đến 54, nhưng với các mã ASCII tương ứng, vì vậy thay vì lấy một số thứ (g[f1(str)] + g[f2(str)]) % mtôi muốn . Nhưng điều đó cho phép tự do thử nhiều loại khác nhau và xem liệu bất kỳ trong số chúng cho phép một bảng tra cứu hợp lệ , bất kể có chu kỳ hay không. Không giống như Séc và cộng sự, tôi không quan tâm nếu tìm kiếm hàm băm hoàn hảo là O (n ^ 4).(g[f1(str)] + g[f2(str)]) % NN > 'z'Ng

Biểu đồ được tạo bởi -4base5basemod 59là:

Biểu đồ được hiển thị bằng dấu chấm với một số điều chỉnh nhỏ

khá đẹp ngoài thành phần được kết nối lớn nhất, có ba chu kỳ dài 1. Chúng ta phải đi lên N=233trước khi có thể tìm thấy một thành gphần phù hợp.


Các mã hóa có thể khác cho bảng tra cứu: mã hóa khác biệt sẽ không hữu ích, vì không có cấu trúc. Có thể khai thác việc không lặp lại các giá trị bằng cách mã hóa dưới dạng hoán vị, nhưng các khoảng trống cần được xử lý riêng (54 ký tự đầu ra => 30 byte entropy, cộng với giải mã; các lần chạy cần ít nhất 15 byte nếu được mã hóa như một chuyển đổi cơ sở thẳng, có thể cải thiện tổng số 92 byte hiện tại) hoặc chúng tôi đang thẩm thấu 138 mục (hơn 98 byte entropy, cộng với giải mã).
Peter Taylor

Vì đó là mã không có tiền tố, chúng tôi không thể dễ dàng cố gắng thực hiện công việc khó khăn để triển khai zlib.
Peter Taylor

4

C, 169 ký tự

Tôi không thể tìm thấy hàm băm tốt hơn ..

(Tôi đã đăng mã chưa được tối ưu hóa nhưng đã đếm nó được rút gọn; để thu nhỏ chỉ cần làm :%s/ //g | %j!trong vim, sau đó đặt khoảng trắng trong chuỗi ký tự trở lại.)

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

Chạy thử nghiệm

( morse.inchỉ là toàn bộ bảng chữ cái trong morse trên các dòng riêng biệt):

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

Giải trình

Điều này là khá đơn giản. c < 33tìm thấy một ký tự khoảng trắng / tách ( , \n, EOF, ...). c % 2dịch một dấu chấm hoặc dấu gạch ngang thành một chút. Ý tưởng là tạo một số duy nhất cho mỗi ký tự chỉ bằng cách diễn giải nó thành số nhị phân (sau khi đặt trước nó là 1 để xử lý độ dài biến) (cách hiểu này là v*2 + c%2một phần). Sau đó, tôi nhận được một LUT 137, mà tôi đã nén bằng cách băm giá trị kết quả ( v < 64? v : v % 51 + 33, các hằng số được tìm thấy thông qua thử và lỗi và bằng cách nhìn vào phân phối và cố gắng tìm một khoảng cách lớn). Thật không may, hàm băm này có một xung đột duy nhất, đó là lý do tại sao tôi phải đặc biệt hóa 40 → '&'ánh xạ.


4

R , 145 byte

Đã dịch một dấu chấm thành 2, dấu gạch ngang thành 1 và diễn giải số trong ternary và lấy mod 89, đưa ra một số duy nhất chúng ta có thể sử dụng trong bảng băm. Sự hiện diện của 13 (111 cơ sở 3) có nghĩa là thêm 1 vì ASCII 13 không hoạt động trong TIO.

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

Hãy thử trực tuyến!

R , 236 byte (không cạnh tranh)

Điều này sẽ không cạnh tranh, nhưng nó cho phép chúng tôi thể hiện một điều thú vị trong R: lưu trữ cây mã Morse bên trong cấu trúc ngôn ngữ được trích dẫn mvà lấy nó từ mã chấm và dấu gạch ngang rất đơn giản bằng cách sử dụng thực tế [[có thể được áp dụng đệ quy cho danh sách. Ví dụ: m[[c(2,2,3,2)]]lấy dấu chấm, dấu chấm, dấu gạch ngang, dấu chấm hoặc "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]])))

Hãy thử trực tuyến!


1

Powershell, 193 byte

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

Kịch bản kiểm tra ít chơi gôn:

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

Đầu ra:

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

0

JavaScript (165 byte, chỉ thực hiện bốn mặt phẳng.)

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)

Đầu vào phải được gán cho n, thực thi đoạn mã sau để lấy đầu ra:

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)

Điều này không chỉ có vẻ là một triển khai không đầy đủ, mà thậm chí còn không hoạt động. Fiddle + Chrome đưa ra lỗi Cannot read property '42' of undefinedvà IdeOne cũng báo cáo lỗi (mặc dù không có thông báo hữu ích).
Peter Taylor

Hãy thử sửa nó :)
Timtech

@PeterTaylor Người ta nói rằng nó chỉ hỗ trợ bốn mặt phẳng, tức là mã tăng 4 ký tự morse, do đó nó sẽ không chấp nhận . -..- .- -- .--. .-.. . .-.-.-làm đầu vào, vì mã cuối cùng dài 6 ký tự. Trong kịch bản ví dụ tôi bỏ qua nó và đi với . -..- .- -- .--. .-.., cảnh báo ( example).
aularon

Đây là một câu đố với mã khối thứ hai: jsfiddle.net/aularon/AHY4e/1
aularon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.