简体   繁体   English

如何获得等于 Python 中结果数的列表的所有数学组合

[英]How to get all mathematical combinations of a list that equal a result number in Python

Background背景

We have a family tradition where my and my siblings' Christmas presents are identified by a code that can be solved using only numbers related to us.我们有一个家庭传统,我和我的兄弟姐妹的圣诞礼物是用一个代码来识别的,这个代码只能使用与我们相关的数字来解决。 For example, the code could be birth month * age + graduation year (This is a simple one).例如,代码可以是birth month * age + graduation year (这是一个简单的)。 If the numbers were 8 * 22 + 2020 = 2196 , the number 2196 would be written on all my Christmas presents.如果数字是8 * 22 + 2020 = 2196 ,那么 2196 将写在我所有的圣诞礼物上。

I've already created a Python class that creates a list for every sibling with every number related to them.我已经创建了一个 Python class ,它为每个兄弟姐妹创建了一个列表,其中包含与之相关的每个数字。 Currently the list is over 30 numbers, but it may grow to over 40.目前该列表有 30 多个数字,但可能会增长到 40 多个。

Question问题

Is there any way to test all the mathematical combinations of a list of numbers that equal a result number?有没有办法测试等于结果数的数字列表的所有数学组合? For example, findPossibleCombinations( [8, 7, 4, 22, 2020, 573], 2196 ) returns a list of lists that can create the result number?比如findPossibleCombinations( [8, 7, 4, 22, 2020, 573], 2196 )返回可以创建结果数的列表列表? So this function would return [8, 22, 2020] and any other lists it found that could be used to equal 2196. No number will ever be used more than once.因此,此 function 将返回 [8, 22, 2020] 以及它发现的任何其他可用于等于 2196 的列表。任何数字都不会被使用超过一次。

I'm sure there's a way to do it that would result in an O(N^47) algorithm (Joking, of course), but am wondering what the most optimized algorithm to accomplish this kind of outcome is?我确信有一种方法可以实现 O(N^47) 算法(当然是开玩笑),但我想知道实现这种结果的最优化算法是什么?

For the sake of computational time, limit the number of operations to 5-6 total.为了计算时间,将操作数限制为总共 5-6 个。 My parents aren't crazy and would probably never use more than 5-6 numbers to calculate the end result.我的父母并不疯狂,可能永远不会使用超过 5-6 个数字来计算最终结果。 I'd also limit operations to +, -, * and /, though I may need to add other operations for future years.我还将操作限制为 +、-、* 和 /,尽管我可能需要在未来几年添加其他操作。

Thank you for any and all help.感谢您的任何帮助。 I hope you at least get a laugh out of my weird family tradition.我希望你至少能从我奇怪的家庭传统中得到一笑。

Edit: Here's my class structure.编辑:这是我的 class 结构。 It could be optimized a lot more, but good enough for now.它可以进行更多优化,但现在已经足够了。 Any strings are converted to alphanumeric and inverse alphanumeric and added by letter.任何字符串都将转换为字母数字和反字母数字并按字母添加。 The "listofnums" is the list I'd want to use. “listofnums”是我想要使用的列表。

def getalpha( str, inverse ):
   "Converts string to alphanumeric array of chars"
   array = []
   for i in range(0, len(str)): 
      alpha = ord(str[i]) - 96
      if inverse:
        array.append(27 - alpha)
      else:
        array.append(alpha)
   return array;

class Person:
  def __init__(self, name, middlename, birthmonth, birthday, birthyear, age, orderofbirth, gradyear, state, zip):
    #final list
    self.listofnums = []
    self.listofnums.extend((birthmonth, birthday, birthyear, birthyear - 1900, age, orderofbirth, gradyear, gradyear - 2000, zip))
    letters = name + middlename + state
    #add all related alphanumeric letters
    self.listofnums.extend(getalpha(letters, False))
    self.listofnums.extend(getalpha(letters, True))

You need itertools.product .你需要itertools.product It gives a generator which yield all the tuples of the cartesian product of the sequences given.它给出了一个生成器,它产生给定序列的笛卡尔积的所有元组。

from itertools import product

values1 = range(3)     # replace with your candidate birth month values
values2 = range(3, 6)  # replace with your candidate age values
values3 = range(7, 9)  # replace with your candidate graduation year values 
target_values = {10, 20, 30}  # replace with your target values (results)
# target_values need to be a set for efficient lookup.
for val1, val2, val3 in product(values1, values2, values3):
    if val1 + val2 + val3 in target_values:  #replace with your function
        print(val1, val2, val3)

Ismael had a great response that got me on the right track.伊斯梅尔的反应很好,让我走上了正轨。 I had to combine a permutation of all operations with a combination of all numbers to get a list of all possible sets (of a list of numbers and a list of operations) that would reach a number in the target values.我必须将所有操作的排列与所有数字的组合结合起来,以获得将达到目标值中的数字的所有可能集合(数字列表和操作列表)的列表。

This answer does assume a constant to define the number of operations in the solution这个答案确实假设一个常数来定义解决方案中的操作数

#Master algorithm (Get the result set of all combinations of numbers and cartesian products of operations that reach a target_value, using only the number_of_numbers_in_solution)
#Example: sibling1.results[1] = [(3, 22, 4), (<built-in function add>, <built-in function add>), 29]. This means that 3 + 22 + 4 = 29, and 29 is in target_values

NUMBER_OF_OPERATIONS_IN_SOLUTION = 3
NUMBER_OF_NUMBERS_IN_SOLUTION = NUMBER_OF_OPERATIONS_IN_SOLUTION + 1
TARGET_VALUES = {22,27,29,38,39}

import operator
from itertools import product
from itertools import combinations

def getresults( list ):
  #Add the cartesian product of all possible operations to a variable ops
  ops = []
  opslist = [operator.add, operator.sub, operator.mul, operator.truediv]
  for val in product(opslist, repeat=NUMBER_OF_OPERATIONS_IN_SOLUTION):
    ops.append(val)

  #Get the result set of all combinations of numbers and cartesian products of operations that reach a target_value
  results = []
  for x in combinations(list, NUMBER_OF_NUMBERS_IN_SOLUTION):
      for y in ops:
          result = 0
          for z in range(len(y)):
              #On the first iteration, do the operation on the first two numbers (x[z] and x[z+1])
              if (z == 0):
                  result = y[z](x[z], x[z+1])
              #For all other iterations, do the operation on the current result and x[z+1])
              else:
                  result = y[z](result, x[z+1])
      if result in TARGET_VALUES:
          results.append([x, y, result])
  print(len(results))
  return results

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM