Сборник. Сборник упражнений
Скачать 1.68 Mb.
|
Глава 13 Списки Упражнение 110. Порядок сортировки ## # Выводим числа, введенные пользователем, в порядке возрастания # # Начинаем с пустого списка data = [] # Считываем значения и добавляем их в список, пока пользователь не введет ноль num = int(input("Введите целое число (0 для окончания ввода): ")) while num != 0: data.append(num) num = int(input("Введите целое число (0 для окончания ввода): ")) # Сортируем значения data.sort() Вызов метода sort применительно к списку переставляет значения в нем, располагая их в нужном нам порядке. В данном случае этот способ подходит, поскольку нам нет необходимости сохранять копию исходного списка. Для создания копии исходного списка с отсортированными элементами можно воспользоваться функцией sorted. Вызов этой функции не оказывает влияния на порядок следования элементов в ис- ходном списке, а значит, ее стоит использовать, когда в дальнейшем вам пригодятся обе версии списка: исходный и отсортированный в нужном вам порядке. # Выводим числа в порядке возрастания print("Введенные числа в порядке возрастания:") for num in data: print(num) Упражнение 112. Удаляем выбросы ## # Удаляем выбросы из набора данных # Списки 203 ## Удаляем выбросы из списка значений # @param data – список значений для обработки # @param num_outliers – количество наименьших и наибольших элементов для удаления # @return копия исходного списка с отсортированными значениями и # удаленными наименьшими и наибольшими элементами def removeOutliers(data, num_outliers): # Создаем копию списка с отсортированными значениями retval = sorted(data) # Удаляем num_outliers наибольших значений for i in range(num_outliers): retval.pop() # Удаляем num_outliers наименьших значений for i in range(num_outliers): retval.pop(0) # Возвращаем результат return retval # Запрашиваем данные у пользователя и удаляем по два наибольших и наименьших значения def main(): # Запрашиваем данные у пользователя, пока он не оставит ввод пустым values = [] s=input("Введите значение (Enter для окончания ввода): ") while s != "": num = float(s) values.append(num) s = input("Введите значение (Enter для окончания ввода): ") # Отображаем результат или соответствующее сообщение об ошибке if len(values) < 4: print("Вы ввели недостаточное количество чисел.") else: print("Список с удаленными выбросами: ", \ removeOutliers(values, 2)) print("Исходный список: ", values) # Вызов основной функции main() Упражнение 113. Избавляемся от дубликатов ## # Считываем ряд слов, введенных пользователем, и выводим их без дубликатов # в том же порядке, в котором они были введены # # Запрашиваем слова у пользователя и сохраняем их в список words = [] Наибольшие и наименьшие значе- ния в списке можно было удалить и в одном цикле. В данном случае используется два цикла, чтобы ре- шение было более понятным. 204 Решения word = input("Введите слово (Enter для окончания ввода): ") while word != "": # Добавляем слово в список, только если # оно уже не присутствует в нем if word not in words: words.append(word) # Запрашиваем следующее слово у пользователя word = input("Введите слово (Enter для окончания ввода): ") # Отображаем уникальные слова for word in words: print(word) Упражнение 114. Отрицательные, положительные и нули ## # Запрашиваем коллекцию целых чисел у пользователя. Отображаем сначала отрицательные, # затем нули и после этого положительные # # Создаем три списка для хранения отрицательных, нулевых и положительных значений negatives = [] zeros = [] positives = [] В данном решении используется отдельный список для хранения введенных поль- зователем нулей. Но в этом нет особой необходимости, поскольку нули все одинако- вые. Достаточно было бы хранить количество введенных пользователем нулей и при выводе отображать их столько, сколько надо. # Запрашиваем числа у пользователя, помещая их в соответствующие списки line = input("Введите целое число (Enter для окончания ввода): ") while line != "": num = int(line) if num < 0: negatives.append(num) elif num > 0: positives.append(num) else: zeros.append(num) # Запрашиваем следующее число у пользователя line = input("Введите целое число (Enter для окончания ввода): ") # Выводим сначала отрицательные числа, затем нули и после этого положительные print("Введенные числа: ") for n in negatives: Выражения word not in words и not (word in words) эквивалентны. Списки 205 print(n) for n in zeros: print(n) for n in positives: print(n) Упражнение 116. Совершенные числа ## # Целое число n называется совершенным, если сумма всех его собственных делителей # равна самому числу n # Покажем все совершенные числа от 1 до LIMIT. # from proper_divisors import properDivisors LIMIT = 10000 ## Определяем, является ли число совершенным # @param n – число, которое необходимо проверить на совершенство # @return True, если число совершенно, иначе False def isPerfect(n): # Получим список собственных # делителей числа divisors = properDivisors(n) # Рассчитываем их сумму total = 0 for d in divisors: total = total + d # Определяем, является ли число совершенным, и возвращаем результат if total == n: return True return False # Отображаем все совершенные числа от 1 до LIMIT. def main(): print("Совершенные числа от 1 до", LIMIT, ":") for i in range(1, LIMIT + 1): if isPerfect(i): print(" ", i) #Call the main function main() Упражнение 120. Форматирование списка ## # Отображаем перечень введенных слов через запятую и с союзом "и" между # последними двумя словами # Сумма элементов списка также может быть вычислена при помощи функции sum языка Python. Это позволит избежать написания цикла и сократить операцию до одной строки. 206 Решения ## Форматируем список с запятыми и союзом "и" #@param items – список элементов для форматирования #@return строка с установленными правилами форматирования def formatList(items): # Отдельно рассматриваем пустой список и список из одного элемента if len(items) == 0: return "<пусто>" if len(items) == 1: return str(items[0]) # Идем по всем элементам списка, за исключением двух последних result = "" for i in range(0, len(items) – 2): result = result + str(items[i]) + ", " Каждый введенный элемент мы явным образом преобразуем в строку путем вызова функции str перед выполнением форматирования. Это позволит функции formatList корректно обрабатывать не только строковые элементы, но и числовые. # Добавляем к строке два последних элемента, разделенных союзом "и" result = result + str(items[len(items) – 2]) + " и " result = result + str(items[len(items) – 1]) # Возвращаем результат return result # Запрашиваем у пользователя слова и форматируем их def main(): # Запрашиваем у пользователя слова, пока не будет пропущена строка ввода items = [] line = input("Введите слово (Enter для окончания ввода): ") while line != "": items.append(line) line = input("Введите слово (Enter для окончания ввода): ") # Форматируем и отображаем результат print("Введенные элементы: %s." % formatList(items)) # Вызов основной функции main() Упражнение 121. Случайные лотерейные номера ## # Собираем уникальные случайные номера для лотерейного билета # from random import randrange Списки 207 MIN_NUM = 1 MAX_NUM = 49 NUM_NUMS = 6 # Используем список для хранения номеров лотерейного билета ticket_nums = [] # Генерируем NUM_NUMS случайных, но уникальных значений for i in range(NUM_NUMS): # Генерируем номер, которого еще нет в списке rand = randrange(MIN_NUM, MAX_NUM + 1) while rand in ticket_nums: rand = randrange(MIN_NUM, MAX_NUM + 1) # Добавляем номер к билету ticket_nums.append(rand) # Сортируем номера по возрастанию и отображаем их ticket_nums.sort() print("Номера вашего билета: ", end="") for n in ticket_nums: print(n, end=" ") print() Упражнение 125. Тасуем колоду карт ## # Создаем колоду карт и перетасовываем ее # from random import randrange ## Генерируем стандартную колоду карт с четырьмя мастями и 13 номиналами в каждой # @return список карт с каждой картой, представленной двумя символами def createDeck(): # Создаем список для хранения карт cards = [] # Проходим по всем мастям и номиналам for suit in ["s", "h", "d", "c"]: for value in ["2", "3", "4", "5", "6", "7", "8", "9", \ "T", "J", "Q", "K", "A"]: # Генерируем карту и добавляем ее в колоду cards.append(value + suit) # Возвращаем целую колоду return cards ## Тасуем колоду, переданную в функцию в качестве параметра # @param cards – список карт для тасования Использование констант поможет быстро адап- тировать программу для любой лотереи. 208 Решения # @return (None) def shuffle(cards): # Проходим по картам for i in range(0, len(cards)): # Выбираем случайный индекс между текущим индексом и концом списка other_pos = randrange(i, len(cards)) # Меняем местами текущую карту со случайно выбранной temp = cards[i] cards[i] = cards[other_pos] cards[other_pos] = temp # Отображаем колоду до и после тасования def main(): cards = createDeck() print("Исходная колода карт: ") print(cards) print() shuffle(cards) print("Перетасованная колода карт: ") print(cards) # Вызываем основную функцию, только если программа не была импортирована как модуль if __name__ == "__main__": main() Упражнение 128. Подсчитать элементы в списке ## # Подсчитываем количество элементов в списке, больших или равных # заданному минимуму и меньших заданного максимума # ## Определяем, сколько элементов в списке больше или равны # заданному минимуму и меньше заданного максимума # @param data – список значений для обработки # @param mn – минимальная граница # @param mx – максимальная граница # @return количество элементов e, отвечающее условию mn <= e < mx def countRange(data, mn, mx): # Подсчитываем количество элементов в списке из указанного диапазона count = 0 for e in data: # Проверяем каждый элемент if mn <= e and e < mx: count = count + 1 # Возвращаем результат return count Списки 209 # Демонстрируем работу функции countRange def main(): data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # Случай, когда несколько элементов входят в диапазон print("Подсчитываем количество элементов в списке [1..10] между 5 и 7...") print("Результат: %d Ожидание: 2" % countRange(data, 5, 7)) # Случай, когда все элементы входят в диапазон print("Подсчитываем количество элементов в списке [1..10] между –5 и 77...") print("Результат: %d Ожидание: 10" % countRange(data, –5, 77)) # Случай, когда ни один из элементов не входит в диапазон print("Подсчитываем количество элементов в списке [1..10] между 12 и 17...") print("Результат: %d Ожидание: 0" % countRange(data, 12, 17)) # Случай, когда список пуст print("Подсчитываем количество элементов в списке [] между 0 и 100...") print("Результат: %d Ожидание: 0" % countRange([], 0, 100)) # Случай, когда в списке есть дубликаты data = [1, 2, 3, 4, 1, 2, 3, 4] print("Подсчитываем количество элементов в списке", data, "между 2 и 4...") print("Результат: %d Ожидание: 4" % countRange(data, 2, 4)) # Вызов основной программы main() Упражнение 129. Разбиение строки на лексемы ## # Разбиение строки, содержащей математическое выражение, на лексемы # ## Преобразуем математическое выражение в список лексем # @param s – строка для разбора # @return список лексем строки s или пустой список, если возникла ошибка def tokenList(s) : # Удаляем все пробелы из строки s s = s.replace(" ", "") # Проходим по символам в строке, определяя лексемы и добавляя их к списку tokens = [] i = 0 while i < len(s): # Обрабатываем односимвольные лексемы: *, /, ˆ, ( и ) if s[i] == "*" or s[i] == "/" or s[i] == "ˆ" or \ s[i] == "(" or s[i] == ")" or s[i] == "+" or s[i] == "–": tokens.append(s[i]) i = i + 1 210 Решения # Обрабатываем числа без лидирующих + или – elif s[i] >= "0" and s[i] <= "9": num = "" # Добавляем символы в лексему, пока они представляют собой цифры while i < len(s) and s[i] >= "0" and s[i] <= "9": num = num + s[i] i = i + 1 tokens.append(num) # Наличие других символов означает недействительность выражения. # Возвращаем пустой список для сигнализации возникновения ошибки else: return [] return tokens # Запрашиваем выражение у пользователя, разбиваем на лексемы и отображаем результат def main(): exp = input("Введите математическое выражение: ") tokens = tokenList(exp) print("Лексемы:", tokens) # Вызываем основную функцию, только если программа не была импортирована как модуль if __name__ == "__main__": main() Упражнение 130. Унарные и бинарные операторы ## # Устанавливаем разницу между унарными и бинарными операторами + и – # from token_list import tokenList ## Определяем появление унарных операторов + и – в списке лексем и # меняем их на u+ и u– соответственно # @param tokens – список лексем, который может содержать унарные операторы + и – # @return список лексем с заменой унарных операторов + и – на u+ и u– def identifyUnary(tokens): retval = [] # Обрабатываем каждую лексему в списке for i in range(len(tokens)): # Если первая лексема – это + или –, то это унарный оператор if i == 0 and (tokens[i] == "+" or tokens[i] == "–"): retval.append("u" + tokens[i]) # Если это лексема + или –, а предыдущая лексема являлась # оператором или открывающей скобкой, то это унарный оператор elif i>0and (tokens[i] == "+" or tokens[i] == "–") and \ (tokens[i–1] == "+" or tokens[i–1] == "–" or tokens[i–1] == "*" or tokens[i–1] == "/" or Списки 211 tokens[i–1] == "("): retval.append("u" + tokens[i]) # Любая другая лексема свидетельствует о том, что это бинарный оператор, # так что он добавляется к списку без изменений else: retval.append(tokens[i]) # Возвращаем новый список лексем с измененными унарными операторами return retval # Демонстрируем выполнение пометки унарных операторов def main(): # Запрашиваем выражение у пользователя, разбиваем на лексемы и отображаем результат exp = input("Введите математическое выражение: ") tokens = tokenList(exp) print("Лексемы:", tokens) # Идентифицируем список унарных операторов marked = identifyUnary(tokens) print("С помеченными унарными операторами: ", marked) # Вызываем основную функцию, только если программа не была импортирована как модуль if __name__ == "__main__": main() Упражнение 134. Все подсписки заданного списка ## # Находим все подсписки в заданном списке # ## Создаем список из всех подсписков заданного списка # @param data – список, в котором выполняется поиск подсписков # @return список из всех подсписков исходного списка def allSublists(data): # Начинаем с добавления пустого списка sublists = [[]] # Генерируем подсписки длиной от 1 до len(data) for length in range(1, len(data) + 1): # Генерируем подсписки начиная с каждого индекса for i in range(0, len(data) – length + 1): # Добавляем найденный подсписок к общему списку sublists.append(data[i : i + length]) # Возвращаем результат return sublists # Демонстрируем работу функции allSublists def main(): print("Подсписки []: ") Список с пустым списком внут- ри обозначается как [[]]. 212 Решения print(allSublists([])) print("Подсписки [1]: ") print(allSublists([1])) print("Подсписки [1, 2]: ") print(allSublists([1, 2])) print("Подсписки [1, 2, 3]: ") print(allSublists([1, 2, 3])) print("Подсписки [1, 2, 3, 4]: ") print(allSublists([1, 2, 3, 4])) # Вызов основной программы main() Упражнение 135. Решето Эратосфена ## # Определяем все простые числа от 2 до значения, введенного пользователем, # при помощи алгоритма "Решето Эратосфена" # # Запрашиваем у пользователя конечное значение limit = int(input("Вывести простые числа вплоть до какого значения? ")) # Создаем список для чисел от 0 до limit nums = [] for i in range(0, limit + 1): nums.append(i) # "Вычеркиваем" единицу, заменяя ее на ноль nums[1] = 0 # Вычеркиваем числа, кратные всем найденным простым числам p = 2 while p < limit: # Вычеркиваем все числа, кратные p, но не его само for i in range(p * 2, limit + 1, p): nums[i] = 0 # Находим следующее "невычеркнутое" число p = p + 1 while p < limit and nums[p] == 0: p = p + 1 # Отображаем результат print("Простые числа вплоть до", limit, ":") for i in nums: if nums[i] != 0: print(i) Глава 14 Словари Упражнение 136. Поиск по значению ## # Проводим поиск всех ключей в словаре по заданному значению # ## Поиск в словаре по значению # @param data – словарь для поиска # @param value – искомое значение # @return список (возможно, пустой) ключей, соответствующих искомому значению def reverseLookup(data, value): # Создаем список ключей для заданного значения keys = [] # Проверяем каждый ключ и добавляем в список, # если он соответствует искомому значению for key in data: if data[key] == value: keys.append(key) # Возвращаем список ключей return keys # Демонстрируем работу reverseLookup def main(): # Словарь соответствий французских слов английским frEn = {"le" : "the", "la" : "the", "livre" : "book", \ "pomme" : "apple"} # Показываем работу функции reverseLookup для трех случаев: # для множества ключей, одного ключа и отсутствия ключей print("Перевод английского слова 'the' на французский: ", \ reverseLookup(frEn, "the")) print("Ожидаемый результат: ['le', 'la']") print() print("Перевод английского слова 'apple' на французский: ", \ Каждый ключ в словаре дол- жен быть уникальным. При этом значения могут повто- ряться. Таким образом, поиск в словаре по значению может привести к результату, содер- жащему от нуля до множества ключей. 214 Решения reverseLookup(frEn, "apple")) print("Ожидаемый результат: ['pomme']") print() print("Перевод английского слова 'asdf' на французский: ", \ reverseLookup(frEn, "asdf")) print("Ожидаемый результат: []") # Вызываем основную функцию, только если файл не был импортирован в качестве модуля if __name__ == "__main__": main() Упражнение 137. Две игральные кости ## # Симуляция многократного выбрасывания двух игральных костей и сравнение # полученных результатов с ожидаемыми # from random import randrange NUM_RUNS = 1000 D_MAX = 6 ## Симуляция выбрасывания двух шестигранных игральных костей # @return общее количество очков, выпавших на двух костях def twoDice(): # Две кости d1 = randrange(1, D_MAX + 1) d2 = randrange(1, D_MAX + 1) # Возвращаем сумму return d1 + d2 # Симулируем многократное выбрасывание костей и отображаем результат def main(): # Составим словарь для ожидаемых значений expected = {2: 1/36, 3: 2/36, 4: 3/36, 5: 4/36, 6: 5/36, \ 7: 6/36, 8: 5/36, 9: 4/36, 10: 3/36, \ 11: 2/36, 12: 1/36} # Составим словарь для хранения результатов выбрасывания костей counts = {2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, \ 8: 0, 9: 0, 10: 0, 11: 0, 12: 0} Словари изначально инициализированы ключами от 2 до 12. В словаре expected значения заполнены в соответствии с теорией вероятностей, тогда как в словаре counts изначально стоят нули, которые будут меняться в процессе симуляции вы- брасывания костей. Словари 215 # Проведение NUM_RUNS симуляций и подсчет результатов for i in range(NUM_RUNS): t = twoDice() counts[t] = counts[t] + 1 # Сравниваем ожидаемые результаты с реальными print("Всего Реальный Ожидаемый") print(" процент процент") for i in sorted(counts.keys()): print("%5d %9.2f %10.2f" % \ (i, counts[i] / NUM_RUNS * 100, expected[i] * 100)) # Вызов основной функции main() Упражнение 142. Уникальные символы ## # Считаем уникальные символы в строке при помощи словаря # # Запрашиваем строку у пользователя s = input("Введите строку: ") # Добавляем каждый символ в словарь со значением True. После окончания процедуры # количество ключей в словаре и будет отражать число уникальных символов characters = {} for ch in s: characters[ch] = True Каждому ключу в словаре должно соответствовать значение. Но в нашем примере эти значения никогда не будут использованы, так что мы решили применить True. Вместо него мы могли использовать любое другое значение. # Отображаем результат print("Строка содержит", len(characters), \ "уникальных символов.") Функция len возвращает количество ключей в словаре. Упражнение 143. Анаграммы ## # Определяем, являются ли два введенных пользователем слова анаграммами # 216 Решения ## Рассчитываем распределение частоты появления символов в строке # @param s – строка для обработки # @return словарь с количеством символов в строке def characterCounts(s): # Создаем пустой словарь counts = {} # Обновляем словарь для каждого символа в строке for ch in s: if ch in counts: counts[ch] = counts[ch] + 1 else: counts[ch] = 1 # Возвращаем результат return counts # Определяем, являются ли строки, введенные пользователем, анаграммами def main(): # Запрашиваем строки у пользователя s1 = input("Введите первую строку: ") s2 = input("Введите вторую строку: ") # Вызываем функцию для двух введенных строк counts1 = characterCounts(s1) counts2 = characterCounts(s2) # Выводим результат if counts1 == counts2: print("Введенные строки являются анаграммами.") else: print("Введенные строки не являются анаграммами.") Два словаря считаются равными, если содержат одинаковое количество ключей и те же самые ассоциированные с ними значения. # Вызов основной функции main() Упражнение 145. Эрудит ## # Используем словарь для подсчета количества очков за собранное слово в Эрудите # # Создаем словарь с соответствием букв и очков за них points = {"A": 1, "B": 3, "C": 3, "D": 2, "E": 1, "F": 4, \ Словари 217 "G": 2, "H": 4, "I": 1, "J": 2, "K": 5, "L": 1, \ "M": 3, "N": 1, "O": 1, "P": 3, "Q": 10, "R": 1, \ "S": 1, "T": 1, "U": 1, "V": 4, "W": 4, "X": 8, "Y": 4, "Z": 10} # Запрашиваем у пользователя слово word = input("Введите слово: ") # Считаем количество очков uppercase = word.upper() score = 0 for ch in uppercase: score = score + points[ch] # Выводим результат print(word, "оценивается в", score, "очков.") Упражнение 146. Карточка лото ## # Создадим и отобразим случайную карточку лото # from random import randrange NUMS_PER_LETTER = 15 ## Создание случайной карточки для игры в лото # @return словарь с ключами, представляющими буквы B, I, N, G и O, # и списком номеров под каждой буквой def createCard(): card = {} # Диапазон целых чисел для букв lower = 1 upper = 1 + NUMS_PER_LETTER # Для каждой из пяти букв for letter in ["B", "I", "N", "G", "O"]: # Создаем пустой список для буквы card[letter] = [] # Генерируем случайные номера, пока не наберется пять уникальных while len(card[letter]) != 5: next_num = randrange(lower, upper) # Убеждаемся, что не храним дубликаты номеров if next_num not in card[letter]: card[letter].append(next_num) # Обновляем диапазон номеров для следующей буквы lower = lower + NUMS_PER_LETTER Введенное слово мы переводим в верхний регистр, чтобы не ограничивать пользовате- ля в выборе регистра при вводе слова. Этого результата можно было добиться и путем до- бавления строчных букв к словарю. 218 Решения upper = upper + NUMS_PER_LETTER # Возвращаем сгенерированную карточку return card ## Выводим отформатированную карточку лото # @param card – карточка лото для отображения # @return (None) def displayCard(card): # Заголовки print("B I N G O") # Отображаем номера for i in range(5): for letter in ["B", "I", "N", "G", "O"]: print("%2d " % card[letter][i], end="") print() # Создаем случайную карточку для игры в лото и отображаем ее def main(): card = createCard() displayCard(card) # Вызываем основную функцию, только если файл не импортирован if __name__ == "__main__": main() |