Lambdas with Functions

Yacht
Yacht in Python

Approach: Using Lambdas with Functions

Each bit of functionality for each category can be encoded in an anonymous function (otherwise known as a lambda expression or lambda form), and the constant name set to that function.

In score, we call the category (as it now points to a function) passing in dice as an argument.

def digits(num):
    return lambda dice: dice.count(num) * num

YACHT = lambda dice: 50 if len(set(dice)) ==  1 else 0
ONES = digits(1)
TWOS = digits(2)
THREES = digits(3)
FOURS = digits(4)
FIVES = digits(5)
SIXES = digits(6)
FULL_HOUSE = lambda dice: sum(dice) if len(set(dice)) == 2 and dice.count(dice[0]) in [2, 3] else 0
FOUR_OF_A_KIND = lambda dice: 4 * dice[1] if dice[0] == dice[3] or dice[1] == dice[4] else 0
LITTLE_STRAIGHT = lambda dice: 30 if sorted(dice) == [1, 2, 3, 4, 5] else 0
BIG_STRAIGHT = lambda dice: 30 if sorted(dice) == [2, 3, 4, 5, 6] else 0
CHOICE = sum

def score(dice, category):
    return category(dice)

Instead of setting each constant in ONES through SIXES to a separate function, we create a function digits that returns a function, using closures transparently.

For LITTLE_STRAIGHT and BIG_STRAIGHT, we first sort the dice and then check it against the hard-coded value. Another way to solve this would be to check if sum(dice) == 20 and len(set(dice)) == 5 (15 in LITTLE_STRAIGHT). In CHOICE, lambda number : sum(number) is shortened to just sum.

In FULL_HOUSE, we create a set to remove the duplicates and check the set's length along with the individual counts. For FOUR_OF_A_KIND, we check if the first and the fourth element are the same or the second and the last element are the same - if so, there are (at least) four of the same number in the array.

This solution is a succinct way to solve the exercise, although some of the one-liners can get a little long and hard to read. Additionally, PEP8 does not recommend assigning constant or variable names to lambda expressions, so it is a better practice to use def:

def digits(num):
    return lambda dice: dice.count(num) * num

def YACHT(dice): return 50 if len(set(dice)) ==  1 else 0
ONES = digits(1)
TWOS = digits(2)
THREES = digits(3)
FOURS = digits(4)
FIVES = digits(5)
SIXES = digits(6)
def FULL_HOUSE(dice): return sum(dice) if len(set(dice)) == 2 and dice.count(dice[0]) in [2, 3] else 0
def FOUR_OF_A_KIND(dice): return 4 * sorted(dice)[1] if len(set(dice)) < 3 and dice.count(dice[0]) in (1, 4, 5) else 0
def LITTLE_STRAIGHT(dice): return 30 if sorted(dice) == [1, 2, 3, 4, 5] else 0
def BIG_STRAIGHT(dice): return 30 if sorted(dice) == [2, 3, 4, 5, 6] else 0
CHOICE = sum

def score(dice, category):
    return category(dice)

As you can see from the examples, the ternary operator (or ternary form) is crucial in solving the exercise using one liners.
As functions are being used, it might be a better strategy to spread the code over multiple lines to improve readability.

def YACHT(dice):
    if dice.count(dice[0]) == len(dice):
        return 50
    return 0
16th Oct 2024 · Found it useful?