C (131 characters)
Yes, 13 1 !
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);}
I highlighted a few more characters by combining the logic from the while and for loops into one for loop and moving the declaration of the variable c to the definition of main as an input parameter. This last method that I borrowed from answered another call .
For those trying to test a program using GCC or with ASCII editors, you may need the following, slightly longer version:
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);}
This version is 17 characters longer (weighs about 148), due to the following changes:
- +4:
getchar() and putchar() instead of getch() and putch() - +6: escape codes for two characters instead of non-ASCII characters
- +1: 32 instead of 0 for space character
- +6: added "
c<0?1: " to suppress garbage from characters smaller than ASCII 32 (namely, from '\n' ). You still get garbage from any of !"#$%&'()*+[\]^_ _` {|}~ Or anything above ASCII 126.
This should make the code fully portable. Compile with:
gcc -std = c89 -funsigned-char morse.c
-std=c89 is optional. However, -funsigned-char is required, or you will get garbage for a comma and a complete stop.
135 characters
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);}
In my opinion, this latest version is much more visually appealing. And no, it is not portable, and it is no longer protected from input outside the limits. It also has a pretty bad interface, accepting character input and converting it to Morse code and not having an exit condition (you need to press Ctrl + Break ). But a portable, reliable code with a nice interface was not required.
The following is a brief description of the code:
main(c){ while(c = toupper(getch())) for(c = c - 32 ?
Each character in a long line of code contains Morse code for one text character. Each bit of an encoded character represents either a dash or a period. One represents a dash, and zero represents a dot. The smaller bit is the first stroke or dot in the Morse code. The final “guard” bit determines the length of the code. That is, the most significant bit in each encoded character represents the end of the code and is not printed. Without this guard bit, endpoint characters cannot be printed correctly.
For example, the letter “L” is “ .-.. ” in Morse code. To represent this in binary, we need 0, 1, and two more 0s, starting with the least significant bit: 0010. Drop one more on the protection bit, and we have our Morse code encoded: 10010 or decimal 18. Add an offset +34 to get 52, which is the ASCII value of the character "4". Thus, the encoded character array has “4” as the 33rd character (index 32).
This method is similar to the one used to encode characters in ACoolie , strager's (2) Miles's , pingw33n's , Alec and, but a bit simpler, requiring only one operation per bit (offset / division), and not two (offset / division and decrement )
EDIT:
Looking through the rest of the implementations, I see that Alec and Anon came up with this coding scheme - using the watchdog bit - before I did it. Anon's solution is particularly interesting, using the Python bin function and separating the "0b" prefix and the protection bit from [3:] , rather than looping, changing, and moving around, as Alec and I did.
As a bonus, this version also handles hyphens ( -....- ), slashes ( -..-. ), -..-. ( ---... ), semicolons ( -.-.-. ), -.-.-. to ( -...- ), but with the sign ( .--.-. ). As long as 8-bit characters are allowed, these characters do not require additional bytes of code to support. No character can be supported with this version without adding length to the code (unless Morse codes have more / less characters).
Since I find that the old implementations are still interesting, and there are some warnings in the text that apply to this version, I left the previous content of this post below.
Well, presumably the user interface can suck, right? So, borrowing from strager , I replaced gets() , which provides buffered echo input, with getch() , which provides unbuffered, unshielded character input. This means that every character you enter is immediately translated into Morse code on the screen. Maybe it's cool. It no longer works with either the stdin argument or the command line, but this is pretty damn small.
I kept the old code below, however, for reference. Here is a new one.
New border checking code, 171 characters:
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 terminates the loop and exits the program.
New code without border checks, 159 characters:
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);}
Following is the old code 196/177 with some explanation:
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);}
This is based on the answer of Andrea Python , using the same method for generating Morse code as in this answer. But instead of storing coding characters one by one and finding their indices, I stored the indices one by one and looked at them by character (similar to my earlier answer ). This prevents lengthy gaps at the end that caused problems for earlier developers.
As before , I used a character that is larger than 127. Converting it to ASCII-only adds 3 characters. The first character of the long string should be replaced with \x9C . An offset is necessary this time, otherwise a large number of characters will be less than 32 and must be represented by escape codes.
As before, processing the command line argument adds 2 characters instead of stdin, and using a real space character between codes adds 1 character.
On the other hand, some of the other routines here do not deal with input outside the valid range [, .0-9 \ A-Za-z]. If such processing was removed from this procedure, then 19 characters can be deleted, resulting in a total of 177 characters. But if this is done, and an invalid input is transferred to this program, it can work and burn.
The code in this case can be:
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);}