Introduction
Scrabble is a word game where players place letter tiles on a board to form words.
Each letter has a value.
A word’s score is the sum of its letters’ values.
Instructions
Instructions
Your task is to compute a word’s Scrabble score by summing the values of its letters.
The letters are valued as follows:
| Letter | Value |
|---|
| A, E, I, O, U, L, N, R, S, T | 1 |
| D, G | 2 |
| B, C, M, P | 3 |
| F, H, V, W, Y | 4 |
| K | 5 |
| J, X | 8 |
| Q, Z | 10 |
For example, the word “cabbage” is worth 14 points:
- 3 points for C
- 1 point for A
- 3 points for B
- 3 points for B
- 1 point for A
- 2 points for G
- 1 point for E
Dig Deeper
Enum
Enum
from enum import IntEnum
class Scrabble(IntEnum):
A = E = I = O = U = L = N = R = S = T = 1
D = G = 2
B = C = M = P = 3
F = H = V = W = Y = 4
K = 5
J = X = 8
Q = Z = 10
def score(word):
return sum(Scrabble[character] for character in word.upper())
This approach uses an Enum to define the score of each letter.
An Enum (also known as an enumeration) is an object with named attributes assigned unique values.
These attributes are referred to as the enumeration members.
Enums can be iterated over to return their members in definition order.
Values can be accessed via index syntax using the member name (similar to how a dictionary lookup works) .
Enums are immutable, and their members function as constants.
The enum module was added to python standard library (also known as stdlib) in Python 3.4.
This approach uses an IntEnum.
An IntEnum is very similar to an Enum, but restricts assigned values to ints.
This allows the IntEnum to act as a collection of integers.
In fact, IntEnums are considered subclasses of ints.
To use an IntEnum you need to first import it using: from enum import IntEnum.
Then you can define your IntEnum subclass.
The IntEnum subclass is defined by using the class keyword, followed by the name you are using for the class, and then the IntEnum class you are subclassing in parenthesis:
class ClassName(IntEnum):
Member names are declared as constants (ALL CAPS) and assigned values using the = operator.
This approach works by creating all the uppercase letters as members with their values being the score.
After the IntEnum is defined, the score function is defined.
The score function takes a word as an argument.
The score function uses the same generator expression as the dictionary approach, but with a slight modification.
Instead of looking up the value in a dictionary, it looks up the InEnum class member value.
Dictionary
Dictionary
LETTER_SCORES = {
'A': 1, 'E': 1, 'I': 1, 'O': 1, 'U': 1,
'L': 1, 'N': 1, 'R': 1, 'S': 1, 'T': 1,
'D': 2, 'G': 2, 'B': 3, 'C': 3, 'M': 3,
'P': 3, 'F': 4, 'H': 4, 'V': 4, 'W': 4,
'Y': 4, 'K': 5, 'J': 8, 'X': 8, 'Q': 10, 'Z': 10
}
def score(word):
return sum(LETTER_SCORES[letter] for letter in word.upper())
This code starts with defining a constant LETTER_SCORES as a dictionary (concept:python/dicts) where each letter is a key and the corresponding score is a value.
Then the score function is defined, which takes a <word> as an argument.
The function returns the total score for the word using the built-in function sum.
Sum is passed a generator expression that iterates over the letters in the word, looking up each score in LETTER_SCORES.
The generator expression produces the score values on the fly.
This means that it doesn’t use memory to store all the values from LETTER_SCORES.
Instead, each value is looked up as needed by sum.
Within the generator expression, the word is converted from lower to uppercase.
Each letter of the word is looked up in LETTER_SCORES, and the score value is yielded to sum as sum iterates over the expression.
This is almost exactly the same process as using a list comprehension.
However, a list comprehension would look up the values and save them into a list in memory.
sum would then “unpack” or iterate over the list.
A variation on this dictionary approach is to use a dictionary transposition.
LETTER_SCORES = {
1: {'A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T'},
2: {'D', 'G'},
3: {'B', 'C', 'M', 'P'},
4: {'F', 'H', 'V', 'W', 'Y'},
5: {'K'},
8: {'J', 'X'},
10: {'Q', 'Z'}
}
def score(word):
return sum(next(score for score, letters in LETTER_SCORES.items() if character in letters) for character in word.upper())
However, transposing the dictionary so that the keys are the score and the values are the letters requires more computational calculation (a loop within a loop) and is harder to read.
Therefore, arranging the dictionary by letter is both more efficient and easier to understand.
Nested Tuple
Nested Tuple
LETTERS_OF_SCORE = (
("AEIOULNRST", 1),
("DG", 2),
("BCMP", 3),
("FHVWY", 4),
("K", 5),
("JX", 8),
("QZ", 10),
)
def score(word):
return sum(score for character in word.upper() for
letters, score in LETTERS_OF_SCORE if character in letters)
The code starts with defining a constant, LETTERS_OF_SCORE as a tuple of tuples (also known as a nested tuple).
Inside of the inner tuples are 2 values, the first value is a string of letters and the second value is the score for those letters.
Next, the score function is defined, taking a word as an argument.
The score function uses a generator expression similar to the dictionary approach with some slight modifications.
This particular approach uses a nested for loop to iterate over the letters and the tuples.
We first iterate over the characters in the word and then the tuples.
Which means that for each letter we iterate over all of the tuples.
Each iteration, the tuple is unpacked into the letters and their corresponding score.
You can read more about unpacking in the concept:python/unpacking-and-multiple-assignment.
Then the code checks if the character is in the unpacked letters and if it is we return its score.
Source: Exercism python/scrabble-score