I want to know whether the task explained below is even theoretically possible, and if so how I could do it.
You are given a space of N
elements (i.e. all numbers between 0
and N-1
.) Let's look at the space of all permutations on that space, and call it S
. The i
th member of S
, which can be marked S[i]
, is the permutation with the lexicographic number i
.
For example, if N
is 3, then S
is this list of permutations:
S[0]: 0, 1, 2
S[1]: 0, 2, 1
S[2]: 1, 0, 2
S[3]: 1, 2, 0
S[4]: 2, 0, 1
S[5]: 2, 1, 0
(Of course, when looking at a big N
, this space becomes very large, N!
to be exact.)
Now, I already know how to get the permutation by its index number i
, and I already know how to do the reverse (get the lexicographic number of a given permutation.) But I want something better.
Some permutations can be huge by themselves. For example, if you're looking at N=10^20
. (The size of S
would be (10^20)!
which I believe is the biggest number I ever mentioned in a Stack Overflow question :)
If you're looking at just a random permutation on that space, it would be so big that you wouldn't be able to store the whole thing on your harddrive, let alone calculate each one of the items by lexicographic number. What I want is to be able to do item access on that permutation, and also get the index of each item. That is, given N
and i
to specify a permutation, have one function that takes an index number and find the number that resides in that index, and another function that takes a number and finds in which index it resides. I want to do that in O(1)
, so I don't need to store or iterate over each member in the permutation.
Crazy, you say? Impossible? That may be. But consider this: A block cipher, like AES, is essentially a permutation, and it almost accomplishes the tasks I outlined above. AES has a block size of 16 bytes, meaning that N
is 256^16
which is around 10^38
. (The size of S
, not that it matters, is a staggering (256^16)!
, or around 10^85070591730234615865843651857942052838
, which beats my recent record for "biggest number mentioned on Stack Overflow" :)
Each AES encryption key specifies a single permutation on N=256^16
. That permutation couldn't be stored whole on your computer, because it has more members than there are atoms in the solar system. But, it allows you item access. By encrypting data using AES, you're looking at the data block by block, and for each block (member of range(N)
) you output the encrypted block, which the member of range(N)
that is in the index number of the original block in the permutation. And when you're decrypting, you're doing the reverse (Finding the index number of a block.) I believe this is done in O(1)
, I'm not sure but in any case it's very fast.
The problem with using AES or any other block cipher is that it limits you to very specific N
, and it probably only captures a tiny fraction of the possible permutations, while I want to be able to use any N
I like, and do item access on any permutation S[i]
that I like.
Is it possible to get O(1)
item access on a permutation, given size N
and permutation number i
? If so, how?
(If I'm lucky enough to get code answers here, I'd appreciate if they'll be in Python.)
UPDATE:
Some people pointed out the sad fact that the permutation number itself would be so huge, that just reading the number would make the task non-feasible. Then, I'd like to revise my question: Given access to the factoradic representation of a permutation's lexicographic number, is it possible to get any item in the permutation in O(as small as possible)?
0
and256^16
, and permute that to a different number in that range. – LenticN=10^10
, where specifyingi
would take around 40 gigabytes, but still you'd like to get item access to each item in the permutation without going over the ~5,000,000,000 items that preceded it. – LenticO(N log N)
, which means that it is asymptotically the same (within a constant factor) as the size of N<sup>N</sup>; in other words, you could use as an index the valid permutations amongst the total set of N-digit base-N numbers. Or to put it another way, the permutation itself, written out, is only a constant factor larger than the index. Perhaps that puts this question into perspective. – Chain