如何扩展 Itertools 库产生的可能性?

问题描述 投票:0回答:1

我构建此代码是为了完成数学挑战,我必须找到一个组合来给出目标结果。

我必须替换“?”对于“+”、“-”、“/”或“*”,并在需要给我们答案的地方添加“( )”。

6 ? 6 ? 6 ? 6 = 5
6 ? 6 ? 6 ? 6 = 6
6 ? 6 ? 6 ? 6 = 8
6 ? 6 ? 6 ? 6 = 30
6 ? 6 ? 6 ? 6 = 24
6 ? 6 ? 6 ? 6 = 48
6 ? 6 ? 6 ? 6 = 66
6 ? 6 ? 6 ? 6 = 180

但是下面的代码找不到 30 的答案,应该是:

(6-(6/6))*6 = 30

这是代码

import itertools  # Import itertools module for combinations
import datetime  # Import datetime module for timing

# Function to evaluate mathematical expression
def evaluate_expression(expression):
    try:
        return eval(expression)  # Use eval to compute the expression's value
    except:
        return None

# Function to resolve using combinatorics
def solve_with_combinatorics(target_results, factor):
    operators = ['+', '-', '*', '/']  # List of mathematical operators
    numbers = [factor, factor, factor, factor]  # List of input numbers
    found_solutions = []  # List to store found solutions
    all_possibilities = []  # List to store all expression possibilities

    # Iterate over target results
    for target_result in target_results:
        found = False  # Flag to track if solution is found
        attempts = 0  # Counter for attempts
        expression_possibilities = []  # List to store expression possibilities

        # Iterate over operator combinations
        for operator_combination in itertools.product(operators, repeat=3):
            attempts += 1  # Increment attempts counter
            expression = str(numbers[0])  # Initialize expression with first number
            for i in range(3):
                expression = f"({expression} {operator_combination[i]} {numbers[i+1]})"
            result = evaluate_expression(expression)  # Evaluate the expression
            
            if result == target_result:  # Check if the result matches the target
                found_solutions.append((expression, result, attempts))  # Store solution
                found = True
                break
            expression_possibilities.append(expression)  # Store expression possibility

        all_possibilities.append((target_result, expression_possibilities))  # Store possibilities

        if not found:
            for possibility in expression_possibilities:
                if evaluate_expression(possibility) == target_result:  # Check if possibility matches target
                    found_solutions.append((possibility, target_result, attempts))  # Store solution
                    found = True
                    break
        
        if not found:
            found_solutions.append(("No solution found", None, attempts))  # Store no solution
    
    # Print and return results
    for solution, result, attempts in found_solutions:
        if result is not None:
            print(f"Expression: {solution} = {int(result)}")  # Print solution expression and result
        else:
            print("Expression:", solution)  # Print no solution message
        print("Attempts:", attempts)  # Print number of attempts
    
    return all_possibilities

# Target results and factor
target_results = [5, 6, 8, 30, 24, 48, 66, 180]
factor = 6

print("\n[ACHIEVE EQUALITY FOR THE MATHEMATICAL EXPRESSIONS BELOW]")
for i, result in enumerate(target_results):
    print(f"{factor} ? {factor} ? {factor} ? {factor} = {result}")  # Print target expressions
print()

start_time = datetime.datetime.now()
print(f'## Program started at: {start_time}\n')  # Print start time
all_possibilities = solve_with_combinatorics(target_results, factor)  # Call the solver function
end_time = datetime.datetime.now()
total_time = end_time - start_time
print(f'## Program ended at: {end_time}')  # Print end time
print(f'## Total time: {total_time}\n')  # Print total execution time
print("\n[All possible combinations and combination results]")

largest_target_result = max(target_results)
for target_result, possibilities in all_possibilities:
    if target_result <= largest_target_result:
        print(f"\nTarget Result {target_result}:")  # Print target result label
        for possibility in possibilities:
            print(possibility)  # Print each expression possibility
        print()

这是输出的一部分:

## Program started at: 2023-08-26 14:30:45.595289

Expression: (((6 * 6) - 6) / 6) = 5
Attempts: 40
Expression: (((6 - 6) * 6) + 6) = 6
Attempts: 25
Expression: (((6 + 6) / 6) + 6) = 8
Attempts: 13
Expression: No solution found
Attempts: 64
Expression: (((6 + 6) + 6) + 6) = 24
Attempts: 1
Expression: (((6 * 6) + 6) + 6) = 48
Attempts: 33
Expression: (((6 + 6) * 6) - 6) = 66
Attempts: 10
Expression: (((6 * 6) - 6) * 6) = 180
Attempts: 39
## Program ended at: 2023-08-26 14:30:45.604267
## Total time: 0:00:00.008978

那么,问题是:除了64种可能性之外,如何增加组合的可能性?

我尝试在屏幕上绘制所有可能性,看看代码中是否有问题,但没有。我相信这是 intertool 库的限制。

python python-itertools puzzle
1个回答
0
投票

为了增加 64 种可能性,您应该创建数字的可能括号组。

这是一种查找数字可能的括号组的算法:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


def product(*iterables):
    if not iterables:
        yield []
        return
    for i in iterables[0]:
        for p in product(*iterables[1:]):
            yield [i, *p]


def find_numbers(s: str):
    return list(map(int, "".join(map(lambda i: i if i.isnumeric() else " ", s)).split()))
    
    
def find_chars(s: str):
    return list(filter(lambda i: not i.isnumeric(), s))


def group_numbers(x):
    step = 2
    result = [x]
    while step < len(x):
        for i in range(len(x) - 1):
            left = x[:i]
            mid = x[i: i + step]
            right = x[i + step:]
            if len(mid) == step:
                result.append([*left, mid, *right])
                if len(left) == step:
                    result.append([left, mid, *right])
                if len(mid) > 2:
                    for mid_group in group_numbers(mid):
                        item = [*left, mid_group, *right]
                        if item not in result:
                            result.append(item)           
        step += 1
    return result
    
    
def insert_operators(x, y):
    expr = ""
    for i in range(len(x)):
        if isinstance(x[i], list):
            expr += "(" + insert_operators(x[i], y) + ")"
            try:
                if expr[-1] != x[i + 1]:
                    expr += next(y)
            except IndexError:
                pass
        else:
            expr += str(x[i])
            if i != len(x) - 1:
                try:
                    expr += next(y)
                except StopIteration:
                    pass 
    return expr
    
    
def get_products(factor, ops, number):
    products = []
    for i in range(number):
        if i == number - 1:
            products += [factor]
        else:
            products += [factor] + [ops]
    return products
   

def main():
    ops = "+-/*"
    factor = "6"
    number = 4
    targets = [5, 6, 8, 30, 24, 48, 66, 180]
    for i in product(*get_products(factor, ops, number)):
        expr = "".join(i)
        for group in group_numbers(find_numbers(expr)):
            equation = insert_operators(group, iter(find_chars(expr)))
            try:
                res = eval(equation)
                if res in targets:
                    print(equation, res)
                    targets.remove(res)
            except ZeroDivisionError:
                pass

                                      
main()

输出:

6+6+6+6 24
6+(6+6)/6 8.0
6+6+6*6 48
6+(6-6)/6 6.0
(6+6)*6-6 66
(6-6/6)*6 30.0
(6*6-6)/6 5.0
(6*6-6)*6 180
© www.soinside.com 2019 - 2024. All rights reserved.