Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 排列列表的有序排序_Python_Permutation_Lexicographic - Fatal编程技术网

Python 排列列表的有序排序

Python 排列列表的有序排序,python,permutation,lexicographic,Python,Permutation,Lexicographic,我正在尝试开发一种方法,用于在以下列表中查找特定序列的有序秩 a = list(sorted(itertools.combinations(range(0,5),3))) b = list(sorted(itertools.permutations(range(0,5),3))) a表示a的元素列表,因此秩的公式非常简单 我需要的是2个函数magic_rank_1和magic_rank_2,它们有以下定义 def magic_rank_1(perm_item,permutation_list_

我正在尝试开发一种方法,用于在以下列表中查找特定序列的有序秩

a = list(sorted(itertools.combinations(range(0,5),3)))
b = list(sorted(itertools.permutations(range(0,5),3)))
a
表示a的元素列表,因此秩的公式非常简单

我需要的是2个函数magic_rank_1和magic_rank_2,它们有以下定义

def magic_rank_1(perm_item,permutation_list_object): 
## permutation_list_object is actually b
    return list_object.index(perm_item)

def magic_rank_2(perm_item,permutation_list_object,combination_list_object):
## permutation_list_object is actually b and combination_list_object is actually a
    return combination_list_object.index(tuple(sorted(perm_item)))
所以基本上
magic_rank_2((0,1,2),b,a)=magic_rank_2((2,0,1),b,a)

听起来很容易。。但我有一些限制

  • 我无法使用indexof函数,因为我无法为每个项目搜索超过100000000个项目的列表
  • 我需要magic_rank_1和magic_rank_2是纯数学的,不使用任何排序函数、比较函数或搜索函数。我将拥有的所有信息是需要识别其等级的元组和字母表的最后一个字母(在本例中为5)
    • 当k=len(a)时,魔秩2不需要是介于0和k-1之间的数字,只要它是介于0和2^(上限((max_字母/2)+1))之间的唯一数字即可
我知道magic_rank_1可以用类似的方法计算,但有一点不同,输入字母表中的每个字母都被使用,在我的例子中,它是一个子集

最后是的,这应该是散列函数的替代品,目前使用的是散列函数,但我没有利用
magic_rank_2((0,1,2),b,a)=magic_rank_2((2,0,1),b,a)
这一事实。如果我可以,它将大大减少我的存储空间需求,因为我的序列长度实际上是5,因此如果我可以计算magic_rank_2的方法,我将我的存储需求减少到当前需求的1%

更新 -对于magic_rank_2,元组元素之间不应该有比较操作,即没有排序、最小值、最大值等


这只会使算法的效率低于常规散列。以下两个函数将根据给定的单词和字母表(或元组和列表)对组合和排列进行排序

功能相似,但差别不大:

  • new_alph
    的过滤方式不同
  • num
    den
    的计算是不同的
更新:

rank_comb2
不需要对输入单词进行排序(三元组):


这只考虑了magic_rank_1,所以不能将其标记为答案,否则效果很好。没问题,但您可以扩展一下magic_rank_2的功能吗?或者什么
rank\u comb(已排序(word),alph)
不符合您的要求?我已经提到了。。我不想对单词进行排序,因为它会显著降低性能,寻找一个纯粹的数学函数对3元素元组进行排序会显著降低性能?无论如何,我用一种不需要对输入单词进行排序的方法更新了答案,尽管它似乎效率较低,没有更多。如果您能够预先存储列表并为其编制索引以提高性能,那么像您所说的那样,
indexof
函数最好通过哈希实现。否则,由于
itertools.compositions
itertools.permutation
都是生成器,这意味着每次调用它们时,都要花时间迭代整个列表,而且速度很慢。您在magic_rank_2中的输入只需要排序一次。如果您需要多次调用
magic\u rank\u 2
,您可以将循环封装在
Cython
函数中。至于数学(?)方法,您可以查看
itertools
的源代码,以确定生成器迭代中元素的预期顺序。然后,您可以尝试根据预期的顺序计算perm_项的确切索引。我不会那样做,因为没有人知道这是否是一个NP难问题,是否需要博士学位。论文。我不会称之为NP难问题,最终的实现是针对c的。无论如何,我使用排序树进行排序(即log(n)),但由于我的单词长度为7-10位,这意味着13-22个排序比较操作被证明是一个瓶颈,我还需要利用自秩以来的受控冲突(x,y,z)=秩(y,z,x)@Mai 1)Python用于概念证明和原型设计,因此Python中的高效算法适用于C 2)我没有说树排序,我说排序树有很大的不同3)我是来这里寻求一种更有效的做事方法的。与其渴望得到你的答案,不如不要回答,如果你忍不住希望没有下一次,我很抱歉,我不能。祝你好运
import itertools
import math

def rank_comb(word, alph, depth=0):
    if not word: return 0

    if depth == 0:
        word = list(word)
        alph = sorted(alph)

    pos = 0
    for (i,c) in enumerate(alph):
        if c == word[0]:
            # Recurse
            new_word = [x for x in word if x != c]
            new_alph = [x for x in alph if x > c]
            return pos + rank_comb(new_word, new_alph, depth+1)
        else:
            num = math.factorial(len(alph)-i-1)
            den = math.factorial(len(alph)-i-len(word)) * math.factorial(len(word)-1)
            pos += num // den


def rank_perm(word, alph, depth=0):
    if not word: return 0

    if depth == 0:
        word = list(word)
        alph = sorted(alph)

    pos = 0
    for c in alph:
        if c == word[0]:
            # Recurse
            new_word = [x for x in word if x != c]
            new_alph = [x for x in alph if x != c]
            return pos + rank_perm(new_word, new_alph, depth+1)
        else:
            num = math.factorial(len(alph)-1)
            den = math.factorial(len(alph)-len(word))
            pos += num // den


#== Validation =====================================================================
# Params
def get_alph(): return range(8)
r = 6

a = list(sorted(itertools.combinations(get_alph(), r)))
b = list(sorted(itertools.permutations(get_alph(), r)))

# Tests
PASS_COMB = True
PASS_PERM = True
for (i,x) in enumerate(a):
    j = rank_comb(x, get_alph())
    if i != j:
        PASS_COMB = False
        print("rank_comb() FAIL:", i, j)

for (i,x) in enumerate(b):
    j = rank_perm(x, get_alph())
    if i != j:
        PASS_PERM = False
        print("rank_perm() FAIL:", i, j)

print("rank_comb():", "PASS" if PASS_COMB else "FAIL")
print("rank_perm():", "PASS" if PASS_PERM else "FAIL")
import itertools
import math

def rank_comb2(word, alph, depth=0):
    if not word: return 0

    if depth == 0:
        word = list(word)
        alph = sorted(alph)

    pos = 0
    for (i,c) in enumerate(alph):
        if c == min(word):
            # Recurse
            new_word = [x for x in word if x != c]
            new_alph = [x for x in alph if x > c]
            return pos + rank_comb2(new_word, new_alph, depth+1)
        else:
            num = math.factorial(len(alph)-i-1)
            den = math.factorial(len(alph)-i-len(word)) * math.factorial(len(word)-1)
            pos += num // den

r1 = rank_comb2([2,4,1], range(5))
r2 = rank_comb2([1,4,2], range(5))
r3 = rank_comb2([4,1,2], range(5))

print(r1, r2, r3)     # 7 7 7