简体   繁体   English

整数和 arrays 排列之间的惰性映射,而不生成所有排列

[英]lazy mapping between integers and arrays permutations without generating all the permutations

I want to generate a mapping between a set of integer arrays and integer values in python, eg for n=2 (size of the array) and m=2 (array item range), I want to have: I want to generate a mapping between a set of integer arrays and integer values in python, eg for n=2 (size of the array) and m=2 (array item range), I want to have:

{
   0: [0, 0, 0],
   1: [0, 0, 1],
   2: [0, 1, 1],
   3: [1, 0, 0],
   ...
   7: [1, 1, 1]

}

One way to do this is to use the itertools.product and do the following:一种方法是使用itertools.product并执行以下操作:

from itertools import product
import numpy as np
n = 2
m = 3
a = list(product(np.arange(n), repeat=3))
a = list(map(lambda l: list(l), a))
b = dict(zip(np.arange(len(a)), a))

and b will be:b将是:

{0: [0, 0, 0], 1: [0, 0, 1], 2: [0, 1, 0], 3: [0, 1, 1], 4: [1, 0, 0], 5: [1, 0, 1], 6: [1, 1, 0], 7: [1, 1, 1]}

and I can have the mentioned mapping eg我可以有上面提到的映射,例如

>>> b[1]
[0, 0, 1]

However, in my case the n=8 and m=16 and storing such a dictionary ( 8**16 entries.) will take more than 100 Gb?但是,在我的情况下, n=8m=16并存储这样的字典( 8**16个条目。)将占用超过 100 Gb? I want to know if there is a lazy way of generating each index of the b everytime I want to access that without generating the entire dictionary?我想知道每次我想访问它而不生成整个字典时是否有一种懒惰的方式来生成 b 的每个索引?

You can generate the xth element by taking the successive x//n**(i-1)%n for i that varies between m-1 and 0.您可以通过对在 m-1 和 0 之间变化的 i 取连续的x//n**(i-1)%n来生成第 x 个元素。

n = 3
m = 4

x = 6
[x//n**(i-1)%n for i in range(m, 0, -1)]

output: [0, 0, 2, 0] output: [0, 0, 2, 0]

as a function作为 function
def f(x, n, m):
    return [x//n**(i-1)%n for i in range(m, 0, -1)]

f(1, n=2, m=3)
# [0, 0, 1]

f(1234567890, n=8, m=16)
# [0, 0, 0, 0, 0, 1, 1, 1, 4, 5, 4, 0, 1, 3, 2, 2]

You can make a function instead of full map.您可以制作 function 而不是完整的 map。 Your output is actually array of size m representing value of input a in n-th scale of notation.您的 output 实际上是大小为 m 的数组,表示输入 a 的第 n 个符号的值。 If you want to make a map just save the result of the function in map if key doesn't exist.如果要制作 map,只需将 function 的结果保存在 map 中(如果密钥不存在)。

def f(a, n, m):
    res = []
    while a != 0:
        res = [a % n] + res
        a //= n
        m -= 1
    while m != 0:
        res = [0] + res
        m -= 1
    return res

If you want to manipulate the permutations as if you had a list but without generating the actual list, you can make a function that will give you then Nth permutation in a "virtual" list:如果您想像有一个列表一样操作排列但不生成实际列表,您可以制作一个 function ,它将在“虚拟”列表中为您提供第 N 个排列:

from math import factorial
def permCount(A,k): return factorial(len(A))//factorial(len(A)-k)
def permAtIndex(A,k,index):
    A      = list(A)
    base   = permCount(A,k)
    result = []
    for _ in range(k):                    # for required size
        base  //= len(A)                  # chunk size for position
        i,index = divmod(index,base or 1) # i is value index at position
        result.append(A.pop(i))           # build permutation
    return result 

This will give you the size of the permutation "list" and allow you to get a permutation at a given index:这将为您提供排列“列表”的大小,并允许您在给定索引处获得排列:

print(permCount([1,2,3,4],4))       # 24
print(permAtIndex([1,2,3,4],4,22))  # [4, 3, 1, 2]

print(permCount(range(15),10))              # 10897286400
print(permAtIndex(range(15),10,5897286400)) # [8,1,10,5,12,0,13,7,14,9]

You can also create a reverse function to give you the index of a given permutation:您还可以创建一个反向 function 来为您提供给定排列的索引:

def indexOfPerm(A,k,P):
    A      = list(A)
    base   = permCount(A,k)
    result = 0
    for n in P:            
        base //= len(A)  # chunk size for position
        i = A.index(n)   # index in remaining items
        result += base*i # position's component of index
        A.pop(i)         # next position on rest of items
    return result

print(indexOfPerm([1,2,3,4],4,[4, 3, 1, 2])) # 22
print(indexOfPerm(range(15),10,[8,1,10,5,12,0,13,7,14,9])) # 5897286400

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

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