Permutation index Python
Interface


The parameters passed to the function are not orthogonal; they are subject to a number of restrictions, such as


length == len(numbers)
length == len(str(target))
target is composed of precisely the elements of numbers



If any restriction is violated, the function fails with an exception, or produces the wrong result. You may want to validate the input, or revise the interface to infer as much as possible from as little as necessary.

For example, it is reasonable to assume that length is len(numbers), and don't pass it at all. It is also reasonable to assume that target is well formed, and infer the alphabet from it.


By passing target as an integer you severely restrict the utility of a function. I highly recommend to pass it as a list of (comparable) elements.

Efficiency

First obvious inefficiency is recalculation of factorial, which drives the complexity quadratic by length. I recommend precompute factor = factorial(length) before the loop, and do

    factor /= length
    ind += factor * times
    length -= 1


to reduce the complexity to linear.

Second, extraction of leading digit also involves heavyweight computations. Even if the target is passed as integer, you'd be better off by converting it to an iterable, e.g.

    target = str(target)


and access individual digits positionally. And let me reiterate, it is better to pass target as iterable in the first place.