-
Notifications
You must be signed in to change notification settings - Fork 0
/
morse_frequency.py
225 lines (174 loc) · 7.81 KB
/
morse_frequency.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
from datetime import datetime
from translation import MorseCodeTranslator
import os
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
class SortedList:
def __init__(self):
self.head = None
def insert(self, item):
node = Node(item)
if self.head is None or node.data < self.head.data:
node.next = self.head
self.head = node
else:
curr = self.head
while curr.next is not None and curr.next.data < node.data:
curr = curr.next
node.next = curr.next
curr.next = node
def get_list(self):
curr = self.head
items = []
while curr:
items.append(curr.data)
curr = curr.next
return items
def __str__(self):
return ', '.join(str(item) for item in self.get_list())
class keyword:
def __init__(self, word, frequency):
self.word = word
self.frequency = frequency
def __lt__(self, other):
if self.frequency == other.frequency:
return self.word.lower() < other.word.lower()
else:
return self.frequency > other.frequency
def __str__(self):
return "'" + self.word + "': " + str(self.frequency)
class Morse_Frequency:
def __init__(self):
self.current_directory = os.path.dirname(__file__)
#Read the Stop Words
def read_stop_words(self, file_path):
file_path = os.path.join(self.current_directory, file_path)
with open(file_path, 'r') as file:
return file.read().strip().split()
# Count the frequencies of each Morse word
def __count_word_frequencies(self, decoded_morse_text):
word_frequencies = {}
for word in decoded_morse_text.split(): # Split the text into words based on spaces
if word not in word_frequencies:
word_frequencies[word] = 0
word_frequencies[word] += 1
return word_frequencies
# Identify keywords based on a list of stop words
def __identify_keywords(self, word_frequencies, stop_words):
# return the word frequencies that are not in the stop words list
return {word: freq for word, freq in word_frequencies.items() if word.lower() not in stop_words}
# Generate the Morse Word Frequencies Report
def generate_report(self, decoded_morse, stop_words):
if decoded_morse == None:
return None
# Time stamp
timestamp = datetime.now().strftime("%d-%m-%Y %H:%M")
# Decoded morse text
decoded_morse_text_section = "*** Decoded Morse Text\n" + (decoded_morse)
# Count word frequencies
word_frequencies = self.__count_word_frequencies(decoded_morse)
# Group and sort Morse words by frequencies and length of Morse code
sorted_word_frequencies = sorted(word_frequencies.items(), key=lambda x: (x[1], -len(MorseCodeTranslator().encode(x[0])), x[0]))
grouped_word_frequencies = {}
for word, freq in sorted_word_frequencies:
if freq not in grouped_word_frequencies:
grouped_word_frequencies[freq] = []
grouped_word_frequencies[freq].append((word, freq))
# Generate summary section
summary_section = ""
for freq, words in grouped_word_frequencies.items():
summary_section += f"\n*** Morse Words with frequency=> {freq}\n"
for word, _ in words:
if word.lower() in stop_words:
keyword_label = ""
else:
keyword_label = "(*)"
# Convert word to morse code
morse_code = MorseCodeTranslator().encode(word)
summary_section += f"[{morse_code}]=> {word}{keyword_label}\n"
# Identify keywords
keywords = self.__identify_keywords(word_frequencies, stop_words)
# Generate report for keywords sorted by frequency
keywords_section = "*** Keywords sorted by frequency\n"
# sorted_keywords = sorted(keywords.items(), key=lambda x: (-x[1], x[0]))
k = SortedList()
# Populate a list with keyword objects
for word , frequency in keywords.items():
k.insert(keyword(word, frequency))
sorted_keywords = [item.word for item in k.get_list()]
# added in during interview
keyword_frequencies = [item.frequency for item in k.get_list()]
for word, frequency in zip(sorted_keywords, keyword_frequencies):
keywords_section += f"{word}({frequency})\n"
# Combine all sections to form the report
report = f"""\
{"*" * 42}
REPORT GENERATED ON: {timestamp}
{"*" * 42}
{decoded_morse_text_section}
{summary_section}
{keywords_section}
"""
return report
def generate_graph(self, decoded_morse, stop_words, words_linkedlist):
# Time stamp
words_linkedlist.set_list(words_linkedlist) # Update the linked list properly
timestamp = datetime.now().strftime("%d-%m-%Y %H:%M")
# Count word frequencies
word_frequencies = self.__count_word_frequencies(decoded_morse)
# Identify keywords
keywords = self.__identify_keywords(word_frequencies, stop_words)
# Remove words in the linked list that are not in the keywords
words_linkedlist.remove_existence(stop_words) # Pass stop_words to the method
# Sort keywords by frequency
# sorted_keywords = sorted(keywords.items(), key=lambda x: (-x[1], x[0]))
# testing sorted list using sorted list class
l = SortedList()
# Populate a list with keyword objects
for word , frequency in keywords.items():
l.insert(keyword(word, frequency))
keyword_frequencies = [item.frequency for item in l.get_list()]
sorted_keywords = [item.word for item in l.get_list()]
# Construct the graph
graph = f"""\
{"*" * 60}
REPORT GENERATED ON: {timestamp}
{"*" * 60}
"""
graph += self.print_vertical_bars(keyword_frequencies,words_linkedlist,sorted_keywords)
return graph
def print_vertical_bars(self, numbers,words_linkedlist,sorted_keywords):
bar_print = ""
max_height = max(numbers)
num_bars = len(numbers)
total_spaces = 60 - num_bars # base length is fixed at 60
# Calculate the number of spaces between each bar
if num_bars > 1:
space_between_bars = total_spaces // (num_bars)
remaining_spaces = total_spaces % (num_bars - 1)
else:
space_between_bars = 0
remaining_spaces = total_spaces
# Iterate through each position vertically
for i in range(max_height, 0, -1):
# Iterate through each number in the list
for j, num in enumerate(numbers):
if num >= i:
bar_print += "*"
else:
bar_print += " "
# Add extra spaces between bars
if j < num_bars - 1:
num_spaces = space_between_bars + (1 if remaining_spaces > 0 else 0)
bar_print += " " * num_spaces
remaining_spaces -= 1 if remaining_spaces > 0 else 0
# Move to the next line after printing each row
bar_print += "\n"
# Print fixed length base
bar_print += "-" * 60 + "\n"
words_linkedlist.sort_by_keywords(sorted_keywords)
word_print = words_linkedlist.report_generation_method()
graph = bar_print + word_print
return graph