Sinisterly
Programming Challenge - Morse Code Cipher - Printable Version

+- Sinisterly (https://sinister.ly)
+-- Forum: Coding (https://sinister.ly/Forum-Coding)
+--- Forum: Coding (https://sinister.ly/Forum-Coding--71)
+--- Thread: Programming Challenge - Morse Code Cipher (/Thread-Programming-Challenge-Morse-Code-Cipher)

Pages: 1 2


Programming Challenge - Morse Code Cipher - 0xDEAD10CC - 02-24-2014

Objective: write a program that translates plaintext into it's morse code format, and include the ability to convert morse code back to its plaintext form as well.

Requirements:
  • In Morse Code Format:
    1. Each character in morse format must be separated by a single space
    2. Each word must be separated by 7 spaces
    3. You must use the traditional '-' and '.' characters for representation

    [Image: 450px-International_Morse_Code.svg.png]

    Notes:
    1. You only need to be able to translate characters that are defined within the table depicted within this image. (Sorry about the transparent background and dark text.) Other special characters can be found online and are optional.
    2. Character casing does not matter (i.e. the morse code for 'a' is the same as 'A').

Example:
"This is a simple test by 0xDEAD10CC." = "- .... .. ... .. ... .- ... .. -- .--. .-.. . - . ... - -... -.-- ----- -..- -.. . .- -.. .---- ----- -.-. -.-. .-.-.-"


RE: Programming Challenge - Morse Code Cipher - Mushroom Face - 02-24-2014

Will do in the morning. Smile


RE: Programming Challenge - Morse Code Cipher - 0xDEAD10CC - 02-24-2014

I wrote the translation to morse code so far. If I have more time tomorrow after work I'll finish this and post it up. I came up with a method to play the morse code too, but it all needs to be optimized further... I'm already tired so good code isn't going to be produced at this point in time lol. 5AM tomorrow for work again. Smile

[Image: hfkQsCH.png]


RE: Programming Challenge - Morse Code Cipher - Skitstep - 02-24-2014

That's pretty sick man, good job! You need to be given the coder award. :victoire:


RE: Programming Challenge - Morse Code Cipher - Mushroom Face - 02-24-2014

(02-24-2014, 12:47 PM)vιpr Wrote: That's pretty sick man, good job! You need to be given the coder award. :victoire:

Hes doing some beautiful C++, once I get over my hangover I'll prob attempt this.


RE: Programming Challenge - Morse Code Cipher - 0xDEAD10CC - 02-25-2014

I'll post up what I've written so far, I started cleaning it up, but I put an 11 hour day in at work today, so I didn't get home until late. Still room for improvement, and this is neither complete yet... Perhaps it'll give someone else ideas for their submission though:

Code:
#include <iostream> #include <Windows.h> #include <string> #include <sstream> #include <iterator> #include <algorithm> #include <map> namespace morse_code { typedef std::map<char, const char *> MorseCodeMap; // Contains substitution mappings // Reference table for substitutions const char _plaintext[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?'!/()&:;=+-_\"$@"; const char _morsetext[][8] = { // Letters ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", // Digits "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", // Special ".-.-.-", "--..--", "..--..", ".----.", "-.-.--", "-..-.", "-.--.", "-.--.-", ".-...", "---...", "-.-.-.", "-...-", ".-.-.", "-....-", "..--.-", ".-..-.", "...-..-", ".--.-." }; // Translates input text from or to morse code. class MorseCode { public: MorseCode(std::string &inputstring) : _inputstring(inputstring) {} ~MorseCode() {} // Translates the plaintext input into morse code and returns the result. std::string TranslateToMorse() { // Create and initialize morse code map used for substitutions. MorseCodeMap morse_code_map; InitMorseMap(morse_code_map); // Transform all input text to uppercase for easy indexing via the // morse code table and parse words from the full text to be placed in // a vector for easy iterator access. std::vector<std::string> parts; std::transform(_inputstring.begin(), _inputstring.end(), _inputstring.begin(), ::toupper); GetWords(_inputstring, parts); // The constant gap/units between each word by international // morse code standard is 7. const unsigned kWordGap = 7; std::string morse; // Morse code string to be returned. // Iterate through each word appending each character in morse code, // separated by spaces, following a constant gap of 7 spaces after // each word. for (auto &it : parts) { std::for_each(it.begin(), it.end(), [&morse, &morse_code_map](char c) { morse.append(morse_code_map.find(c) == morse_code_map.end() ? " " : morse_code_map[c]).append(1, ' '); }); morse.append(kWordGap - 1, ' '); } return morse.substr(0, morse.length() - kWordGap); } // Translates the morse code input into morse code and returns the result. std::string TranslateFromMorse() { // TODO std::string morse; return morse; } // Plays the morse code string through a series of beeps. static void PlayMorseString(std::string &morse, int lowfreq, int highfreq, int delay) { // Use a const iterator for each char in the morse code string to check // whether a high or low beep is produced. A minimal frequency is used for // all parts that are not morse code. for (const auto &it : morse) { if (it == ' ') { Beep(37, delay); continue; } Beep(it == '.' ? lowfreq : highfreq, delay); } } private: std::string _inputstring; // Input string initialized by the constructor. // Populates the referenced (STL) vector container with the words // from the input string. void GetWords(std::string &s, std::vector<std::string> &words) { std::istringstream isstrm(s); std::copy( std::istream_iterator<std::string>(isstrm), std::istream_iterator<std::string>(), std::back_inserter<std::vector<std::string>>(words) ); } // Initializes the referenced morese code map container with the // morse code translation table. void InitMorseMap(MorseCodeMap &morse_code_map) { // The total number of stored substitution values for morse code. int max = sizeof(_morsetext) / sizeof(_morsetext[0]); for (int i = 0; i < max; ++i) morse_code_map[_plaintext[i]] = _morsetext[i]; } }; // MorseCode Class } // morse_code Namespace // ---------------------------------------------------------------------------------------------------- int main() { std::string original("Test by 0xDEAD10CC."); morse_code::MorseCode morse(original); std::string morse_string = morse.TranslateToMorse(); std::cout << morse_string << std::endl; // morse::MorseCode::PlayMorseString(morse_string, 750, 1025, 200); }



RE: Programming Challenge - Morse Code Cipher - Shebang - 02-26-2014

I'll post my response, it's the whole reason I joined :whistle: I'm waiting for some sort of criticism for using VB.NET..

Anyways, here are my variables:
[Image: fS.png]

Here's what the MorseDict class looks like:
[Image: mS.png]

Creating the dictionary:
[Image: nS.png]

Here's the code for converting to morse:
[Image: hS.png]

Here's the code for converting from morse:
[Image: iS.png]

Here it is working:
[Image: jS.png][Image: kS.png]

And finally, here's the source: http://pastebin.com/rjPDkMNF
If you're interested, here's the program: Download (13KB) | Virus Scan (1/47) <-- Not sure how that happened.


RE: Programming Challenge - Morse Code Cipher - 0xDEAD10CC - 02-27-2014

My little bit for criticism for that code is less about it being written in VB.NET...

To start off with my feedback though, 'Dictionary' was a bit confusing to me at first until I saw that it was the generic List<T> and not the Dictionary<Tkey, Tvalue> collection. And on that note, I don't know why you're not using a Dictionary for that reason, it would eliminate that MorseDict user defined type, and make it completely useless and redundant...

My second point would be related to the fact that you're using a string and a string, instead of a char which is mapped to a string. 'A'-'Z' and '0'-'9' don't have to be strings, why construct a string object for that? They're all one character in length.

The other thing would be how you cast a string to a character array--You can index chars with the String type already as though it was an explicitly defined char array. A String just has more functions available to it, because it's a class, not an array, and the indexer is overloaded to grab a char out of the string itself.

If you used a Dictionary though, lots of that looping would become redundant as well.

No criticism about VB.NET in specific, I really don't care, my preference is C# though for a much more succinct syntax. Both compile to relatively the same thing though.

Good to see this thread is getting activity though. Keep up the good work, the only other thing I'd mention is that you should adopt some better naming conventions. Don't be so vague, and stay away from common words as Dictionary has another meaning when System.Collections is referenced. You'll find more about naming conventions on MSDN, but I'm not a fan of that Pascal Casing style for certain identifiers in your code that *should* be in Camel Casing instead.

Let me just show you an example:
Code:
Dictionary<char, string> morseMap = 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', "----."} }; string plainText = "This is a simple test by 0xDEAD10CC"; StringBuilder sb = new StringBuilder(); foreach (var c in plainText) { if (c == ' ') { sb.Append(' ', 6); // minus 1 space because all other chars are padded with a space anyways continue; } // You can do whatever for a value which can't be mapped to morse code char upperChar = char.ToUpper(c); sb.AppendFormat("{0} ", morseMap.ContainsKey(upperChar) ? morseMap[upperChar] : "?????"); } Console.WriteLine(sb);

I guess you could even use char.IsWhiteSpace() in replace of checking for a ' ', but this would also check tabs for instance...

A LINQ demo as well:
Code:
string plainText = "This is a simple test by 0xDEAD10CC"; Console.WriteLine(string.Join( new string(' ', 7), plainText.Split(' ').Select(w => string.Join(" ", w.Select(c => morseMap.ContainsKey(char.ToUpper(c)) ? morseMap[char.ToUpper(c)] : "????"))) ) );



RE: Programming Challenge - Morse Code Cipher - Shebang - 02-27-2014

(02-27-2014, 03:26 AM)0xDEAD10CC Wrote: My little bit for criticism for that code is less about it being written in VB.NET...

To start off with my feedback though, 'Dictionary' was a bit confusing to me at first until I saw that it was the generic List<T> and not the Dictionary<Tkey, Tvalue> collection. And on that note, I don't know why you're not using a Dictionary for that reason, it would eliminate that MorseDict user defined type, and make it completely useless and redundant...

My second point would be related to the fact that you're using a string and a string, instead of a char which is mapped to a string. 'A'-'Z' and '0'-'9' don't have to be strings, why construct a string object for that? They're all one character in length.

The other thing would be how you cast a string to a character array--You can index chars with the String type already as though it was an explicitly defined char array. A String just has more functions available to it, because it's a class, not an array, and the indexer is overloaded to grab a char out of the string itself.

If you used a Dictionary though, lots of that looping would become redundant as well.

No criticism about VB.NET in specific, I really don't care, my preference is C# though for a much more succinct syntax. Both compile to relatively the same thing though.

Good to see this thread is getting activity though. Keep up the good work, the only other thing I'd mention is that you should adopt some better naming conventions. Don't be so vague, and stay away from common words as Dictionary has another meaning when System.Collections is referenced. You'll find more about naming conventions on MSDN, but I'm not a fan of that Pascal Casing style for certain identifiers in your code that *should* be in Camel Casing instead.

Let me just show you an example:
Code:
Dictionary<char, string> morseMap = 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', "----."} }; string plainText = "This is a simple test by 0xDEAD10CC"; StringBuilder sb = new StringBuilder(); foreach (var c in plainText) { if (c == ' ') { sb.Append(' ', 6); // minus 1 space because all other chars are padded with a space anyways continue; } // You can do whatever for a value which can't be mapped to morse code char upperChar = char.ToUpper(c); sb.AppendFormat("{0} ", morseMap.ContainsKey(upperChar) ? morseMap[upperChar] : "?????"); } Console.WriteLine(sb);

I guess you could even use char.IsWhiteSpace() in replace of checking for a ' ', but this would also check tabs for instance...

A LINQ demo as well:
Code:
string plainText = "This is a simple test by 0xDEAD10CC"; Console.WriteLine(string.Join( new string(' ', 7), plainText.Split(' ').Select(w => string.Join(" ", w.Select(c => morseMap.ContainsKey(char.ToUpper(c)) ? morseMap[char.ToUpper(c)] : "????"))) ) );

Thanks for the criticism (literally)! It's a nice change to being chewed out for an inferior language. I'll be completely honest: I had nno clue there was a Dictionary object I could use, would have been much easier if I knew that. The reason I made a custom object is because it's pretty topical in my AP CS course in high school (We use Java), so it was the first thing that came to mind. I also converted to a char array because I felt (at least in the moment) it would be easier to just ForEach through it. I have no explanation for the NormalText property being a Char, poor planning on my part. The bad variable naming was due to laziness, no excuse there.

I like that you posted a programming challenge, it's what made me sign up! I might post some from a contest I was involved in a few days ago. I did pretty well on it considering I had to leave halfway through to go to work. It'd be nice to see what it would look like in C++, as I don't think I'm competent enough in it to do these myself.


RE: Programming Challenge - Morse Code Cipher - 0xDEAD10CC - 02-28-2014

I can help you out further, there's nothing truly wrong with creating your own class to encapsulate the data, but why exclude the functionality from the implementation? The beauty of a class is defined by both of these; functionality, AND data. For instance, add the implementation:

Code:
class MorseCodeConverter { Dictionary<char, string> morseMap = 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', "----."} }; public string this[char key] { get { char c = char.ToUpper(key); if (morseMap.ContainsKey(c)) return morseMap[c]; return "????"; } } public char this[string val] { get { if (morseMap.ContainsValue(val)) return morseMap.First(kv => kv.Value.Equals(val, StringComparison.OrdinalIgnoreCase)).Key; return '?'; } } }

Very easy usage:
Code:
MorseCodeConverter morseCodeConverter = new MorseCodeConverter(); Console.WriteLine(morseCodeConverter[".-"]); // Writes out "A" Console.WriteLine(morseCodeConverter['A']); // Writes out ".-"

You could include TryParseMorse() methods for instance to allow the user to parse and see if the result is usable or not even... You can do many things with this, the whole point of a class is not limited to what you demonstrate it as being capable of or useful for, unless we're talking about a very limited idea of a class here.