From 7fa5ad451bacbf9995538d78b30caa5f1d0d6e28 Mon Sep 17 00:00:00 2001 From: Cur1e Date: Sun, 30 Nov 2025 16:43:41 +0700 Subject: [PATCH 1/5] up to build_shift_dict --- exercise/ps4b.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/exercise/ps4b.py b/exercise/ps4b.py index 4e5e101..5e538d2 100644 --- a/exercise/ps4b.py +++ b/exercise/ps4b.py @@ -1,7 +1,7 @@ # Problem Set 4B -# Name: +# Name: Thai Hong Curi # Collaborators: -# Time Spent: x:xx +# Time Spent: 0:40 import string @@ -70,7 +70,14 @@ def __init__(self, text): self.message_text (string, determined by input text) self.valid_words (list, determined using helper function load_words) ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + self.message_text = text + text_copy = text[:] + self.valid_words = list() + words = list(text_copy.split()) + for word in words: + if is_word(word_list=WORDLIST_FILENAME, word=word): + self.valid_words.append(word) def get_message_text(self): ''' @@ -78,7 +85,8 @@ def get_message_text(self): Returns: self.message_text ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + return self.message_text[:] def get_valid_words(self): ''' @@ -87,7 +95,8 @@ def get_valid_words(self): Returns: a COPY of self.valid_words ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + return self.valid_words[:] def build_shift_dict(self, shift): ''' @@ -104,6 +113,12 @@ def build_shift_dict(self, shift): another letter (string). ''' pass #delete this line and replace with your code here + mapping = dict() + for i in range(26): + mapping[chr(ord('A')+i)] = chr(ord('A') + i + shift) if ord('A') + i + shift <= ord('Z') else chr(ord('A') + i + shift - 26) + mapping[chr(ord('a')+i)] = chr(ord('a') + i + shift) if ord('a') + i + shift <= ord('z') else chr(ord('a') + i + shift - 26) + return mapping + def apply_shift(self, shift): ''' From 1f98fd9c88dc1d4c7966f2ba6992768034fb8a79 Mon Sep 17 00:00:00 2001 From: Cur1e Date: Mon, 1 Dec 2025 15:19:41 +0700 Subject: [PATCH 2/5] Finished ps4b --- exercise/ps4b.py | 104 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 24 deletions(-) diff --git a/exercise/ps4b.py b/exercise/ps4b.py index 5e538d2..8691776 100644 --- a/exercise/ps4b.py +++ b/exercise/ps4b.py @@ -58,6 +58,7 @@ def get_story_string(): ### END HELPER CODE ### WORDLIST_FILENAME = 'words.txt' +wordlist = load_words(WORDLIST_FILENAME) class Message(object): def __init__(self, text): @@ -75,8 +76,9 @@ def __init__(self, text): text_copy = text[:] self.valid_words = list() words = list(text_copy.split()) + for word in words: - if is_word(word_list=WORDLIST_FILENAME, word=word): + if is_word(wordlist, word=word): self.valid_words.append(word) def get_message_text(self): @@ -112,7 +114,7 @@ def build_shift_dict(self, shift): Returns: a dictionary mapping a letter (string) to another letter (string). ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here mapping = dict() for i in range(26): mapping[chr(ord('A')+i)] = chr(ord('A') + i + shift) if ord('A') + i + shift <= ord('Z') else chr(ord('A') + i + shift - 26) @@ -132,7 +134,22 @@ def apply_shift(self, shift): Returns: the message text (string) in which every character is shifted down the alphabet by the input shift ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + letter = list() + mapping = self.build_shift_dict(shift) + + for char in self.message_text: + letter.append(char) + + for i in range(len(letter)): + if ord('A') <= ord(letter[i]) <= ord('Z') or ord('a') <= ord(letter[i]) <= ord('z'): + letter[i] = mapping[letter[i]] + else: + continue + + shifted = ''.join(letter) + return shifted + class PlaintextMessage(Message): def __init__(self, text, shift): @@ -150,7 +167,11 @@ def __init__(self, text, shift): self.message_text_encrypted (string, created using shift) ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + Message.__init__(self, text) + self.shift = shift + self.encryption_dict = self.build_shift_dict(shift) + self.message_text_encrypted = self.apply_shift(shift) def get_shift(self): ''' @@ -158,7 +179,8 @@ def get_shift(self): Returns: self.shift ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + return self.shift def get_encryption_dict(self): ''' @@ -166,15 +188,17 @@ def get_encryption_dict(self): Returns: a COPY of self.encryption_dict ''' - pass #delete this line and replace with your code here - + #delete this line and replace with your code here + return self.encryption_dict.copy() + def get_message_text_encrypted(self): ''' Used to safely access self.message_text_encrypted outside of the class Returns: self.message_text_encrypted ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + return self.message_text_encrypted def change_shift(self, shift): ''' @@ -186,13 +210,16 @@ def change_shift(self, shift): Returns: nothing ''' - pass #delete this line and replace with your code here - + #delete this line and replace with your code here + self.shift = shift + self.encryption_dict = self.build_shift_dict(shift) + self.message_text_encrypted = self.apply_shift(shift) + return class CiphertextMessage(Message): def __init__(self, text): ''' - Initializes a CiphertextMessage object + Initializes a Ciph ertextMessage object text (string): the message's text @@ -200,7 +227,8 @@ def __init__(self, text): self.message_text (string, determined by input text) self.valid_words (list, determined using helper function load_words) ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + Message.__init__(self, text) def decrypt_message(self): ''' @@ -218,22 +246,50 @@ def decrypt_message(self): Returns: a tuple of the best shift value used to decrypt the message and the decrypted message text using that shift value ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + total_count = dict() + + for shift in range(26): + shifted_text = self.apply_shift(shift) + shifted_words = shifted_text.split() + count = 0 + for word in shifted_words: + if is_word(wordlist, word=word): + count += 1 + total_count[shift] = count + + max_count = 0 + for i in range(len(total_count)): + if total_count[i] > max_count: + max_count = total_count[i] + + for k, v in total_count.items(): + if v == max_count: + break + + riu_shift = k + final_shifted_text = self.apply_shift(riu_shift) + return (riu_shift, final_shifted_text) + + + if __name__ == '__main__': -# #Example test case (PlaintextMessage) -# plaintext = PlaintextMessage('hello', 2) -# print('Expected Output: jgnnq') -# print('Actual Output:', plaintext.get_message_text_encrypted()) -# -# #Example test case (CiphertextMessage) -# ciphertext = CiphertextMessage('jgnnq') -# print('Expected Output:', (24, 'hello')) -# print('Actual Output:', ciphertext.decrypt_message()) + #Example test case (PlaintextMessage) + plaintext = PlaintextMessage('hello', 2) + print('Expected Output: jgnnq') + print('Actual Output:', plaintext.get_message_text_encrypted()) - #TODO: WRITE YOUR TEST CASES HERE + #Example test case (CiphertextMessage) + ciphertext = CiphertextMessage('jgnnq') + print('Expected Output:', (24, 'hello')) + print('Actual Output:', ciphertext.decrypt_message()) + #TODO: WRITE YOUR TEST CASES HERE + encryp_story = CiphertextMessage(get_story_string()) + print('Actual Output:', encryp_story.decrypt_message()) + #TODO: best shift value and unencrypted story - pass #delete this line and replace with your code here + #delete this line and replace with your code here From 5557630e7fd1171d9d54689c00cadb295648625d Mon Sep 17 00:00:00 2001 From: Cur1e Date: Wed, 3 Dec 2025 15:12:37 +0700 Subject: [PATCH 3/5] decrypt left --- exercise/ps4b.py | 4 ++-- exercise/ps4c.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/exercise/ps4b.py b/exercise/ps4b.py index 8691776..fda285f 100644 --- a/exercise/ps4b.py +++ b/exercise/ps4b.py @@ -1,7 +1,7 @@ # Problem Set 4B # Name: Thai Hong Curi # Collaborators: -# Time Spent: 0:40 +# Time Spent: 2:40 import string @@ -292,4 +292,4 @@ def decrypt_message(self): #TODO: best shift value and unencrypted story - #delete this line and replace with your code here + # delete this line and replace with your code here diff --git a/exercise/ps4c.py b/exercise/ps4c.py index 1ceb239..c463210 100644 --- a/exercise/ps4c.py +++ b/exercise/ps4c.py @@ -1,5 +1,5 @@ # Problem Set 4C -# Name: +# Name: Thai Hong Curi # Collaborators: # Time Spent: x:xx From 4d2fff8195e511f13cb3d62c4bc52e9302a6bce9 Mon Sep 17 00:00:00 2001 From: Cur1e Date: Wed, 3 Dec 2025 19:11:49 +0700 Subject: [PATCH 4/5] Finished ps4c --- exercise/ps4c.py | 101 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 16 deletions(-) diff --git a/exercise/ps4c.py b/exercise/ps4c.py index c463210..753e1d2 100644 --- a/exercise/ps4c.py +++ b/exercise/ps4c.py @@ -4,7 +4,8 @@ # Time Spent: x:xx import string -from ps4a import get_permutations +from numba import njit, prange +from itertools import permutations ### HELPER CODE ### def load_words(file_name): @@ -59,6 +60,9 @@ def is_word(word_list, word): CONSONANTS_LOWER = 'bcdfghjklmnpqrstvwxyz' CONSONANTS_UPPER = 'BCDFGHJKLMNPQRSTVWXYZ' +wordlist = load_words(WORDLIST_FILENAME) + + class SubMessage(object): def __init__(self, text): ''' @@ -70,7 +74,15 @@ def __init__(self, text): self.message_text (string, determined by input text) self.valid_words (list, determined using helper function load_words) ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + self.message_text = text + text_copy = text[:] + self.valid_words = list() + words = list(text_copy.split()) + + for word in words: + if is_word(wordlist, word=word): + self.valid_words.append(word) def get_message_text(self): ''' @@ -78,8 +90,9 @@ def get_message_text(self): Returns: self.message_text ''' - pass #delete this line and replace with your code here - + #delete this line and replace with your code here + return self.message_text + def get_valid_words(self): ''' Used to safely access a copy of self.valid_words outside of the class. @@ -87,8 +100,11 @@ def get_valid_words(self): Returns: a COPY of self.valid_words ''' - pass #delete this line and replace with your code here - + + #delete this line and replace with your code here + return self.valid_words.copy() + + def build_transpose_dict(self, vowels_permutation): ''' vowels_permutation (string): a string containing a permutation of vowels (a, e, i, o, u) @@ -108,10 +124,20 @@ def build_transpose_dict(self, vowels_permutation): Returns: a dictionary mapping a letter (string) to another letter (string). ''' - - pass #delete this line and replace with your code here + lower_perm = vowels_permutation[:] + upper_perm = vowels_permutation[:].upper() + #delete this line and replace with your code here + mapping = dict() + for i in range(26): + mapping[chr(ord('A')+i)] = chr(ord('A') + i) + mapping[chr(ord('a')+i)] = chr(ord('a') + i) + for i in range(5): + mapping[VOWELS_LOWER[i]] = lower_perm[i] + mapping[VOWELS_UPPER[i]] = upper_perm[i] + + return mapping - def apply_transpose(self, transpose_dict): + def apply_transpose(self, vowels_perm): ''' transpose_dict (dict): a transpose dictionary @@ -119,8 +145,22 @@ def apply_transpose(self, transpose_dict): on the dictionary ''' - pass #delete this line and replace with your code here - + #delete this line and replace with your code here + letter = list() + mapping = self.build_transpose_dict(vowels_perm) + + for char in self.message_text: + letter.append(char) + + for i in range(len(letter)): + if ord('A') <= ord(letter[i]) <= ord('Z') or ord('a') <= ord(letter[i]) <= ord('z'): + letter[i] = mapping[letter[i]] + else: + continue + + transposed = ''.join(letter) + return transposed + class EncryptedSubMessage(SubMessage): def __init__(self, text): ''' @@ -132,7 +172,8 @@ def __init__(self, text): self.message_text (string, determined by input text) self.valid_words (list, determined using helper function load_words) ''' - pass #delete this line and replace with your code here + #delete this line and replace with your code here + SubMessage.__init__(self, text) def decrypt_message(self): ''' @@ -153,18 +194,46 @@ def decrypt_message(self): Hint: use your function from Part 4A ''' pass #delete this line and replace with your code here - + list_of_perm =['aeiou']+[''.join(vow) for vow in permutations(VOWELS_LOWER)] + total_count = dict() + + for perm in list_of_perm: + transposed_text = self.apply_transpose(perm) + transposed_words = transposed_text.split() + count = 0 + for word in transposed_words: + if is_word(wordlist, word=word): + count += 1 + total_count[perm] = count + + max_count = 0 + for k, v in total_count.items(): + if v > max_count: + max_count = v + + for k, v in total_count.items(): + if v == max_count: + break + + riu_transpose = k + final_transposed_text = self.apply_transpose(riu_transpose) + return (riu_transpose, final_transposed_text) + + if __name__ == '__main__': # Example test case message = SubMessage("Hello World!") permutation = "eaiuo" - enc_dict = message.build_transpose_dict(permutation) print("Original message:", message.get_message_text(), "Permutation:", permutation) print("Expected encryption:", "Hallu Wurld!") - print("Actual encryption:", message.apply_transpose(enc_dict)) - enc_message = EncryptedSubMessage(message.apply_transpose(enc_dict)) + print("Actual encryption:", message.apply_transpose(permutation)) + enc_message = EncryptedSubMessage(message.apply_transpose(permutation)) print("Decrypted message:", enc_message.decrypt_message()) #TODO: WRITE YOUR TEST CASES HERE + mes = EncryptedSubMessage('i am gay') + print(mes.decrypt_message()) + mes = EncryptedSubMessage('u im goy') + print(mes.decrypt_message()) \ No newline at end of file From a217ebe2a8514d64f88a83e39dad2d80c135f648 Mon Sep 17 00:00:00 2001 From: Cur1e Date: Thu, 4 Dec 2025 17:29:08 +0700 Subject: [PATCH 5/5] Minor change --- exercise/ps4c.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercise/ps4c.py b/exercise/ps4c.py index 753e1d2..a52205c 100644 --- a/exercise/ps4c.py +++ b/exercise/ps4c.py @@ -233,7 +233,7 @@ def decrypt_message(self): print("Decrypted message:", enc_message.decrypt_message()) #TODO: WRITE YOUR TEST CASES HERE - mes = EncryptedSubMessage('i am gay') + mes = EncryptedSubMessage('i am goy') print(mes.decrypt_message()) mes = EncryptedSubMessage('u im goy') print(mes.decrypt_message()) \ No newline at end of file