The following is what I am trying to achieve:
alpha = 'abcdefghijklmnopqrstuvwxyz0123456789'
items = ['item-a','item-b'...'item-n']
my_map = defaultdict()
for i, item in enumerate(items):
my_map[alpha[i]] = item
Here, I am creating a dictionary where each item is mapped against a single character. Every possible combination (i.e. ab7, so 3 items) can randomly be picked after which its value will be processed.
For n items a total of 2^n combinations exist. So for 6 items, the total of combinations that can be picked looks as follows:
['a','b','ab'....'bef'...'abcdef']
NOTE: combinations only occur once. In this situation 'ba' is the same as 'ab', therefor only 'ab' exists in the list.
Suppose I have the index of the combination, how can I get the combination that belongs to that index without calculating all possible combinations?
I have played around with the following but this only works for all possible combinations
import math
def get_bijective_val(n, alphabet):
base = len(alphabet)
digits = []
while n:
remainder = math.ceil(n/base)-1
digits.append(n - remainder*base)
n = remainder
digits.reverse()
return "".join(alphabet[digit-1] for digit in digits)
get_bijective_val(50,'abcdef')
(taken from https://stackoverflow.com/a/20446640/1251070)
I have tried to modify it but am unable to find the solution
This is the expected result:
>>> print(get_bijective_val(0, 'abcdef'))
>>> 'a'
>>> print(get_bijective_val(50, 'abcdef'))
>>> 'bef'
>>> print(get_bijective_val(63, 'abcdef'))
>>> 'abcdef'
For larger alphabets this algorithm is much faster than generating all combinations with itertools, but there is probably still a lot of potential for optimizations:
Small CLI and benchmarks here
For an alphabet of length 15,
get_combinationtook 0.228s andget_combination_bruteforcetook 39.525s to find all possible combinations one by one (173 times speedup).It works by first finding out how long the combination with the given index is and then reconstructing it element-wise:
n over kcombinations of lengthk, wherenis the alphabet size. So we find the length by subtractingn over kfor increasingkfrom the given index until it goes negative. The lastkis the length of the requested combination.kstarting with thex-th element of the alphabet, the remaining combination elements have to be chosen fromalphabet[x+1:]. With this information we can reconstruct each element like we calculatedkbefore.There may be a closed form solution to both of these steps, but I won't be the one to find it.