|
| 1 | +""" |
| 2 | +Task: Replicate what rachel does on countdown - generate an expression to get from smaller numbers to a target number |
| 3 | +
|
| 4 | +What we'll need to do: |
| 5 | +- Something to generate some smaller numbers (or a hardcoded list) |
| 6 | +- Randomly choose 6 smaller numbers |
| 7 | +- Randomly choose a target number |
| 8 | +
|
| 9 | +- Something to generate an expression that makes the target from the smaller numbers (or tells us if that is not possible) |
| 10 | +- Only +-*/ are allowed |
| 11 | +
|
| 12 | +"The contestant in control chooses six of 24 shuffled face-down number tiles, arranged into two groups: 20 "small numbers" |
| 13 | +(two each of 1 to 10) and four "large numbers" of 25, 50, 75 and 100. The contestant decides how many large numbers are to be used, |
| 14 | +from none to all four, after which the six tiles are randomly drawn and placed on the board. |
| 15 | +A random three-digit target figure from 100 to 999 is then generated by an electronic machine" |
| 16 | +
|
| 17 | +"They may use only the four basic operations of addition, subtraction, multiplication and division[47] and do not have to use all six numbers. |
| 18 | +A number may not be used more times than it appears on the board. Division can only be performed if the result has no remainder |
| 19 | +(i.e., the divisor is a factor of the dividend)." |
| 20 | +
|
| 21 | +""" |
| 22 | +import random |
| 23 | + |
| 24 | +LARGE_NUMBERS = [25, 50, 75, 100] |
| 25 | +SMALL_NUMBERS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * 2 |
| 26 | +OPERATIONS = { |
| 27 | + "+": lambda a, b: a + b, |
| 28 | + "*": lambda a, b: a * b, |
| 29 | + "-": lambda a, b: a - b, |
| 30 | + "/": lambda a, b: a // b if a % b else float("inf") |
| 31 | +} |
| 32 | + |
| 33 | +def generate_numbers(large_number_count: int) -> list[int]: |
| 34 | + """Generate 6 numbers, with large_number_count from the large numbers and the rest from small""" |
| 35 | + |
| 36 | + large_nums = LARGE_NUMBERS.copy() |
| 37 | + numbers = [] |
| 38 | + for i in range(large_number_count): |
| 39 | + value = random.choice(large_nums) |
| 40 | + numbers.append(value) |
| 41 | + large_nums.remove(value) |
| 42 | + |
| 43 | + small_nums = SMALL_NUMBERS.copy() |
| 44 | + for i in range(6 - large_number_count): |
| 45 | + value = random.choice(small_nums) |
| 46 | + numbers.append(value) |
| 47 | + small_nums.remove(value) |
| 48 | + |
| 49 | + return numbers |
| 50 | + |
| 51 | +def generate_target_number() -> int: |
| 52 | + """Generate a random 3 digit number as a target""" |
| 53 | + return random.randint(100, 999) |
| 54 | + |
| 55 | +# def calculate_expression_recursive(numbers: list[int], target_number: int) -> str | None: |
| 56 | +# """Work out how to get from the numbers to the target_number, returning None if it is not possible""" |
| 57 | + |
| 58 | + |
| 59 | +def calculate_expressions(expressions: list[str], target_number: int) -> list[str]: |
| 60 | + """calculate every possible expression and return the equation and the final output""" |
| 61 | + if len(expressions) == 1: |
| 62 | + if eval(expressions[0]) == target_number: |
| 63 | + print(expressions[0], eval(expressions[0])) |
| 64 | + return expressions |
| 65 | + return [] |
| 66 | + |
| 67 | + calculated_expressions = [] |
| 68 | + for i, first in enumerate(expressions): |
| 69 | + for j, second in enumerate(expressions): |
| 70 | + if i == j: |
| 71 | + continue |
| 72 | + remaining_numbers = [expressions[k] for k in range(len(expressions)) if k not in {i, j}] |
| 73 | + for op in ["+", "-", "*", "//"]: |
| 74 | + if op == "//" and (eval(second) == 0 or eval(first) % eval(second) != 0): |
| 75 | + continue |
| 76 | + result = f"({first}{op}{second})" |
| 77 | + # a + b |
| 78 | + calculated_expressions.extend(calculate_expressions([result, *remaining_numbers], target_number)) |
| 79 | + return calculated_expressions |
| 80 | + |
| 81 | + |
| 82 | +def main() -> None: |
| 83 | + """Countdown game""" |
| 84 | + target_number = generate_target_number() |
| 85 | + numbers = generate_numbers(3) |
| 86 | + print(f"Attempting to get to {target_number} with: {numbers}") |
| 87 | + print(calculate_expressions(expressions=list(map(str, numbers)), target_number=target_number)) |
| 88 | + |
| 89 | + |
| 90 | + |
| 91 | +if __name__ == "__main__": |
| 92 | + main() |
0 commit comments