It is something a bit complex to explain here, but the code bellow takes a 128-bit number and converts it into a permutation matrix, a beast which I have already faced before. The matrix is represented as a list of numbers. Each number is a row.
The way I've found to do the mapping number->matrix was to convert the number through a multi-radix (or something that could be considered one) numeric system, so each digit corresponds to a row in the matrix. Since there can't be duplicate rows, some offset magic was needed (that is one of the uses of map taboo
used below).
How could this code be improved regarding data structures and use of loops?
More conceptually, what about my choice of conversion through a multi-radix system?
Could it be simpler and still be a perfect mapping from naturals to permutation matrices?
ps. There are 2^128 numbers and 35! matrices. 2^128 < 35!
, So all numbers can have a unique corresponding matrix.
from sortedcontainers import SortedSet, SortedDict
def permutmatrix2int(m):
"""Convert permutation matrix 35x35 to number."""
taboo = SortedSet()
digits = []
rowid = 34
for bit in m[:-1]:
bitold = bit
for f in taboo:
if bitold >= f:
bit -= 1
taboo.add(bitold)
digits.append(bit)
rowid -= 1
big_number = digits[0]
pos = 0
base = b = 35
for digit in digits[1:]:
big_number += b * digit
pos += 1
base -= 1
b *= base
return big_number
def int2permutmatrix(big_number):
"""Convert number to permutation matrix 35x35."""
taboo = SortedDict()
res = big_number
base = 35
bit = 0
while base > 1:
res, bit = divmod(res, base)
if res + bit == 0:
bit = 0
for ta in taboo:
if bit >= ta:
bit += 1
base -= 1
taboo[bit] = base
for bit in range(35):
if bit not in taboo:
break
taboo[bit] = base - 1
return list(map(
itemgetter(0), sorted(taboo.items(), reverse=True, key=itemgetter(1))
))