Thanks to this answer, here is how I'm getting permutation index and permutation at an index:
def get_Cl(distinct):
Cl = []
for i in range(1, distinct+1): # i is distincct
c = [0] * i + [1, 0]
C = [c]
for l in range(2, distinct+1):
c = [
c[d] * d + c[d + 1] * (distinct - d)
for d in range(i + 1)
] + [0]
C.append(c)
Cl.append(C)
return Cl
def item_index(item, distinct, n_symbols, Cl):
length = len(item)
offset = 0
seen = set()
for i, di in enumerate(item):
for d in range(n_symbols):
if d == di:
break
if d in seen:
# test = Cl[distinct][length - 1 - i][len(seen)]
offset += Cl[distinct][length - 1 - i][len(seen)]
else:
offset += Cl[distinct][length - 1 - i][len(seen) + 1]
seen.add(di)
return offset
def item_at(idx, length, distinct, n_symbols, Cl):
seen = [0] * n_symbols
prefix = [0] * length
used = 0
for i in range(length):
for d in range(n_symbols):
if seen[d] != 0:
branch_count = Cl[distinct][length - 1 - i][used]
else:
branch_count = Cl[distinct][length - 1 - i][used + 1]
if branch_count <= idx:
idx -= branch_count
else:
prefix[i] = d
if seen[d] == 0:
used += 1
seen[d] = 1
break
return prefix
if __name__ == "__main__":
Cl = get_Cl(300)
item = item_at(idx=432,length=300,distinct=200, n_symbols=300, Cl=Cl)
print(item)
print(item_index(item=item, distinct=200, n_symbols=300, Cl=Cl))
It works fine unless numbers get bigger then it gets very slow. Wondered if it is possible to improve this code like this answer?
The reason I get Cl
in a separate line is that for a fixed distinct
there will be thousands of calls on item_at
and item_index
, so the Cl
is the same if distinct
is the same thus no need for call it for each item_at
or item_index
.
from Getting permutation index and permutation at index faster than the provided solution
No comments:
Post a Comment