Eu quero codificar compactamente números inteiros positivos x
em bits, de uma maneira que permita a decodificação de volta nos números inteiros originais para um decodificador sem estado, sabendo o valor máximo m
de cada um x
; deve ser possível decodificar exclusivamente a concatenação de codificações, como é o caso da codificação de Huffman.
[A introdução acima motiva o resto, mas não faz parte da definição formal]
Notação: para qualquer número inteiro não negativo i
, n(i)
seja o número de bits necessário para representar i
em binário; esse é o menor inteiro não negativo de k
tal forma quei>>k == 0
i : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ..
n(i): 0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 ..
Eu quero uma função F(x,m)
definida para 0<x
e x<=m
, com saída, uma sequência de ' 0
' ou ' 1
', com estas propriedades:
F(x,m)
tem comprimento menor que2*n(x)
ou2*n(m)-1
, o que for menor.- Se
x<y
então:F(x,m)
não é mais do queF(y,m)
;F(x,m)
eF(y,m)
diferem em alguma posição ao longo deF(x,m)
;- há um
0
naF(x,m)
primeira posição.
- Quando por certas
m
propriedades 1 e 2 não se definir de forma únicaF(x,m)
para todos positivosx
no máximom
, se rejeitar qualquer codificação dando um maisF(x,m)
do que alguns codificação de outro modo aceitável, para a mais pequenax
para que o comprimento não coincidem.
Nota: No exemplo acima, implicitamente, 0<x
, 0<y
, 0<m
, x<=m
, e y<=m
, de modo que F(x,m)
e F(y,m)
são definidos.
É solicitado o programa mais curto que, dado qualquer um x
e m
atendendo às restrições acima e até 9 dígitos decimais, gera uma F(x,m)
consistência com as regras acima. A seguinte estrutura C (ou seu equivalente em outros idiomas) não é contada:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define C(c) putchar((c)?'1':'0') // output '0' or '1'
#define S(s) fputs((s),stdout) // output a string
typedef unsigned long t; // at least 32 bits
void F(t x,t m); // prototype for F
int main(int argc,char *argv[]){
if(argc==3)F((t)atol(argv[1]),(t)atol(argv[2]));
return 0;}
void F(t x,t m) { // counting starts on next line
} // counting ends before this line
Comentário: A propriedade 1 limita agressivamente o comprimento codificado; a propriedade 2 formaliza que a decodificação inequívoca é possível e canoniza a codificação; Afirmo (sem prova) que isso é suficiente para definir exclusivamente a saída de F
quando m+1
é uma potência de dois e que a propriedade 3 é suficiente para definir exclusivamente F
para outra m
.
Aqui está uma tabela parcial (artesanal; a primeira versão postada estava cheia de erros, desculpe):
x : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
F(x,1) : empty
F(x,2) : 0 1
F(x,3) : 0 10 11
F(x,4) : 0 10 110 111
F(x,5) : 0 10 110 1110 1111
F(x,6) : 0 100 101 110 1110 1111
F(x,7) : 0 100 101 1100 1101 1110 1111
F(x,8) : 0 100 101 110 11100 11101 11110 11111
F(x,15) : 0 100 101 11000 11001 11010 11011 111000 111001 111010 111011 111100 111101 111110 111111
11111
, tornando impossível a decodificação. Com a codificação proposta, a concatenação de várias saídas pode ser decodificada exclusivamente (inclusive com a máximam
alteração dinâmica). Eu tentei esclarecer isso.Respostas:
Python 3, 163 bytes
Ignore o
c=0
parâmetro, isso é um truque de golfe.Isso avidamente escolhe a menor representação possível para cada número, desde que os números restantes ainda sejam representáveis. Portanto, por construção, satisfaz exatamente as propriedades desejadas. Na verdade, não é tão difícil modificar esse código para suportar um conjunto diferente de regras de codificação, como resultado.
Por exemplo, aqui estão as saídas até
m=15
:fonte
Python, 171
Observe que as linhas que parecem começar com 4 espaços na verdade começam com uma guia.
Teste, com o script de teste do bitpwner:
Explicação:
Tudo isso se baseia na observação de que, entre dois elementos consecutivos do código, F (x, m) e F (x + 1, m), sempre adicionamos um ao número binário e depois multiplicamos por dois algumas vezes. Se essas etapas forem seguidas, é um código válido. O restante simplesmente testa para garantir que seja curto o suficiente.
Golfe: 175 -> 171: alterado 2 ** (2 * ... para 4 **
fonte
Python - 370
Cria uma árvore de huffman, equilibra-a de acordo com as regras e, em seguida, percorre a árvore para obter os valores finais.
Para uma solução mais sucinta baseada no padrão emergente, observe a resposta de isaacg.
É um bom exemplo de como uma abordagem completamente diferente pode resolver o problema.
Teste:
Resultados:
fonte
F(7,8)
de111110
está errado, por que tem comprimento 6, e "menos do que2*n(x)
" implica menos de 6.