获取python中的置换总数

获取python中的置换总数,python,rubygems,Python,Rubygems,好的,我写了一个函数/方法,在这个函数/方法中,我在某个if条件大部分失败后执行一些操作,但只有1-2次是真的 这是我的代码: def solve_current_level(self): self.remaining_possibilities = list(self.remaining_possibilities) if len(self.remaining_possibilities) > 10 ** 6: #self.reduce_weapon_op

好的,我写了一个函数/方法,在这个函数/方法中,我在某个if条件大部分失败后执行一些操作,但只有1-2次是真的

这是我的代码:

def solve_current_level(self):
    self.remaining_possibilities = list(self.remaining_possibilities)
    if len(self.remaining_possibilities) > 10 ** 6:
        #self.reduce_weapon_options()
        pass

    guess = list(random.choice(self.remaining_possibilities))
    response = self.client.solve_level(self.current_level.levelNum, guess)

    if 'roundsLeft' in response:
        self.reset_remaining_possibilities()
        return None
    elif 'response' not in response:
        return response

    self.remaining_possibilities=[possibility for possibility in self.remaining_possibilities if game.Game_evaluate(guess, list(possibility)) == response['response']]
    return None
现在,当生成非常大的排列,然后将其转换为列表以检查长度是否超过10**6,然后执行其他操作并返回时,就会出现问题。这是我目前的解决方案,但问题是当它变得非常巨大的脚本被杀死。我将这段代码从ruby转换而来,在ruby中,您可以获得枚举数的大小,而无需将其转换为list,而且这个问题在ruby中从未发生过

以下是ruby中的代码:

def solve_current_level
  reduce_weapon_options if @remaining_possibilities.size > 10 ** 6
  if !@remaining_possibilities.kind_of?(Array)
    @remaining_possibilities = @remaining_possibilities.to_a
  end

  guess = @remaining_possibilities.sample
  response = @client.solve_level(@current_level.levelNum, guess)

  if response['roundsLeft']
    reset_remaining_possibilities
    return Nil
  elsif !response['response']
    return response
  end

  @remaining_possibilities.select! do |possibility|
    Game.evaluate(guess, possibility) == response['response']
  end
  return Nil
end
现在您可以看到,在ruby代码中,排列的长度是在转换为数组/散列以继续处理之前计算出来的,如果这个数字大于10**6,那么它将调用另一个方法“reduce\u-bool\u-options”。虽然在python中,如果不先转换为列表,就无法获得生成器的长度,但我需要它以这种方式工作,因为此时,当我获得更大的范围时,它会阻塞并被我的服务器杀死。我不能扩展ram,因为我需要像ruby一样使用更少的ram,我绝对希望避免

self.remaining_posabilities=列表(self.remaining_posabilities)

如果条件已通过/失败,则在python中使用此选项

注意:我正在使用itertools.permutations计算置换,这些置换后来保存在“self.remaining\u可能性”中

以下是python和ruby中的代码:

return (0...@numWeapons).to_a.permutation(@numGladiators)
(THIS RETURNS AN ENUMERATOR OBJECT)

return it.permutations(range(0, self.numWeapons), self.numGladiators)
(THIS RETURNS A GENERATOR OBJECT)

解决此问题的最简单方法可能是使用排列公式计算生成的排列数,该公式可定义为:

from math import factorial
def nPr(n, r):
    return int(factorial(n)/factorial(n-r))
但是,这要求该数据可用,或者长度从创建原始置换生成器的位置开始传递。如果情况并非如此,出于某种原因,可以使用
itertools.tee()
从第一个生成器生成第二个生成器,并仅用于计数:

def solve_current_level(self):
    self.remaining_possibilities, perm_count = itertools.tee(self.remaining_possibilities)
    # exhausting the 'teed' generator, leaving the 'original' intact:
    num_perm = sum(1 for _ in perm_count)
    if num_perm > 10 ** 6:
        #self.reduce_weapon_options()
        pass
    # here we can still use self.remaining_possibilities
    .
    .
    .

由于您已经在使用
itertools
,我想这不是一个太重的解决方案,但它仍然需要您浏览整个列表。不过,内存占用要小得多。

解决这一问题的最简单方法可能是使用排列公式计算生成的排列数,该公式可以定义为:

from math import factorial
def nPr(n, r):
    return int(factorial(n)/factorial(n-r))
但是,这要求该数据可用,或者长度从创建原始置换生成器的位置开始传递。如果情况并非如此,出于某种原因,可以使用
itertools.tee()
从第一个生成器生成第二个生成器,并仅用于计数:

def solve_current_level(self):
    self.remaining_possibilities, perm_count = itertools.tee(self.remaining_possibilities)
    # exhausting the 'teed' generator, leaving the 'original' intact:
    num_perm = sum(1 for _ in perm_count)
    if num_perm > 10 ** 6:
        #self.reduce_weapon_options()
        pass
    # here we can still use self.remaining_possibilities
    .
    .
    .

由于您已经在使用
itertools
,我想这不是一个太重的解决方案,但它仍然需要您浏览整个列表。但是内存占用要小得多。

我有一个问题,你可以看到如果条件大于10**6时检查生成的排列的大小,则调用另一种方法,该方法放弃排列,改为使用组合,因此,您能否让我知道,在不实际执行“it.combines(range(0,self.numWeapons),self.numGladiators)”的情况下,我如何找到可能的组合的大小?对于组合,您可以使用定义为
def nCr(n,r):返回int(阶乘(n)/(阶乘(n-r)*阶乘(r))的
nCr
而不是
nPr
。在Python3.8+
math.comb
math.perm
中,我有一个问题,您可以看到当生成的排列大于10**6时,检查其大小的if条件被调用了另一个方法,它放弃了排列而改为使用组合,因此,您能否让我知道,在不实际执行“it.combines(range(0,self.numWeapons),self.numGladiators)”的情况下,我如何找到可能的组合的大小?对于组合,您可以使用定义为
def nCr(n,r):返回int(阶乘(n)/(阶乘(n-r)*阶乘(r))的
nCr
而不是Python3.8+
math.comb
math.perm
中的
nPr