Почему это дискретное кодирование не рассчитывается должным образом?Я что-то пропустил? - PullRequest
0 голосов
/ 13 июня 2019

Я пытаюсь закодировать некоторые факторы в дискретное число, а затем преобразовать дискретное число обратно в его факторы - но как только я добавлю достаточное количество факторов, обратный процесс не покажет правильные числа.

a = 3
b = 13
c = 7
d = 8
e = 3
f = 2

state = (((((b)*20+c)*10+d)*10+e)*5+f)*5
# If i add "a*4" to the front of the line (as shown in this line below), A and B is no longer showing correct

state = ((((((a)*4+b)*20+c)*10+d)*10+e)*5+f)*5

print(state)

print("f:", state // 5 % 5)
state = state // 5
print(state)

print("e:", state // 5 % 5)
state = state // 5
print(state)

print("d:", state // 10 % 10)
state = state // 10
print(state)

print("c:", state // 10 % 10)
state = state // 10
print(state)

print("b:", state // 20 % 20)
state = state // 20
print(state)

print("a:", state // 4 % 4)
state = state // 4
print(state)

1 Ответ

2 голосов
/ 13 июня 2019

Вы пытаетесь сделать что-то, что невозможно.Если вы определите

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]
...