The challenge
The shortest code by character count, that will input a string using only alphabetical characters (upper and lower case), numbers, commas, periods and question mark, and returns a representation of the string in Morse code.
The Morse code output should consist of a dash (-
, ASCII 0x2D) for a long beep (AKA 'dah') and a dot (.
, ASCII 0x2E) for short beep (AKA 'dit').
Each letter should be separated by a space (' '
, ASCII 0x20), and each word should be separated by a forward slash (/
, ASCII 0x2F).
Morse code table:
alt text http://liranuna.com/junk/morse.gif
Test cases:
Input:
Hello world
Output:
.... . .-.. .-.. --- / .-- --- .-. .-.. -..
Input:
Hello, Stackoverflow.
Output:
.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- .-.-.-
Code count includes input/output (that is, the full program).
Perl, 206 characters, using dmckee's idea
This is longer than the first one I submitted, but I still think it's interesting. And/or awful. I'm not sure yet. This makes use of dmckee's coding idea, plus a couple other good ideas that I saw around. Initially I thought that the "length/offset in a fixed string" thing couldn't come out to less data than the scheme in my other solution, which uses a fixed two bytes per char (and all printable bytes, at that). I did in fact manage to get the data down to considerably less (one byte per char, plus four bytes to store the 26-bit pattern we're indexing into) but the code to get it out again is longer, despite my best efforts to golf it. (Less complex, IMO, but longer anyway).
Anyway, 206 characters; newlines are removable except the first.
Explanation:
"\264\202\317\0"
) represent 32 bits of morse code ("--.-..-.-.-----.....--..--------"
) although only the first 26 bits are used. This is the "reference string".$m{'a'} = '.-'
et cetera, so all there is left is to match characters of the input, look them up in the hash, and format the output, which the last line does... with some help from the shebang, which tells perl to remove the newline on input, put lines of input in$_
, and when the code completes running, write$_
back to output with newlines added again.Bash, a script I wrote a while ago (time-stamp says last year) weighing in at a hefty 1661 characters. Just for fun really :)
C89 (388 characters)
This is incomplete as it doesn't handle comma, fullstop, and query yet.
Wrapped for readability. Only two of the linebreaks are required (one for the #define, one after else, which could be a space). I've added a few non-standard characters but didn't add non-7-bit ones.
I was dorking around with a compact coding for the symbols, but I don't see if getting any better than the implicit trees already in use, so I present the coding here in case some one else can use it.
Consider the string:
which contains all the needed sequences as substrings. We could code the symbols by offset and length like this:
with the space (i.e. word boundary) starting and ending on the final character (the '/'). Feel free to use it, if you see a good way.
Most of the shorter symbols have several possible codings, of course.
P Daddy found a shorter version of this trick (and I can now see at least some of the redundancy here) and did a nice c implementation. Alec did a python implementation with the first (buggy and incomplete) version. Hobbs did a pretty compact perl version that I don't understand at all.
Here's another approach, based on dmckee's work, demonstrating just how readable Python is:
Python
244 characters
Limitations:
Since the rules called for fewest characters, not fewest bytes, you could make at least one of my lookup tables smaller (by half) if you were willing to go outside the printable ASCII characters.
EDIT: If I use naïvely-chosen Unicode chars but just keep them in escaped ASCII in the source file, it still gets a tad shorter because the decoder is simpler:
Python
240 characters
I think it also makes the intent of the program much clearer.
If you saved this as UTF-8, I believe the program would be down to 185 characters, making it the shortest complete Python solution, and second only to Perl. :-)
Perl, 170 characters (with a little help from accomplished golfer
mauke
). Wrapped for clarity; all newlines are removable.Explanation:
"Hello world"
becomes"H E L L O / W O R L D"
|
)In the final version, the dictionary is optimized for runtime efficiency:
Since the golfed code only replaces one character per loop (to save one character of code!) the number of loops is limited to five times the length of the input (three times the length of the input if only alphabetics are used). But by adding a
g
to thes///
operation, the number of loops is limited to three (two if only alphabetics are used).Example transformation: