Skip to content

Instantly share code, notes, and snippets.

@Kwisses
Created March 30, 2017 04:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kwisses/582e7823b5993450bd36a42cbe5f5d8e to your computer and use it in GitHub Desktop.
Save Kwisses/582e7823b5993450bd36a42cbe5f5d8e to your computer and use it in GitHub Desktop.
[Daily Challenge #139 - Intermediate] - Telephone Keypads - r/DailyProgrammer
# ***** DAILY CHALLENGE #139 - INTERMEDIATE *****
# (Intermediate): Telephone Keypads
#
# Telephone Keypads commonly have both digits and characters on them. This
# is to help with remembering & typing phone numbers (called a Phoneword),
# like 1-800-PROGRAM rather than 1-800-776-4726. This keypad layout is also
# helpful with T9, a way to type texts with word prediction.
#
# Your goal is to mimic some of the T9-features: given a series of digits
# from a telephone keypad, and a list of English words, print the word or
# set of words that fits the starting pattern. You will be given the number
# of button-presses and digit, narrowing down the search-space.
#
# Formal Inputs & Outputs
#
# Input Description
#
# On standard console input, you will be given an array of digits (0 to 9)
# and spaces. All digits will be space-delimited, unless the digits
# represent multiple presses of the same button (for example pressing 2
# twice gives you the letter 'B').
#
# Use the modern Telephone Keypads digit-letter layout:
#
# 0 = Not used
# 1 = Not used
# 2 = ABC
# 3 = DEF
# 4 = GHI
# 5 = JKL
# 6 = MNO
# 7 = PQRS
# 8 = TUV
# 9 = WXYZ
#
# You may use any source for looking up English-language words, though this
# simple English-language dictionary is complete enough for the challenge.
#
# Output Description
#
# Print a list of all best-fitting words, meaning words that start with the
# word generated using the given input on a telephone keypad. You do not
# have to only print words of the same length as the input (e.g. even if the
# input is 4-digits, it's possible there are many long words that start
# with those 4-digits).
#
# Sample Inputs & Outputs
#
# Sample Input
#
# 7777 666 555 3
#
# Sample Output
#
# sold
# solder
# soldered
# soldering
# solders
# soldier
# soldiered
# soldiering
# soldierly
# soldiers
# soldiery
#
# Challenge++
#
# If you want an extra challenge, accomplish the same challenge but without
# knowing the number of times a digit is pressed. For example "7653" could
# mean sold, or poke, or even solenoid! You must do this efficiently with
# regards to Big-O complexity.
# -----------------------------------------------------------------------------
class Phoneword(object):
"""Class for Phoneword."""
def __init__(self, button_presses):
"""Initialize class parameters and data.
Args:
button_presses (str): Keypad presses.
"""
# Button presses as a string
self.button_presses = button_presses
# Filenames
self.keypad_file = "keypad.txt"
self.words_file = "words.txt"
# Get and set class data
self.keypad_info = self.get_lines(self.keypad_file)
self.words = self.get_lines(self.words_file)
self.keypad = self.set_keypad()
# Class lists
self.letters = []
self.best_words = []
@staticmethod
def get_lines(filename):
"""Get lines from filename.
Args:
filename (str): Name of file to be read.
Returns:
list: Contains lines from filename.
"""
with open(filename) as f:
lines = f.readlines()
lines = [' '.join(line.split()) for line in lines]
return lines
def set_keypad(self, limit=4, symbol=" = "):
"""Set keypad dict from data in self.keypad_info.
Args:
limit (int): Total number of letters per button.
symbol (str): Symbol to use to split data in self.keypad_info.
Returns:
dict: Number, letters key, value pairs.
"""
keypad = {}
for line in self.keypad_info:
digit, letters = line.split(symbol)
# Prevents misuse of keypad assignment
if len(letters) <= limit:
keypad[digit] = letters
else:
keypad[digit] = None
return keypad
def find_best_words(self):
"""Find all words that start with joined self.letters.
Returns:
list: Best words (words that start with start_word).
"""
start_word = ''.join(self.letters)
for word in self.words:
if start_word in word[:len(start_word)]:
self.best_words.append(word)
return self.best_words
def get_best_words(self):
"""Get best words (words that start with joined self.letters).
Returns:
list: Contains all words that start with joined self.letters.
"""
for button in self.button_presses.split():
number, presses = button[0], len(button)-1
letter = self.keypad[number][presses]
self.letters.append(letter.lower())
return self.find_best_words()
def main():
"""Print word in best_words from Phoneword object."""
button_presses = "7777 666 555 3"
phoneword = Phoneword(button_presses)
best_words = phoneword.get_best_words()
for word in best_words:
print(word)
if __name__ == "__main__":
main()
0 = Not used
1 = Not used
2 = ABC
3 = DEF
4 = GHI
5 = JKL
6 = MNO
7 = PQRS
8 = TUV
9 = WXYZ
@Kwisses
Copy link
Author

Kwisses commented Mar 30, 2017

[Daily Challenge #139 - Intermediate] from the DailyProgrammer subreddit. Telephone Keypads.

Note: Omitted words.txt file as it contains over 77,000 English words.

Reference: https://www.reddit.com/r/dailyprogrammer/comments/1sody4/12113_challenge_139_intermediate_telephone_keypads/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment