Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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_Algorithm_Permutation - Fatal编程技术网

Python 特定索引中某些元素的置换

Python 特定索引中某些元素的置换,python,algorithm,permutation,Python,Algorithm,Permutation,是否有可能找到列表(n=27)的所有排列,并且限制元素x0到x7只能位于排列的索引0到7中的任何位置 keys = [x0, x1, x2, x3, x4, x5, x6, x7 ... x26] 我需要它能够从第n个排列中“恢复”,因为将有很多排列,我不能在一次运行中测试它们。它可能必须是一个生成器(某种类型),所以我可以在生成每个置换时对其进行测试,否则它将很快耗尽内存 非常感谢任何指点 我考虑过的解决方案: permitted = [x0, x1, x2, x3, x4, x5, x6,

是否有可能找到列表(n=27)的所有排列,并且限制元素x0到x7只能位于排列的索引0到7中的任何位置

keys = [x0, x1, x2, x3, x4, x5, x6, x7 ... x26]
我需要它能够从第n个排列中“恢复”,因为将有很多排列,我不能在一次运行中测试它们。它可能必须是一个生成器(某种类型),所以我可以在生成每个置换时对其进行测试,否则它将很快耗尽内存

非常感谢任何指点

我考虑过的解决方案:

permitted = [x0, x1, x2, x3, x4, x5, x6, x7]

for p in itertools.permutations(keys):
   if p[0] not in permitted:
      continue
   if p[1] not in permitted:
      continue
   ...
   # if it passes all the limitations, test this permutation
   test(p)
问题是我不能生成所有的排列并在一次意外的运行中测试它们

我从这个答案中尝试了另一种方法:

从数学导入阶乘
定义ith_置换(i,seq,r=None):
li=列表(seq)
长度=长度(li)
如果r为无:
r=长度
res=[]
当前_阶乘=阶乘(长度)//阶乘(长度-r)

如果当前的_factorial请注意,您正在寻找一个排列
x0,…,x7
,然后是一个排列
x8,…,x26
。因此,一个双循环就可以了。

首先,您必须编写一个函数,它将给出列表中元素的第n个排列。然后可以将0..7子列表的排列与8..26子列表的排列组合起来

可以使用由阶乘组成的变量基来定义获得第n个置换的函数。例如,N个大小列表的第一个元素将以0*为基数、1*为基数、2*为基数。。。因此,您可以通过计算基数(N-1)的值来确定第一个元素的索引!把这个位置除以这个基数。该除法的剩余部分是第二个元素在N-1个剩余元素中的位置。可以递归地执行此过程,直到到达最后一个元素

例如:

from math import factorial

def nthPermute(A,n):
    if not A: return tuple()        
    i,j = divmod(n,factorial(len(A)-1))
    return (A[i],)+nthPermute(A[:i]+A[i+1:],j)
输出:

for i in range(24):
    print(i,nthPermute("ABCD",i))

0  ('A', 'B', 'C', 'D')
1  ('A', 'B', 'D', 'C')
2  ('A', 'C', 'B', 'D')
3  ('A', 'C', 'D', 'B')
4  ('A', 'D', 'B', 'C')
5  ('A', 'D', 'C', 'B')
6  ('B', 'A', 'C', 'D')
7  ('B', 'A', 'D', 'C')
8  ('B', 'C', 'A', 'D')
9  ('B', 'C', 'D', 'A')
10 ('B', 'D', 'A', 'C')
11 ('B', 'D', 'C', 'A')
12 ('C', 'A', 'B', 'D')
13 ('C', 'A', 'D', 'B')
14 ('C', 'B', 'A', 'D')
15 ('C', 'B', 'D', 'A')
16 ('C', 'D', 'A', 'B')
17 ('C', 'D', 'B', 'A')
18 ('D', 'A', 'B', 'C')
19 ('D', 'A', 'C', 'B')
20 ('D', 'B', 'A', 'C')
21 ('D', 'B', 'C', 'A')
22 ('D', 'C', 'A', 'B')
23 ('D', 'C', 'B', 'A')
A = "12345678ABCDEFGHIJKLMNOPQRS"
for g in range(0,factorial(19)*7,factorial(19)):
    for i in range(g,g+4):
        print(i,"".join(nthPerm_8_19(A,i)))

0                  12345678ABCDEFGHIJKLMNOPQRS
1                  12345678ABCDEFGHIJKLMNOPQSR
2                  12345678ABCDEFGHIJKLMNOPRQS
3                  12345678ABCDEFGHIJKLMNOPRSQ
121645100408832000 12345687ABCDEFGHIJKLMNOPQRS
121645100408832001 12345687ABCDEFGHIJKLMNOPQSR
121645100408832002 12345687ABCDEFGHIJKLMNOPRQS
121645100408832003 12345687ABCDEFGHIJKLMNOPRSQ
243290200817664000 12345768ABCDEFGHIJKLMNOPQRS
243290200817664001 12345768ABCDEFGHIJKLMNOPQSR
243290200817664002 12345768ABCDEFGHIJKLMNOPRQS
243290200817664003 12345768ABCDEFGHIJKLMNOPRSQ
364935301226496000 12345786ABCDEFGHIJKLMNOPQRS
364935301226496001 12345786ABCDEFGHIJKLMNOPQSR
364935301226496002 12345786ABCDEFGHIJKLMNOPRQS
364935301226496003 12345786ABCDEFGHIJKLMNOPRSQ
486580401635328000 12345867ABCDEFGHIJKLMNOPQRS
486580401635328001 12345867ABCDEFGHIJKLMNOPQSR
486580401635328002 12345867ABCDEFGHIJKLMNOPRQS
486580401635328003 12345867ABCDEFGHIJKLMNOPRSQ
608225502044160000 12345876ABCDEFGHIJKLMNOPQRS
608225502044160001 12345876ABCDEFGHIJKLMNOPQSR
608225502044160002 12345876ABCDEFGHIJKLMNOPRQS
608225502044160003 12345876ABCDEFGHIJKLMNOPRSQ
729870602452992000 12346578ABCDEFGHIJKLMNOPQRS
729870602452992001 12346578ABCDEFGHIJKLMNOPQSR
729870602452992002 12346578ABCDEFGHIJKLMNOPRQS
729870602452992003 12346578ABCDEFGHIJKLMNOPRSQ
排列顺序遵循列表中元素的顺序。如果列表已排序,则可以使用二进制搜索算法查找给定排列的索引:

def indexOfPermute(A,P):
    lo,hi = 0,factorial(len(A))-1
    while lo<=hi:
        mid = (lo+hi)//2
        p = nthPermute(A,mid)
        if   p<P: lo = mid+1
        elif p>P: hi = mid-1
        else: return mid

i = indexOfPermute("ABCD",tuple('BCAD'))
print(i)
# 8
输出:

for i in range(24):
    print(i,nthPermute("ABCD",i))

0  ('A', 'B', 'C', 'D')
1  ('A', 'B', 'D', 'C')
2  ('A', 'C', 'B', 'D')
3  ('A', 'C', 'D', 'B')
4  ('A', 'D', 'B', 'C')
5  ('A', 'D', 'C', 'B')
6  ('B', 'A', 'C', 'D')
7  ('B', 'A', 'D', 'C')
8  ('B', 'C', 'A', 'D')
9  ('B', 'C', 'D', 'A')
10 ('B', 'D', 'A', 'C')
11 ('B', 'D', 'C', 'A')
12 ('C', 'A', 'B', 'D')
13 ('C', 'A', 'D', 'B')
14 ('C', 'B', 'A', 'D')
15 ('C', 'B', 'D', 'A')
16 ('C', 'D', 'A', 'B')
17 ('C', 'D', 'B', 'A')
18 ('D', 'A', 'B', 'C')
19 ('D', 'A', 'C', 'B')
20 ('D', 'B', 'A', 'C')
21 ('D', 'B', 'C', 'A')
22 ('D', 'C', 'A', 'B')
23 ('D', 'C', 'B', 'A')
A = "12345678ABCDEFGHIJKLMNOPQRS"
for g in range(0,factorial(19)*7,factorial(19)):
    for i in range(g,g+4):
        print(i,"".join(nthPerm_8_19(A,i)))

0                  12345678ABCDEFGHIJKLMNOPQRS
1                  12345678ABCDEFGHIJKLMNOPQSR
2                  12345678ABCDEFGHIJKLMNOPRQS
3                  12345678ABCDEFGHIJKLMNOPRSQ
121645100408832000 12345687ABCDEFGHIJKLMNOPQRS
121645100408832001 12345687ABCDEFGHIJKLMNOPQSR
121645100408832002 12345687ABCDEFGHIJKLMNOPRQS
121645100408832003 12345687ABCDEFGHIJKLMNOPRSQ
243290200817664000 12345768ABCDEFGHIJKLMNOPQRS
243290200817664001 12345768ABCDEFGHIJKLMNOPQSR
243290200817664002 12345768ABCDEFGHIJKLMNOPRQS
243290200817664003 12345768ABCDEFGHIJKLMNOPRSQ
364935301226496000 12345786ABCDEFGHIJKLMNOPQRS
364935301226496001 12345786ABCDEFGHIJKLMNOPQSR
364935301226496002 12345786ABCDEFGHIJKLMNOPRQS
364935301226496003 12345786ABCDEFGHIJKLMNOPRSQ
486580401635328000 12345867ABCDEFGHIJKLMNOPQRS
486580401635328001 12345867ABCDEFGHIJKLMNOPQSR
486580401635328002 12345867ABCDEFGHIJKLMNOPRQS
486580401635328003 12345867ABCDEFGHIJKLMNOPRSQ
608225502044160000 12345876ABCDEFGHIJKLMNOPQRS
608225502044160001 12345876ABCDEFGHIJKLMNOPQSR
608225502044160002 12345876ABCDEFGHIJKLMNOPRQS
608225502044160003 12345876ABCDEFGHIJKLMNOPRSQ
729870602452992000 12346578ABCDEFGHIJKLMNOPQRS
729870602452992001 12346578ABCDEFGHIJKLMNOPQSR
729870602452992002 12346578ABCDEFGHIJKLMNOPRQS
729870602452992003 12346578ABCDEFGHIJKLMNOPRSQ
使用此函数,您可以使用nthPerm_8_19()函数,就像您有一个超长列表,其中包含元素的所有49047304484106240000个排列

def nthPerm_8_19(A,n):
    i,j = divmod(n,factorial(19))
    return nthPermute(A[:8],i)+nthPermute(A[8:],j)
要实现“可恢复”流程,您只需在虚拟排列列表中记录位置,并在恢复后从那里继续。您还可以使用位置“切分”计算以进行并行处理

索引方案还允许您“跳过”一大块排列。例如,如果您想要跳过排列直到位置11的下一个值,您可以通过添加基(26-11)的模补来更新索引

[编辑]

进一步细分(回应评论):

这可以直接推广到nthPermute()函数中,如下所示:

def nthPermute(A,n,chunks=None):
    if not A: return tuple()
    if chunks is None:
        if n>=factorial(len(A)): return None
        i,j = divmod(n,factorial(len(A)-1))
        return (A[i],)+nthPermute(A[:i]+A[i+1:],j)
    result = tuple()
    for size in reversed(chunks):
        base   = factorial(size)
        n,i    = divmod(n,base)
        A,a    = A[:-size],A[-size:]
        result = nthPermute(a,i) + result
    return result if n==0 else None
以及在反向函数中获取排列的索引(如果元素在块中排序):


这对阿兰很有帮助。由于置换的总数仍然很大,第n个置换8个置换19 func将如何改变,使其成为前8个元素,然后是下10个元素,最后是最后9个元素?
def nthPerm_8_10_9(A,n):
    i,j = divmod(n,factorial(10)*factorial(9))
    j,k = divmod(j,factorial(9))
    return nthPermute(A[:8],i) + nthPermute(A[8:18],j) + nthPermute(A[18:],k)
def nthPermute(A,n,chunks=None):
    if not A: return tuple()
    if chunks is None:
        if n>=factorial(len(A)): return None
        i,j = divmod(n,factorial(len(A)-1))
        return (A[i],)+nthPermute(A[:i]+A[i+1:],j)
    result = tuple()
    for size in reversed(chunks):
        base   = factorial(size)
        n,i    = divmod(n,base)
        A,a    = A[:-size],A[-size:]
        result = nthPermute(a,i) + result
    return result if n==0 else None
def indexOfPermute(A,P,chunks=None):
    lo,hi = 0,1
    for c in chunks or [len(A)]: hi *= factorial(c)
    hi -= 1
    while lo<=hi:
        mid = (lo+hi)//2
        p = nthPermute(A,mid,chunks)
        if   p<P: lo = mid+1
        elif p>P: hi = mid-1
        else: return mid
P = nthPermute(A,121645100408832000,[8,19])
print("".join(P),indexOfPermute(A,P,[8,19]))

# 12345687ABCDEFGHIJKLMNOPQRS 121645100408832000


P = nthPermute(A,26547069911040000,[8,10,9])
print("".join(P),indexOfPermute(A,P,[8,10,9]))
# 51234678ABCDEFGHIJKLMNOPQRS 26547069911040000


P = nthPermute(A,67722117120000,[6,6,9,6])
print("".join(P),indexOfPermute(A,P,[6,6,9,6]))
# 41235678ABCDEFGHIJKLMNOPQRS 67722117120000