Вы пытаетесь сделать что-то, что невозможно.Если вы определите
def make_state(a,b,c,d,e,f):
return ((((((a)*4+b)*20+c)*10+d)*10+e)*5+f)*5
, то и make_state(3,13,7,8,3,2)
, и make_state(4,9,7,8,3,2)
оцениваются в одно и то же состояние (1269585).Таким образом, невозможно начать с 1269585 и декодировать это число обратно в исходный вектор.make_state()
не один-к-одному.Это теряет информацию.Меньший расчет state = (((((b)*20+c)*10+d)*10+e)*5+f)*5
также теряет информацию (по крайней мере, без строгих ограничений на записываемые векторы).В общем случае для любого целого числа x
функция f(a,b): return ax+b
не будет взаимно-однозначной, поэтому, если я что-то упустил, весь этот подход к кодированию последовательности чисел не является начальным.
С другой стороны, если есть известные верхние границы для чисел, то вы можете сделать что-то подобное.Например, если a,b,c,d,e,f
являются неотрицательными целыми числами, каждое из которых меньше 4,20,10,10,5,5
соответственно, то функция
def encode(a,b,c,d,e,f):
return 5*(5*(10*(10*(20*a+b)+c)+d)+e)+f
может быть инвертирована.Это следует из алгоритма деления , в котором говорится, что для любых целых чисел a,b
с b > 0
, a
может быть однозначно , записанным в форме a = b*q + r
с 0 <= r < b
.В приведенной выше функции f
в этом диапазоне может быть однозначно восстановлено после деления на 5
, как и часть в ()
в 5*( ... ) + f
.Оттуда вы можете восстановить e
и т. Д. Для этого достаточно серии 5 divmods
.Обратите внимание, что ограничение на a
не входит в расчет.
Для декодирования:
def decode(n):
q,f = divmod(n,5)
q,e = divmod(q,5)
q,d = divmod(q,10)
q,c = divmod(q,10)
a,b = divmod(q,20)
return a,b,c,d,e,f
Например:
>>> encode(3,13,7,8,3,2)
184467
>>> decode(184467)
(3, 13, 7, 8, 3, 2)
В общем:
def encode(numbers, choices):
#0 <= numbers[i] < choices[i] for all i
n = numbers[0]
for x,y in zip(numbers[1:],choices[1:]):
n = n*y + x
return n
def decode(n,choices):
numbers = []
for d in choices[:0:-1]:
n,r = divmod(n,d)
numbers.append(r)
numbers.append(n)
return numbers[::-1]
работает следующим образом:
>>> encode([3,13,7,8,3,2],[4,20,10,10,5,5])
184467
>>> decode(184467,[4,20,10,10,5,5])
[3, 13, 7, 8, 3, 2]