I'm completed the Reddit challenge #380 (source).
Here is an abbreviated description:
Normally [in Morse code], you would indicate where one letter ends and the next begins, for instance with a space between the letters' codes, but for this challenge, just smoosh all the coded letters together into a single string consisting of only dashes and dots.
An obvious problem with this system is that decoding is ambiguous. For instance, both
bits
andthree
encode to the same string, so you can't tell which one you would decode to without more information.
I've done the best I can, but wanted a few insights to what I could do that would be better.
Code
The code is the solution to the Reddit challenge. In the main method, the class is initialised then prints each of the solutions out. Please note that the main challenge and optional challenges 1-4 are included. I did not include optional challenge 5. The class on initialisation converts and groups the words from a file 'wordlist.txt' that was sourced in the reddit post. I will not include the file here as it is pretty long but here is the source. Please ensure you rename the file to 'wordlist.txt'.
Unorthodox choices
morse_alphabet
variablePyLint highlighted it as a 'line-too-long' exception. I disabled it since shorting the variable name would not have helped but I'm unsure if I should have split up the line. I kept it there as it was easier than typing it out for each individual letter but maybe it was best to split up the letters?
count_longest_dash_run function
It seems like it was an unorthodox solution, maybe there was a way to do this without the comparison?
The line repeated in the optional challenges
print(key+":"+str(value))
Should I have separated it into a function or would it have been overkill?
Documentation
I'm unsure if the documentation, usually people put in return type or parameter information but i'm unsure what it should look like or if what i'm doing is correct.
Static methods and class methods
Should I include
@typemethod
for all the functions or is this specific to certain situations such as the static method?
Python Code
"""
This module is a solution the the programming exercise found on reddit.
Exercise:
https://www.reddit.com/r/dailyprogrammer/comments/cmd1hb/20190805_challenge_380_easy_smooshed_morse_code_1/
This solution is not posted in the reddit thread.
This solution completes the challenge and the optional challenges 1-4.
On running this script, you should see the results with the console.
Each set of results will be labeled with which challenge they refer to.
"""
class Morsecoder:
"""
This class handles generating the morse code for all of the words listed in the wordlist.txt
and storing them. It also handles generating the result for each challenge.
"""
def __init__(self):
""" Create a list of words and its morse code.
Also creates a dict compiling the words with the same more code together. """
# pylint: disable=line-too-long
morse_alphabet = ".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --.."
self.morse_characters = morse_alphabet.split(" ")
self.words = []
self.encoded_words = {}
self.encode_word_list()
self.find_matching_codes()
def get_morse_character(self, char):
""" Retrieves the morse character of the character.
Return none is the character int is not int the lower case range. """
char_int = ord(char)-97
if char_int >= len(self.morse_characters) or char_int < 0:
return None
return self.morse_characters[char_int]
def encode_string(self, string):
""" Encodes the entire string into the morse code.
Raises an Exception if the string is not a lowercase alphabet only string. """
if string.islower() and string.isalpha():
morsecode = ''
for char in string:
morsecode += self.get_morse_character(char)
return morsecode
ex = "'"+string+"' could not be converted."
ex += "The string must only contain lowercase alphabet characters"
raise Exception(ex)
def encode_word_list(self):
""" Reads the wordlist.txt file and encodes each line into morse code.
The original word and the morse code is stored within the words variables. """
with open("wordlist.txt", 'r') as file:
content = file.readlines()
content = [x.strip() for x in content]
for word in content:
encoded = self.encode_string(word)
self.words.append([word, encoded])
def find_matching_codes(self):
""" Find morse codes that are the same and groups the words under the morse code. """
for word, encoded in self.words:
if encoded in self.encoded_words:
self.encoded_words[encoded].append(word)
else:
self.encoded_words[encoded] = [word]
@staticmethod
def count_longest_dash_run(string):
""" static method that count the number of '-' in a row and retrieved the
number of the longest '-' in a row within the string. """
dashruns = string.split('.')
longest_dash_run = 0
for dashrun in dashruns:
length = len(dashrun)
if length > longest_dash_run:
longest_dash_run = length
return longest_dash_run
@staticmethod
def is_palindrome(word):
""" static method that checks if the word is a palindrome. """
return word == word[::-1]
def challenge(self):
""" prints out the result of the challenge. """
print("Challenge Result:")
print(self.encode_string("sos"))
print(self.encode_string("daily"))
print(self.encode_string("programmer"))
print(self.encode_string("bits"))
print(self.encode_string("three"))
def optional_challenge_one(self):
""" prints out the result of the first optional challenge. """
print("Optional Challenge One Result:")
for key in self.encoded_words:
value = self.encoded_words[key]
if len(value) >= 13:
print(key+":"+str(value))
def optional_challenge_two(self):
""" prints out the result of the second optional challenge. """
print("Optional Challenge Two Result:")
for key in self.encoded_words:
value = self.encoded_words[key]
if self.count_longest_dash_run(key) == 15:
print(key+":"+str(value))
def optional_challenge_three(self):
""" prints out the result of the third optional challenge. """
print("Optional Challenge Three Result:")
selected = {}
for pair in self.words:
word = pair[0]
encoded = pair[1]
if len(word) == 21:
selected[encoded] = word
for key in selected:
if key.count('.') == key.count('-'):
value = selected[key]
print(key+":"+str(value))
def optional_challenge_four(self):
""" prints out the result of the fourth optional challenge. """
print("Optional Challenge Four Result:")
for pair in self.words:
key = pair[0]
value = pair[1]
if len(key) == 13:
if self.is_palindrome(value):
print(str(value)+":"+key)
if __name__ == "__main__":
CODER = Morsecoder()
CODER.challenge()
CODER.optional_challenge_one()
CODER.optional_challenge_two()
CODER.optional_challenge_three()
CODER.optional_challenge_four()