Python 查找字母(列表)的第n个组合(增量方法)

Python 查找字母(列表)的第n个组合(增量方法),python,combinations,permutation,dynamic-programming,Python,Combinations,Permutation,Dynamic Programming,给定一个字母表列表,Pythonic找到第n个组合的方法是什么 # a = list("abc") 预期产出(补偿): (这需要Python2.7,但是可以很容易地为早期版本的itertools重写。)您的示例是base3数字 将n转换为base3(或字母表的任意长度)。然后用字母表中的符号替换“数字” 这允许您查找第n个值,而无需使用itertools生成之前的所有n-1项,从而生成沿线的所有组合: def powerprod(iterable): s = list(iterable

给定一个字母表列表,Pythonic找到第n个组合的方法是什么

# a = list("abc")
预期产出(补偿):


(这需要Python2.7,但是可以很容易地为早期版本的itertools重写。)

您的示例是base3数字

n
转换为base3(或字母表的任意长度)。然后用字母表中的符号替换“数字”


这允许您查找第n个值,而无需使用itertools生成之前的所有n-1项,从而生成沿线的所有组合:

def powerprod(iterable):
    s = list(iterable)
    for r in itertools.count(1):
        for c in itertools.product(s, repeat=r):
            yield c
演示:

更新

好吧,@gnibbler方法不起作用,因为不要区分
001
1
以及类似的组合。这里有一个更快的方法来获得第n个组合:

from itertools import product, islice

def max_sum_n_pow_lower_x(x, n):
    """ returns tuple of number of summand and maximal sum
        of form `n` + `n`**2 + `n`**3  not greater than `x` """
    i, c, s = 1, 0, 0
    while s < x:
       i *= n
       c += 1
       s += i
    return c-1, s-i

def get_nth_pow(iterable, n):
    l = list(iterable)
    repeat, start_from = max_sum_n_pow_lower_x(n, len(l))
    prod = itertools.product(l, repeat=repeat+1)
    return ''.join(list(islice(prod, n-start_from))[-1])
正如对gnibbler答案的评论,您想要使用的是a,其中字母表中的字符是数字

以下是如何在代码中执行此操作:

import math

def get_bijective_val(n, alphabet):
    base = len(alphabet)
    digits = []
    while n:
        remainder = math.ceil(n/base)-1
        digits.append(n - remainder*base)
        n = remainder
    digits.reverse()
    return "".join(alphabet[digit-1] for digit in digits)
即使对于非常大的数字或很长的字母表,这也应该有效。它的运行时间与输出字符串的长度成正比,或与字母表长度相等的整数的
log

下面是一个运行示例:

>>> for i in range(40):
    print(i, get_bijective_val(i, "eht"))


0 
1 e
2 h
3 t
4 ee
5 eh
6 et
7 he
8 hh
9 ht
10 te
11 th
12 tt
13 eee
14 eeh
15 eet
16 ehe
17 ehh
18 eht
19 ete
20 eth
21 ett
22 hee
23 heh
24 het
25 hhe
26 hhh
27 hht
28 hte
29 hth
30 htt
31 tee
32 teh
33 tet
34 the
35 thh
36 tht
37 tte
38 tth
39 ttt

“n”是什么意思?你看过itertools powerset配方了吗?我记录了所有的组合,所以当我有了所需的组合数时,我会终止循环。powerset的问题是它在('a','b','c')之后会断开,但我确实想在('a','b','c'),到('a','a','a','a','a','a')等等之后继续。这是一个非常聪明的方法。荣誉我喜欢。这些不是基数3。它们是,因为012和12是不同的。你如何准确地用字母替换“数字”!请您详细说明一下好吗?@alko您有什么建议,如何用字母表中的符号替换“数字”吗?没有生成正确的组合,对于“eht”和n=34,最后一个组合应该是“the”,它不匹配,而不是Isling
product
,一旦你有了几何级数的和,你就可以从
n
中减去它,然后你就可以使用基展开。@DSM可能是的,我考虑过了。但我现在有点厌倦了实现它:)它还能处理像“4125383079316”这样的max int吗?似乎引发了一个错误引发了一个“ValueError:islice()的停止参数必须为None或整数:0@Vanthewilderperson嘿,该要求未包含在规范中:)请参阅DSM注释
from itertools import product, islice

def max_sum_n_pow_lower_x(x, n):
    """ returns tuple of number of summand and maximal sum
        of form `n` + `n`**2 + `n`**3  not greater than `x` """
    i, c, s = 1, 0, 0
    while s < x:
       i *= n
       c += 1
       s += i
    return c-1, s-i

def get_nth_pow(iterable, n):
    l = list(iterable)
    repeat, start_from = max_sum_n_pow_lower_x(n, len(l))
    prod = itertools.product(l, repeat=repeat+1)
    return ''.join(list(islice(prod, n-start_from))[-1])
>>> get_nth_pow('eht', 34)
'the'
import math

def get_bijective_val(n, alphabet):
    base = len(alphabet)
    digits = []
    while n:
        remainder = math.ceil(n/base)-1
        digits.append(n - remainder*base)
        n = remainder
    digits.reverse()
    return "".join(alphabet[digit-1] for digit in digits)
>>> for i in range(40):
    print(i, get_bijective_val(i, "eht"))


0 
1 e
2 h
3 t
4 ee
5 eh
6 et
7 he
8 hh
9 ht
10 te
11 th
12 tt
13 eee
14 eeh
15 eet
16 ehe
17 ehh
18 eht
19 ete
20 eth
21 ett
22 hee
23 heh
24 het
25 hhe
26 hhh
27 hht
28 hte
29 hth
30 htt
31 tee
32 teh
33 tet
34 the
35 thh
36 tht
37 tte
38 tth
39 ttt