04 Jan 2020 »
smooshed morse code - challenge 1
This challenge was taken from this post and uses the enable1 word list.
Challenge Prompt
For the purpose of this challenge, Morse code represents every letter as a sequence of 1-4 characters, each of which is either .
(dot) or -
(dash). The code for the letter a
is .-
, for b
is -...
, etc. The codes for each letter a through z are:
.- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..
Normally, 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.
Examples
smorse("sos") => "...---..."
smorse("daily") => "-...-...-..-.--"
smorse("programmer") => ".--..-.-----..-..-----..-."
smorse("bits") => "-.....-..."
smorse("three") => "-.....-..."
Note: decoding is ambiguous
Challenges
- The sequence
-...-....-.--.
is the code for four different words (needing
,nervate
,niding
,tiling
). Find the only sequence that’s the code for 13 different words. autotomous
encodes to.-..--------------..-...,
which has 14 dashes in a row. Find the only word that has 15 dashes in a row.- Call a word perfectly balanced if its code has the same number of dots as dashes.
counterdemonstrations
is one of two 21-letter words that’s perfectly balanced. Find the other one. protectorate
is 12 letters long and encodes to.--..-.----.-.-.----.-..--.
, which is a palindrome (i.e. the string is the same when reversed). Find the only 13-letter word that encodes to a palindrome.--.---.---.--
is one of five 13-character sequences that does not appear in the encoding of any word. Find the other four.
Solution
import string
morseList = ".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --.."
morseDict = dict(zip(string.ascii_lowercase, morseList.split()))
wordsDict = {word: encode(word) for word in words}
# function for encoding a given word into a string of morse.
def encode(word):
return(''.join([morseDict[letter] for letter in word]))
print(encode('sos'))
with open('enable1.txt', 'r') as f:
words = [line.rstrip() for line in f.readlines()]
# function for decoding a morse string into possible words.
def decode(query):
return([word for (word, morse) in wordsDict.items() if morse == query])
print(decode('-....--....'))
# prompt 1: Find sequence that is code for n words.
def morseWithNumWords(num):
morseFreq = dict.fromkeys(set(wordsDict.values()), 0)
for word, morse in wordsDict.items():
morseFreq[morse] = 1 + morseFreq.get(morse, 0)
return([morse for morse, freq in morseFreq.items() if num == freq])
print(morseWithNumWords(13)) # '-....--....'
# prompt 2: Find word with n dashes in a row.
def wordWithDashes(dashes):
dashString = '-' * dashes
return([word for (word, morse) in wordsDict.items() if dashString in morse])
print(wordWithDashes(15)) # "bottommost"
# prompt 3: Find words that contain the same number of dots and dashes.
def balanced(chars):
equal = []
words = []
for (word, morse) in wordsDict.items():
if (morse.count('.') == morse.count('-')):
equal.append(word)
for item in equal:
if len(item) == chars:
words.append(item)
return(words)
print(balanced(21)) # [counterdemonstrations, overcommercialization]
# prompt 4: Find morse palindrome with n characters.
def palindrome(chars):
palindrome = []
words = []
for (word, morse) in wordsDict.items():
if (morse == morse[::-1]):
palindrome.append(word)
for item in palindrome:
if len(item) == chars:
words.append(item)
return(words)
print(palindrome(13)) # intransigence
# bonus 5: Find x-character morse sequences that do not appear in encoding of any word.
def missingSequence(chars):
binarySequences = list(range(0, (2 ** chars) + 1)) # find all possible binary representations up to length n
sequences = []
for num in binarySequences:
seq = bin(num).lstrip('0b').replace('1', '-').replace('0', '.') # filter list to n-length binaries and substitute 0,1 for .,-
if len(seq) >= chars:
sequences.append(seq)
for morse in wordsDict.values(): # check if each seq is in morse and remove if it is. (much faster to remove, shortens subsequent array loops)
if len(morse) >= chars:
for seq in sequences:
if seq in morse:
sequences.remove(seq)
return(sequences)
print(missingSequence(13))
# ['--.---.---.--', '--.---.------', '---.---.---.-', '---.---.-----', '---.----.----']