简体   繁体   English

数字列表上所有可能的操作组合,以查找特定数字

[英]All possible combinations of operations on list of numbers to find a specific number

I know that there are other questions like mine but the only problem is that they get all the combinations for all of the varibales in list but I want it so that the user enters the number that the want and the numbers they need to make the desired number. 我知道还有其他问题,例如我的,但是唯一的问题是,它们可以获取列表中所有变量的所有组合,但是我想要这样,以便用户输入所需数量和所需数量数。 This is the code that I have: 这是我的代码:

numbers = []
operators = ['+', '*', '-', '/']
desire = int(input("Enter the number you want: "))
num1 = int(input("Enter First number: "))
num2 = int(input("Enter Second number: "))
num3 = int(input("Enter Third number: "))
num4 = int(input("Enter Fourth number: "))
numbers.append(num1)
numbers.append(num2)
numbers.append(num3)
numbers.append(num4)

But I have no idea how to expand on this 但我不知道该如何扩展

This is an example on what the code should do: 这是代码应执行的示例:

Say that the number they want made is 24 and 假设他们要拨打的号码是24

Say the numbers that they enter are 1, 9, 8, 2 说他们进入数字是1, 9, 8, 2

output should be this: 输出应为:

9 - 1 + 8 * 2 = 24

etc... 等等...

All possible solutions need to be listed 所有可能的解决方案都需要列出

All suggestions will be greatly appriciated 所有建议将不胜枚举

You could use permutations from the itertools module to arrange numbers and operators in all possible ways into a string formula. 您可以使用itertools模块中的置换以所有可能的方式将数字和运算符排列到字符串公式中。 Then use eval() to compute the result. 然后使用eval()计算结果。

For example: 例如:

from itertools import permutations
numbers   = ["1","9","8","2"]
target    = 24
operators = ["+","-","*","/"]
for values in permutations(numbers,len(numbers)):
    for oper in permutations(operators,len(numbers)-1):
        formula = "".join(o+v for o,v in zip([""]+list(oper),values))
        if eval(formula) == target: print(formula,"=",target)

[UPDATE1] If you are allowed to use the same operator more than once (as suggested by your comment on 1+1+1*8=24), you will need to use combinations_with_replacement to generate more operator patterns: [UPDATE1]如果允许您多次使用同一运算符(如您对1 + 1 + 1 * 8 = 24的评论所建议),则将需要使用groups_with_replacement生成更多运算符模式:

from itertools import permutations,combinations_with_replacement
numbers   = ["1","1","1","8"]
target    = 10
operators = ["+","-","*","/"]
seen      = set()
for values in permutations(numbers,len(numbers)):
    for operCombo in combinations_with_replacement(operators,len(numbers)-1):
        for oper in permutations(operCombo,len(numbers)-1):
            formula = "".join(o+v for o,v in zip([""]+list(oper),values))
            if formula not in seen and eval(formula) == target:
                print(formula,"=",target)
                seen.add(formula)

Essentially, this only differs from the previous example by the insertion of the for operCombo in ... loop. 本质上,这仅与前面的示例有所不同for operCombo in ...循环中插入了for operCombo in ...

Note: The combinations will generate formulas that look exactly the same so you will want to avoid printing solutions that have already been seen (as I did here). 注意:这些组合将生成看起来完全相同的公式,因此您将要避免打印已经看到的解决方案(就像我在这里所做的那样)。 Duplications would also occur in the previous example if any numbers were repeated in the input. 如果在输入中重复任何数字,则在前面的示例中也会发生重复。

Also note that in order for 9-1+8*2 to result in 24, the multiplication must be performed before additions and subtractions (ie under precedence rules) otherwise 9-1+8*2=32. 还要注意,为了使9-1 + 8 * 2产生24,必须在加法和减法之前(即在优先规则下)执行乘法,否则9-1 + 8 * 2 = 32。 You would need to support parentheses to cover different orders of operation. 您需要支持括号以涵盖不同的操作顺序。

[UPDATE2] Supporting parentheses is a bit more involved depending on how many numbers you want to allow. [UPDATE2]根据您要允许多少个数字,需要更多地加上括号。 For 4 numbers, there are 11 patterns: 对于4个数字,有11种模式:

  • No parentheses: A+B+C+D 无括号:A + B + C + D
  • A+B group: (A+B)+C+D A + B组:(A + B)+ C + D
  • B+C group: A+(B+C)+D B + C组:A +(B + C)+ D
  • C+D group: A+B+(C+D) C + D组:A + B +(C + D)
  • A+B and C+D groups: (A+B)+(C+D) A + B和C + D组:(A + B)+(C + D)
  • A+B+C group: (A+B+C)+D A + B + C组:(A + B + C)+ D
  • B+C+D group: A+(B+C+D) B + C + D组:A +(B + C + D)
  • A+B group + C: ((A+B)+C)+D A + B组+ C:((A + B)+ C)+ D
  • A + group B+C: (A+(B+C))+D A + B + C组:(A +(B + C))+ D
  • B+C group + D: A+((B+C)+D) B + C组+ D:A +(((B + C)+ D)
  • B + group C+D: A+(B+(C+D)) B + C + D组:A +(B +(C + D))

If you have more than 4 numbers there will be more patterns of parentheses grouping. 如果您有4个以上的数字,则会有更多的括号分组方式。

Here's an example (for 4 numbers): 这是一个示例(4个数字):

from itertools import permutations,combinations_with_replacement
numbers   = ["9","8","1","2"]
target    = 24
operators = ["+","-","*","/"]
groups    = ['X+X+X+X', 'X+X+(X+X)', 'X+(X+X)+X', '(X+X+X)+X', '(X+X)+X+X', 'X+(X+X+X)', '((X+X)+X)+X', 'X+(X+(X+X))', 'X+((X+X)+X)', '(X+X)+(X+X)', '(X+(X+X))+X']
seen      = set()
for values in permutations(numbers,len(numbers)):
    for operCombo in combinations_with_replacement(operators,len(numbers)-1):
        for oper in permutations(operCombo,len(numbers)-1):
            formulaKey = "".join(oper+values)
            if formulaKey in seen: continue # ignore variations on parentheses alone
            for pattern in groups:
                formula = "".join(o+p for o,p in zip([""]+list(oper), pattern.split("+")))
                formula = "".join(v+p for v,p in zip([""]+list(values),formula.split("X")))
                try:
                    if eval(formula) == target:
                        print(formula,"=",target)
                        seen.add(formulaKey)
                        break 
                except: pass

Groupings could result in divisions by zero, so a try:except block had to be added. 分组可能导致被零除,因此必须添加try:except块。

This produces the following result: 这将产生以下结果:

9*8/(1+2) = 24
9+8*2-1 = 24
9*8/(2+1) = 24
9-1+8*2 = 24
9-(1-8*2) = 24
9-1+2*8 = 24
(9-1)*2+8 = 24
9/(1+2)*8 = 24
9/((1+2)/8) = 24
9-(1-2*8) = 24
9+2*8-1 = 24
9/(2+1)*8 = 24
9/((2+1)/8) = 24
8+(9-1)*2 = 24
8*9/(1+2) = 24
8*9/(2+1) = 24
8-(1-9)*2 = 24
8/(1+2)*9 = 24
8/((1+2)/9) = 24
8+2*(9-1) = 24
8*2+9-1 = 24
8*2-1+9 = 24
8/(2+1)*9 = 24
8/((2+1)/9) = 24
8-2*(1-9) = 24
8*2-(1-9) = 24
2*(9-1)+8 = 24
2*8+9-1 = 24
2*8-1+9 = 24
2*8-(1-9) = 24

To generate the parentheses grouping patterns for more numbers, you can use this function: 要为更多数字生成括号分组模式,可以使用以下函数:

from itertools import product
import re
def groupPatterns(count,pattern=None):
    arr = pattern or "X"*count
    if len(arr) < 2 : return [arr]
    result = []
    for mid in range(1,len(arr)):
        leftPattern  = groupPatterns(count,arr[:mid])
        rightPattern = groupPatterns(count,arr[mid:])
        for left,right in product(leftPattern,rightPattern):
            result += [left + right]
            if len(left)  > 1 : result += ["(" + left + ")" + right]
            if len(right) > 1 : result += [left + "(" + right + ")"]
            if len(left) > 1 and len(right) > 1: 
                result += ["(" + left + ")(" + right + ")"]
    if pattern: return result # recursion
    patterns = [] # final, add "+" between X value placeholders or groups
    for pat in sorted(set(result),key=lambda x:len(x)):
        pat = re.sub("X(?=X)", r"X+",  pat)  # XX --> X+X
        pat = re.sub("X\(",    r"X+(", pat)  # X( --> X+(
        pat = re.sub("\)X",    r")+X", pat)  # )X --> )+X
        pat = re.sub("\)\(",   r")+(", pat)  # )( --> )+(
        patterns.append(pat)
    return patterns

And then replace groups = ["X+X+X+X",... with groups = groupPatterns(len(numbers)) in the previous example. 然后在上一个示例中,将groups = ["X+X+X+X",...替换为groups = groupPatterns(len(numbers))

OR, create a completely generic function for any number of values, with or without grouping and operator reuse: 或者,为任意数量的值创建一个完全通用的函数,无论是否进行分组和运算符重用:

from itertools import permutations,combinations_with_replacement
def numbersToTarget(numbers,target,reuseOper=True,allowGroups=True,operators=["+","-","*","/"]):   
    groups      = groupPatterns(len(numbers)) if allowGroups else [ "+".join("X"*len(numbers)) ]
    seen        = set()
    for values in permutations(numbers,len(numbers)):
        for operCombo in combinations_with_replacement(operators,len(numbers)-1) if reuseOper else [operators]:
            for opers in permutations(operCombo,len(numbers)-1):
                formulaKey = str(opers)+str(values)
                if formulaKey in seen: continue # ignore variations on parentheses alone
                for pattern in groups:
                    formula = "".join(o+p      for o,p in zip([""]+list(opers), pattern.split("+")))
                    formula = "".join(str(v)+p for v,p in zip([""]+list(values),formula.split("X")))
                    try:
                        if eval(formula) == target:
                            seen.add(formulaKey)
                            yield formula
                            break 
                    except: pass

for formula in numbersToTarget([9,8,1,2],24):
    print("24 =",formula)
for formula in numbersToTarget([9,8,1,2,5],0,allowGroups=False):
    print("0 =",formula)

Here is what I came up with using eval() to mathematically evaluate the string of math operators (note this is not a very secure method and malicious users could potentially hack your program through it. If you are deploying then maybe look at Evaluating a mathematical expression in a string ) 这是我使用eval()对数学运算符的字符串进行数学计算的结果(请注意,这不是一种非常安全的方法,恶意用户可能会通过该方法对您的程序进行黑客攻击。如果要进行部署,则可以看看评估数学函数字符串中的表达式

numbers = []
operators = ['+', '*', '-', '/']
desire = int(input("Enter the number you want: "))
num1 = input("Enter First number: ")
num2 = input("Enter Second number: ")
num3 = input("Enter Third number: ")
num4 = input("Enter Fourth number: ")
numbers.append(num1)
numbers.append(num2)
numbers.append(num3)
numbers.append(num4)

for operator1 in operators:
    for operator2 in operators:
        for operator3 in operators:
            problem = numbers[0] + operator1 + numbers[1] + operator2 + numbers[2] + operator3 + numbers[3]
            result = int(eval(problem))
            if result == desire:
                print("{} = {}".format(problem, result))

My first simple test 我的第一个简单测试

Enter the number you want: 40
Enter First number: 10
Enter Second number: 10
Enter Third number: 10
Enter Fourth number: 10

Yields 产量

10+10+10+10 = 40 10 + 10 + 10 + 10 = 40

A more complex test 更复杂的测试

Enter the number you want: 18
Enter First number: 6
Enter Second number: 3
Enter Third number: 4
Enter Fourth number: 4

Yeilds: Yeilds:

6*3+4-4 = 18 6 * 3 + 4-4 = 18

6*3*4/4 = 18 6 * 3 * 4/4 = 18

6*3-4+4 = 18 6 * 3-4 + 4 = 18

6*3/4*4 = 18 6 * 3/4 * 4 = 18

6/3+4*4 = 18 6/3 + 4 * 4 = 18

It should be noted though that this solution does not consider the various orders for your numbers. 但应注意,此解决方案未考虑您的电话号码的各种顺序。 I'll see if I can craft something more devious 我会看看我是否可以制作一些更狡猾的东西

UPDATE UPDATE

I've crafted a way to consider all permutations of numbers as well 我已经设计出一种方法来考虑数字的所有排列

def make_order_combinations():
    number_orders = []
    for i in range(4):
        for j in range(4):
            for k in range(4):
                for z in range(4):
                    if i != j and i != k and i != z and j != k and j != z and k != z:
                        number_orders.append((i, j, k, z))
    return number_orders


def solve_given_number_order(number_order):
    for operator1 in operators:
        for operator2 in operators:
            for operator3 in operators:
                problem = numbers[number_order[0]] + operator1 + numbers[number_order[1]] + operator2 + numbers[number_order[2]] + operator3 + numbers[number_order[3]]
                # print(problem)
                result = eval(problem)
                # print(result)
                if result == desire:
                    print("{} = {}".format(problem, result))

numbers = []
operators = ['+', '*', '-', '/']
desire = int(input("Enter the number you want: "))
num1 = input("Enter First number: ")
num2 = input("Enter Second number: ")
num3 = input("Enter Third number: ")
num4 = input("Enter Fourth number: ")
numbers.append(num1)
numbers.append(num2)
numbers.append(num3)
numbers.append(num4)

list_of_orders = make_order_combinations()
for order in list_of_orders:
    solve_given_number_order(order)

Now the test 现在测试

Enter the number you want: 67
Enter First number: 15
Enter Second number: 4
Enter Third number: 7
Enter Fourth number: 1

Yields 产量

15*4+7*1 = 67
15*4+7/1 = 67.0
15*4+1*7 = 67
15*4*1+7 = 67
15*4/1+7 = 67.0
15*1*4+7 = 67
15/1*4+7 = 67.0
4*15+7*1 = 67
4*15+7/1 = 67.0
4*15+1*7 = 67
4*15*1+7 = 67
4*15/1+7 = 67.0
4*1*15+7 = 67
4/1*15+7 = 67.0
7+15*4*1 = 67
7+15*4/1 = 67.0
7+15*1*4 = 67
7+15/1*4 = 67.0
7+4*15*1 = 67
7+4*15/1 = 67.0
7+4*1*15 = 67
7+4/1*15 = 67.0
7+1*15*4 = 67
7*1+15*4 = 67
7/1+15*4 = 67.0
7+1*4*15 = 67
7*1+4*15 = 67
7/1+4*15 = 67.0
1*15*4+7 = 67
1*4*15+7 = 67
1*7+15*4 = 67
1*7+4*15 = 67

Where you can see it does consider all possible rearrangement of the numbers as well. 在可以看到的地方,也确实考虑了所有可能的数字重排。 Order of operations does still apply though and therefore the output: 操作顺序仍然适用,因此输出:

1*7+4*15 = 67 1 * 7 + 4 * 15 = 67

Should be read as (1*7)+(4*15) = 67 应该读为(1 * 7)+(4 * 15)= 67

this is really not well tested (and probably does too much work) but may get you started: 这确实没有经过很好的测试(可能会做很多工作),但可能会让您入门:

from operator import mul, add, sub, truediv
from itertools import permutations, combinations_with_replacement

operators = (mul, add, sub, truediv)
desire = 24

numbers = [1, 9, 8, 2]

OP2SYM = {mul: '*', add: '+', sub: '-', truediv: '/'}

for op0, op1, op2 in combinations_with_replacement((mul, add, sub, truediv), 3):
    for n0, n1, n2, n3 in permutations(numbers, 4):
        # print(op0, op1, op2)
        # print(n0, n1, n2, n3)
        if op0(n0, op1(n1, op2(n2, n3))) == desire:
            print('{} {} ({} {} ({} {} {}))'.format(
                n0, OP2SYM[op0], n1, OP2SYM[op1], n2, OP2SYM[op2], n3))
        if op0(op1(n0, n1), op2(n2, n3)) == desire:
            print('({} {} {}) {} ({} {} {})'.format(
                n0, OP2SYM[op0], n1, OP2SYM[op1], n2, OP2SYM[op2], n3))
        if op2(op1(op0(n0, n1), n2), n3) == desire:
            print('(({} {} {}) {} {}) {} {}'.format(
                n0, OP2SYM[op0], n1, OP2SYM[op1], n2, OP2SYM[op2], n3))

it outputs 它输出

((8 * 2) + 9) - 1
((2 * 8) + 9) - 1

a simpler idea would be to constuct the strings of the form '6*3-4+4' and use ast.literal_eval to evaluate them 一个更简单的想法是构造形式为'6*3-4+4'的字符串,并使用ast.literal_eval对其求值

You can try with the permutations module inside itertools 您可以尝试使用itertools中置换模块

from itertools import permutations, combinations
numbers = ""
solutions = []
operators = "+*-/"
desire = int(input("Enter the number you want: "))
num1 = input("Enter First number: ")
num2 = input("Enter Second number: ")
num3 = input("Enter Third number: ")
num4 = input("Enter Fourth number: ")
#concatenate the input
numbers = num1 + num2 + num3 + num4    
#generate all possible permutations of this characters
num_permutations = [p for p in permutations(numbers)]
op_combinations = [p for p in combinations(operators,3)]

for n_perm in num_permutations:
   for op_perm in op_combinations:
      cur_expression = ""
      for i in range(3):
         cur_expression += n_perm[i] + op_perm[i]
      cur_expression += n_perm[3]
      tmp_solution = eval(cur_expression)
      if desire == tmp_solution:
         solutions.append(tmp_solution)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 查找给定数字的2个数字的所有可能组合/分区 - Find all possible combinations/partitions of 2 numbers for a given number 找出所有可能的偶数或奇数组合并对结果进行数学运算 - Find all possible combinations of even or odd numbers and perform mathematical operations on the result 查找具有给定总和的数字列表的所有组合 - Find all combinations of a list of numbers with a given sum 如何获取 4 位数字的所有可能组合的列表,其单个数字总和为 13,最后一位数字为 5 - how get list of all the possible combinations of 4 digit numbers whose individual digit sum is 13 and last digit is 5 in that number 找出所有可能的组合 - Find all possible combinations 如何计算1到N范围内的所有可能组合的数量? - How to calculate the number of all possible combinations for a range of numbers from 1 to N? 如何打印特定数字集中的所有数字组合? - How to print all number combinations from specific set of numbers? 如何从字母和数字中找到所有可能的组合 - How to find all combinations possible from alphabet and numbers 蟒蛇。 查找具有设定长度的所有可能的数字组合 - Python. Find all possible combinations of numbers with set length 找出 pandas dataframe 列中数字的所有可能组合,总和为 0 - Find all the possible combinations of the numbers in the column of pandas dataframe that sum to 0
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM