Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """CSC108 Assignment 2 functions"""
- from typing import List
- # Used to determine whether to encrypt or decrypt
- ENCRYPT = 'e'
- DECRYPT = 'd'
- def clean_message(message: str) -> str:
- """Return a string with only uppercase letters from message with non-
- alphabetic characters removed.
- >>> clean_message('Hello world!')
- 'HELLOWORLD'
- >>> clean_message("Python? It's my favourite language.")
- 'PYTHONITSMYFAVOURITELANGUAGE'
- >>> clean_message('88test')
- 'TEST'
- """
- # WRITE THE BODY OF clean_message HERE
- clean_string = ""
- for c in message:
- if c.isalpha():
- clean_string = clean_string + c.upper()
- return clean_string
- # WRITE THE REST OF YOUR A2 FUNCTIONS HERE
- def encrypt_letter(letter: str, value: int) -> str:
- """
- Applies keystream value to the letter to encrpyt the letter, and returns the result.
- Parameters:
- letter (str): Single uppercase letter to encrypt
- value (int): Keystream value
- Returns:
- str: The encrypted letter
- """
- return None
- def decrypt_letter(letter: str, value: int) -> str:
- """
- Applies keystream value to the letter to decrpyt the letter, and returns the result.
- Parameters:
- letter (str): Single uppercase letter to decrypt
- value (int): Keystream value
- Returns:
- str: The decrypted letter
- """
- return None
- def is_valid_deck(deck: List[int]) -> bool:
- """
- Checks if a deck is valid (contains every integer from 1 to the number of cards in the deck)
- Parameters:
- deck (List[int]): A candidate deck of cards
- Returns:
- bool: True if the candidate deck is a valid deck of cards
- """
- for i in range(1, len(deck) + 1):
- if deck.count(i) != 1:
- return False
- return True
- def swap_cards(deck: List[int], index: int) -> None:
- """
- Swap the card at an idex with the card after it, treat deck as circular connected
- Parameters:
- deck (List[int]): A candidate deck of cards
- index (int): The index at which to swap with following card
- """
- swap_index = index + 1
- if index == len(deck) - 1:
- swap_index = 0
- temp = deck[swap_index]
- deck[swap_index] = deck[index]
- deck[index] = temp
- return None
- def get_small_joker_value(deck: List[int]) -> int:
- """
- Gets the value of the smaller joker card
- Parameters:
- deck (List[int]): A candidate deck of cards
- Returns:
- int: The value of the small joker
- """
- max = 0
- for i in deck:
- if i > max:
- max = i
- return max - 1
- def get_big_joker_value(deck: List[int]) -> int:
- """
- Gets the value of the big joker card
- Parameters:
- deck (List[int]): A candidate deck of cards
- Returns:
- int: The value of the larger joker
- """
- max = 1
- for i in deck:
- if i > max:
- max = i
- return max
- def move_small_joker(deck: List[int]) -> None:
- """
- Swap the small joker with the following card, treat as circular connected
- Parameters:
- deck (List[int]): A candidate deck of cards
- """
- swap_cards(deck, deck.index(get_small_joker_value(deck)))
- return None
- def move_big_joker(deck: List[int]) -> None:
- """
- Swap the big joker with the following card, treat as circular connected
- Parameters:
- deck (List[int]): A candidate deck of cards
- """
- swap_cards(deck, deck.index(get_big_joker_value(deck)))
- swap_cards(deck, deck.index(get_big_joker_value(deck)))
- return None
- def triple_cut(deck: List[int]) -> None:
- """
- Do a triple cut on the deck
- Parameters:
- deck (List[int]): A candidate deck of cards
- """
- s_j_index = deck.index(get_small_joker_value(deck))
- b_j_index = deck.index(get_big_joker_value(deck))
- f_j_index = s_j_index if s_j_index < b_j_index else b_j_index
- sd_j_index = s_j_index if s_j_index > b_j_index else b_j_index
- if sd_j_index == len(deck) - 1:
- deck[:] = deck[f_j_index:] + deck[:f_j_index]
- elif f_j_index == 0:
- deck[:] = deck[sd_j_index + 1:] + deck[:sd_j_index + 1]
- else:
- deck[:] = deck[sd_j_index+1:] + \
- deck[f_j_index:sd_j_index + 1] + deck[:f_j_index]
- return None
- def insert_top_to_bottom(deck: List[int]) -> None:
- """
- Examine the value of the bottom card and move that many cards from the top of the deck to the bottom, just above the bottom card (If bottom card is big joker, use small joker value as number of cards)
- Parameters:
- deck (List[int]): A candidate deck of cards
- """
- bottom_index = deck[len(deck) - 1]
- if bottom_index == get_big_joker_value(deck):
- bottom_index -= 1
- deck[:] = deck[bottom_index:len(deck)-1] + \
- deck[:bottom_index]+deck[len(deck) - 1: len(deck)]
- return None
- def get_card_at_top_index(deck: List[int]) -> int:
- """
- Using the top value of the card as an index, return the card in the deck at that index (If top card is big joker, use small joker value as index)
- Parameters:
- deck (List[int]): A candidate deck of cards
- Returns:
- int: The value of the top index card
- """
- index = deck[0]
- if get_big_joker_value(deck) == index:
- index = get_small_joker_value(deck)
- return deck[index]
- def get_next_keystream_value(deck: List[int]) -> int:
- """
- Repeats algorithm steps until a valid keystream value is produced
- Parameters:
- deck (List[int]): A candidate deck of cards
- Returns:
- int: Return the valid keystream value
- """
- keystream_value = -1
- while keystream_value < 1 or (keystream_value == get_small_joker_value(deck) or keystream_value == get_big_joker_value(deck)):
- move_small_joker(deck)
- move_big_joker(deck)
- triple_cut(deck)
- insert_top_to_bottom(deck)
- keystream_value = get_card_at_top_index(deck)
- return keystream_value
- def process_messages(deck: List[int], messages: List[str], type: str) -> List[str]:
- """
- Process the encrypted or decrypted messages
- Parameters:
- deck (List[int]): A candidate deck of cards
- message (List[str]): List of unprocessed encrypted or decrypted messages
- type (str): ENCRYPT or DECRYPT
- Returns:
- List[str]: List of processed encrypted or decrypted messages
- """
- result = []
- if type == ENCRYPT:
- for i in range(0, len(messages)):
- message_values = []
- key_values = []
- messages[i] = clean_message(messages[i])
- s = ""
- for j in range(0, len(messages[i])):
- message_values.append(ord(messages[i][j]) - 64)
- key_values.append(get_next_keystream_value(deck))
- char_val = ((message_values[j] + key_values[j]) %
- (len(deck) - 2)) + 64
- if char_val == 64:
- char_val = len(deck) - 2 + 64
- print(char_val-64)
- s += chr(char_val)
- result.append(s)
- if type == DECRYPT:
- for i in range(0, len(messages)):
- message_values = []
- key_values = []
- messages[i] = clean_message(messages[i])
- s = ""
- for j in range(0, len(messages[i])):
- message_values.append(ord(messages[i][j]) - 64)
- key_values.append(get_next_keystream_value(deck))
- char_val = ((message_values[j] - key_values[j]) %
- (len(deck) - 2)) + 64
- if char_val == 64:
- char_val = len(deck) - 2 + 64
- s += chr(char_val)
- result.append(s)
- return result
- # This if statement should always be the last thing in the file, below all of
- # your functions:
- if __name__ == '__main__':
- """Did you know that you can get Python to automatically run and check
- your docstring examples? These examples are called "doctests".
- To make this happen, just run this file! The two lines below do all
- the work.
- For each doctest, Python does the function call and then compares the
- output to your expected result.
- NOTE: your docstrings MUST be properly formatted for this to work!
- In particular, you need a space after each >>>. Otherwise Python won't
- be able to detect the example.
- """
- import doctest
- doctest.testmod()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement