import random
import sys

import nltk

KEY_ADJACENCY_LIST_FILE_NAME = 'keys.adj'


# read in key adjacency list
def read_adjacency_list(filename):
    mapping = {}
    with open(filename) as adjacency_list:
        for line in adjacency_list:
            if len(line) > 1:
                keys = line.split()
                mapping[keys[0]] = keys[1:]
    return mapping


def typo(input_text):
    # read in input sentence and tokenize
    tokens = nltk.word_tokenize(input_text)

    # for each word randomly select a letter and then randomly replace it with its adjacent letter
    new_words = []
    for token in tokens:
        letters = list(token)
        length = len(letters)

        selected_index = random.randint(0, length - 1)
        selected_letter = letters[selected_index]

        possible_replacements = KEY_MAPPING[selected_letter.lower()]
        new_letter = random.choice(possible_replacements)
        if selected_letter.isupper():
            new_letter = new_letter.upper()

        letters[selected_index] = new_letter
        word = ''.join(letters)
        new_words.append(word)

    new_text = ' '.join(new_words)
    return new_text


KEY_MAPPING = read_adjacency_list(KEY_ADJACENCY_LIST_FILE_NAME)

print(typo(sys.argv[1]))

@@ -1,12 +1,29 @@
+import itertools%0A
 import rando
@@ -388,27 +388,714 @@
 g%0A%0A%0A
-def typo(input_text
+# finds a replacement letter based on the given key mapping%0Adef get_replacement(character, key_mapping):%0A    possible_replacements = key_mapping%5Bcharacter.lower()%5D%0A    new_letter = random.choice(possible_replacements)%0A    if character.isupper():%0A        new_letter = new_letter.upper()%0A    return new_letter%0A%0A%0A# pairwise function from itertools recipes page%0A# https://docs.python.org/3/library/itertools.html#itertools-recipes%0Adef pairwise(iterable):%0A    %22%22%22s -%3E (s0,s1), (s1,s2), (s2, s3), ...%22%22%22%0A    a, b = itertools.tee(iterable)%0A    next(b, None)%0A    return zip(a, b)%0A%0A%0A# create typos using nltk's tokens%0A# (slower but more flexibility for future augmentation)%0Adef typo_by_token(input_text, key_mapping
 ):%0A 
@@ -1327,27 +1327,30 @@
 ns:%0A        
-let
+charac
 ters = list(
@@ -1377,19 +1377,22 @@
 h = len(
-let
+charac
 ters)%0A%0A 
@@ -1466,20 +1466,27 @@
 ted_
-let
+charac
 ter
+s
  = 
-let
+charac
 ters
@@ -1515,317 +1515,856 @@
     
-possible_replacements = KEY_MAPPING%5Bselected_letter.lower()%5D%0A        new_letter = random.choice(possible_replacements)%0A        if selected_letter.isupper():%0A            new_letter = new_letter.upper()%0A%0A        letters%5Bselected_index%5D = new_letter%0A        word = ''.join(letters)%0A        new_words.append(word)
+new_character = get_replacement(selected_characters, key_mapping)%0A%0A        characters%5Bselected_index%5D = new_character%0A        word = ''.join(characters)%0A        new_words.append(word)%0A%0A    new_text = ' '.join(new_words)%0A    return new_text%0A%0A%0A# create typos using delimiters in the text%0A# (faster but less flexible)%0Adef typo_by_delimiter(input_text, key_mapping, delimiter=' '):%0A    characters = list(input_text)%0A    indices = %5Bindex for index, character in enumerate(characters) if character == delimiter%5D%0A    indices.insert(0, 0)%0A    indices.append(len(characters))%0A%0A    for begin, end in pairwise(indices):%0A        selected_index = random.randint(begin + 1, end - 1)%0A        selected_character = characters%5Bselected_index%5D%0A        new_character = get_replacement(selected_character, key_mapping)%0A        characters%5Bselected_index%5D = new_character
 %0A%0A  
@@ -2377,32 +2377,32 @@
 text = '
- 
 '.join(
-new_word
+character
 s)%0A    r
@@ -2486,30 +2486,101 @@
 ME)%0A
-%0Aprint(typo(sys.argv%5B1%5D)
+old_text = sys.argv%5B1%5D%0Atypoed_text = typo_by_delimiter(old_text, KEY_MAPPING)%0Aprint(typoed_text
 )%0A

add more performant function