我想在(n 选择 p)binary 上“强加”顺序并能够对项目进行编码/解码。
您可以在下面看到 p=2 的示例。对于 p > 2 它将需要更多循环。顺便说一句,这个功能只是对一个特定顺序的说明,它可以是不同的一个,只需要用尽所有组合。
我追求的是编码/解码!
如果它使用 INDEX value 而不是 bitarray 会更好,即 10100 => (3,5)
import numpy as np
#should exhaust all (n choose p) possibilities
def order(p=2,n=4) :
p = 0
for i in range(n):
for j in range(i+1,n):
v = np.zeros(n,dtype=int)
v[i]=1; v[j]=1; p+=1
print(f'pos:{p} {v}')
def encode(pos,p=2,n=4):
pass #should return val at pos
def decode(value,p=2,n=4):
pass #should return pos of val
order(n=4)
print()
order(n=5)
-----
pos:1 [1 1 0 0]
pos:2 [1 0 1 0]
pos:3 [1 0 0 1]
pos:4 [0 1 1 0]
pos:5 [0 1 0 1]
pos:6 [0 0 1 1]
pos:1 [1 1 0 0 0]
pos:2 [1 0 1 0 0]
pos:3 [1 0 0 1 0]
pos:4 [1 0 0 0 1]
pos:5 [0 1 1 0 0]
pos:6 [0 1 0 1 0]
pos:7 [0 1 0 0 1]
pos:8 [0 0 1 1 0]
pos:9 [0 0 1 0 1]
pos:10 [0 0 0 1 1]
似乎是合法的 :
In [36]: [nth_combination(range(10),3,i) for i in range(10)]
Out[36]: [(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 1, 5), (0, 1, 6), (0, 1, 7), (0, 1, 8), (0, 1, 9), (0, 2, 3), (0, 2, 4)]
In [6]: [nth_combination(range(1000),5,i) for i in range(100000,100010)]
Out[6]:
[(0, 1, 2, 108, 989),
(0, 1, 2, 108, 990),
(0, 1, 2, 108, 991),
(0, 1, 2, 108, 992),
(0, 1, 2, 108, 993),
(0, 1, 2, 108, 994),
(0, 1, 2, 108, 995),
(0, 1, 2, 108, 996),
(0, 1, 2, 108, 997),
(0, 1, 2, 108, 998)]
In [7]: combination_index((0,1,2,108,990),range(1000))
Out[7]: 100001
回答1
下面是 encoding / 解码的递归实现。我想发出两个警告:
如果您要编码/解码非常大的 values,您可能会遇到 RecursionDepthExceeded
异常,就像大多数递归一样。但是,这将需要非常大的输入 values。
其次,由于列表连接(为了简单起见),这可能比它需要的慢很多。如果性能是一个问题,你应该传递一个累加器,并附加到列表中,而不是不断地连接 + 形成新的列表。那时,可能也将递归转换为迭代循环。
from math import comb
def encode(pos, n, p):
if p == n:
return [1] * n
if p == 0:
return [0] * n
if pos < comb(n-1, p-1):
return [1] + encode(pos, n-1, p-1)
else:
return [0] + encode(pos - comb(n-1, p-1), n-1, p)
def decode(value, n, p):
if all(value):
return 0
if not any(value):
return 0
head, *tail = value
if head == 1:
return decode(tail, n-1, p-1)
else:
return comb(n-1, p-1) + decode(tail, n-1, p)
例子:
for i in range(6):
e = encode(i, 4, 2)
d = decode(e, 4, 2)
print(i, e, i == d)
输出:
0 [1, 1, 0, 0] True
1 [1, 0, 1, 0] True
2 [1, 0, 0, 1] True
3 [0, 1, 1, 0] True
4 [0, 1, 0, 1] True
5 [0, 0, 1, 1] True