На этом шаге мы рассмотрим запись телефонных номеров в мнемоническом виде.
До того как появились смартфоны со встроенной адресной книгой, на каждой кнопке телефона кроме цифр значилось еще несколько букв. Причиной этого было обеспечение возможности выработать простые мнемонические правила для запоминания телефонных номеров. В Соединенных Штатах, как правило, на клавише 1 букв не было, на клавише 2 стояло АВС, на клавише 3 - DEF, на клавише 4 - GHI, на клавише 5 - JKL, на клавише 6 - MNO, на клавише 7 - PQRS, на клавише 8 - TUV, на клавише 9 - WXYZ, на клавише 0 букв также не было. Таким образом, номер 1-800-МY-APPLE соответствует номеру телефона 1-800-69-27753. Такие сочетания все еще встречаются в рекламных объявлениях, поэтому цифры с клавиатуры попали в современные приложения для смартфонов (рисунок 1).
Рис.1. В приложении для набора номера сохранены буквы на клавишах, которые были в старых телефонах
Как придумать новое мнемоническое правило для номера телефона? В 1990-х годах было популярно условно-бесплатное приложение, позволяющее это сделать. Разные части данной программы генерировали все перестановки букв телефонного номера и затем просматривали словарь, чтобы найти слова, которые содержали эти перестановки. Затем программа показывала пользователю перестановки с наиболее полными словами. Мы решим первую половину этой задачи. Поиск в словаре останется в качестве самостоятельного упражнения.
В предыдущей задаче, рассматривая генерацию перестановок, мы использовали функцию permutations() для нахождения потенциальных путей решения задачи коммивояжера. Однако, как уже упоминалось, существует много способов генерации перестановок. В частности, в этой задаче для создания новой перестановки мы не будем менять местами две позиции в существующей, а сгенерируем каждую перестановку с нуля. Сделаем это, просмотрев потенциальные буквы, которые соответствуют всем цифрам телефонного номера, и, переходя к каждой последующей цифре, станем добавлять новые варианты в конец списка. Это своего рода декартово произведение, и модуль itertools стандартной библиотеки Python снова нам поможет.
Сначала определим соответствие чисел и потенциальных букв.
from typing import Dict, Tuple, Iterable, List from itertools import product phone_mapping: Dict[str, Tuple[str, ...]] = {"1": ("1",), "2": ("a", "b", "c"), "3": ("d", "e", "f"), "4": ("g", "h", "i"), "5": ("j", "k", "l"), "6": ("m", "n", "o"), "7": ("p", "q", "r", "s"), "8": ("t", "u", "v"), "9": ("w", "x", "y", "z"), "0": ("0",)}
Следующая функция объединяет все эти возможности для каждой цифры в список возможных мнемонических правил для данного телефонного номера. Для этого создается список кортежей потенциальных букв для каждой цифры в телефонном номере. Затем эти кортежи объединяются посредством функции декартова произведения product() из модуля itertools. Обратите внимание на оператор unpack(*) для использования кортежей в letter_tuples в качестве аргументов для функции product().
def possible_mnemonics(phone_number: str) -> Iterable[Tuple[str, ...]]: letter_tuples: List[Tuple[str, ...]] = [] for digit in phone_number: letter_tuples.append(phone_mapping.get(digit, (digit,))) return product(*letter_tuples)
Теперь мы можем найти все возможные мнемонические правила для данного номера телефона.
if __name__ == "__main__": phone_number: str = input("Задайте номер телефона:") print("Его мнемоническое представление:") for mnemonic in possible_mnemonics(phone_number): print("".join(mnemonic))
Оказывается, номер телефона 144-07-87 можно записать как 1gh-0s-ts, что легче запомнить.
На следующем шаге мы подведем некоторые итоги.