Hotel binário de Hilbert


18

Nesse desafio, você será solicitado a implementar qualquer função (ou programa completo) que cumpra duas propriedades. Essas propriedades são:

  • Sua função deve ser uma função injetável (reversível) dos polinômios com coeficientes inteiros não negativos para os inteiros não negativos. Isso significa que não há duas entradas desiguais que podem ser mapeadas para uma saída igual.

  • Sua função deve preservar o número total de "em bits" desde a entrada até a saída. Isso significa que, se você contar os 1 bits de cada coeficiente do polinômio, sua soma deverá ser igual ao número de 1 bits na representação binária da saída. Por exemplo, 9está 1001em binário, por isso tem 2 1bits.


IO

Um polinômio inteiro não negativo é igual a uma lista infinita de números inteiros não negativos, de modo que após um certo ponto todos os números inteiros sejam zero. Assim, os polinômios podem ser representados por listas infinitas (embora isso provavelmente seja indesejável) ou por listas finitas com zeros implícitos após o final da lista.

A principal distinção entre polinômios e listas finitas é que adicionar um zero ao final de uma lista mudará a lista:

Listas

A adição de um zero ao final de um polinômio não altera seu valor:

Polinômios

Portanto, se sua função usa uma lista finita representando um polinômio como entrada, adicionar um zero não deve alterar o resultado.

Ao representar polinômios como listas, você pode representá-los com a primeira ou a última entrada representando o termo constante. Por exemplo, você pode ter uma das seguintes possibilidades:

Para a frente ou para trás

No primeiro caso, adicionar zeros ao final da lista não deve alterar o resultado; no segundo caso, adicionar zeros à frente da lista não deve alterar o resultado.

Obviamente, se o seu idioma suportar polinômios, você poderá considerá-los como entradas.

A saída deve ser uma saída inteira não negativa através de qualquer método padrão.


Isso é então as respostas serão pontuadas em bytes, com menos bytes sendo melhores.


É []ou [0]uma entrada válida?
JungHwan Min

1
@JungHwanMin Sim, ambos são, eles são o polinômio zero.
Assistente de trigo

Eu sei que você quer dizer para colocar 1 para dividir zeros, mas alguns aspectos podem trabalhar e não parecem tão bom ...
l4m2

1
@ l4m2 Sinto muito, mas não entendo nenhum dos seus comentários. No que diz respeito à sua pergunta, zeros à esquerda em quê? O polinômio, os coeficientes? Também não sei o que você quer dizer com "zeros não escritos".
Wheat Wizard

1
As imagens são realmente necessárias (ou seja, não podem ser representadas usando rich text) ??? Porque as pessoas sem a capacidade de ver imagens não podem ver o seu desafio na sua totalidade.
Mindwin

Respostas:


6

Gelatina , 8 bytes

BFṢḄæ«ÆẸ

Experimente online!

Inverso esquerdo, 5 bytes

Bċ0ÆE

Experimente online!

Como funciona

BFṢḄæ«ÆẸ  Main link. Argument: A (array)

B         Binary; convert each integer in A to base 2.
 F        Flatten; concatenate the resulting binary arrays.
  Ṣ       Sort the resulting bit array.
   Ḅ      Convert from base 2 to integer, yielding an integer x with as much set
          bits as there are set bits in A.
      ÆẸ  Unexponents; convert A = [a1, a2, ...] to y = (p1**a1 + p2**a2 + ...),
          where pn is the n-th prime number.
          By the fundamental theorem of arithmetic, the resulting integer is unique
          for each array A without trailing zeroes.
    æ«    Bitshift left; compute x * 2**y.

6

Wolfram Language (Mathematica) , 36 20 bytes

x#/.x->2^(#/.x->2)!&

Experimente online!

Toma um polinômio f (x) como entrada. Avalia y * f (y), onde y = 2 ^ (f (2)!). Lamentavelmente, isso significa que as saídas ficam muito grandes.

A avaliação de y * f (y) preservará o número de 1 bits sempre que y for uma potência 2 maior que qualquer coeficiente, o que é verdade para o valor escolhido acima. Escolhemos y = 2 ^ (f (2)!) Para tornar o resultado injetivo:

  • Duas entradas diferentes com o mesmo valor de y fornecerão saídas diferentes, porque estamos lendo essencialmente dois números diferentes na base y.
  • Se fixarmos k = f (2) e, portanto, y, o menor valor de y * f (y) é atingido quando a entrada é um polinômio constante igual ak eo maior valor é alcançado quando a entrada é o polinômio que fornece a base -2 expansão de k. No primeiro caso, y * f (y) = 2 ^ (k!) * K, e no segundo caso, y * f (y) <2 ^ (k! * Ceil (lg k)), que é menor que 2 ^ ((k + 1)!) * (k + 1).
  • Como resultado, para dois polinômios feg com f (2) <g (2), o número inteiro que obtemos de f será menor que o número inteiro que obtemos de g.

5

Wolfram Language (Mathematica) , 61 bytes

Tr[2^((2#2-1)2^#)&@@@Position[Reverse/@#~IntegerDigits~2,1]]&

Experimente online!

Dois números inteiros positivos podem ser mapeados para um único número inteiro positivo. Let a, bSer dois inteiros positivos. Então a, b -> (2a - 1) 2^(b-1)é uma bijeção de NxN a N.

Esta função encontra a posição de todos os 1bits na entrada (do lugar 1s) e aplica uma variante somente injetiva do mapa acima a cada posição. Então, cada número resultante é elevado à potência de dois e todos os números são somados (o que é aceitável, pois aplicamos um mapa NxN -> N injetivo).

Por exemplo:

{1, 2, 3}
{{1}, {1, 0}, {1, 1}}             (* Convert to binary *)
{{1}, {0, 1}, {1, 1}}             (* Reverse each *)
{{1, 1}, {2, 2}, {3, 1}, {3, 2}}  (* Position of 1s *)
{2, 12, 8, 24}                    (* Inject to N *)
{4, 4096, 256, 16777216}          (* Raise to the power of 2 *)
16781572                          (* Add *)

Função inversa (124 bytes)

##+#&~Fold~#&@*Reverse/@Normal@SparseArray[{Log2[j=#~BitAnd~-#],(#/j+1)/2}->1&@@@(Reverse[#~IntegerDigits~2]~Position~1-1)]&

Aqui está uma função inversa para testar a injetividade.

Experimente online!


5

Python 2 , 118 117 114 103 100 bytes

100 bytes de Jonathan Frech:

a=input()
while a[0]<1:a.pop(0)
y="".join("2"+bin(v)[2:]for v in a)
print~-2**y.count("1")<<int(y,3)

Experimente online!

103 bytes com possibilidade de golfe 1

a=input()
while a[0]<1:a.pop(0)
x="".join(map(bin,a))
print~-(1<<x.count("1"))<<int(x.replace(*"b2"),3)

Experimente online!

-15 bytes graças a Jonathan Frech

Ele cria um número que primeiro contém os "em bits" e depois a representação unária da matriz, interpretada como um número trinário.

O número trinário é criado convertendo os números em cadeias binárias ( 0bNNN) e substituindo bpor 2.

1 Eu poderia ter economizado 14 bytes convertendo-o em um número de base 12, mas o TIO ficou sem memória e decidi usá-lo.


@JonathanFrech Muito obrigado :)
fergusq

1

05AB1E , 14 bytes

gÅpImPoIbS{2β*

Experimente online!

Produz os mesmos resultados que a solução de Dennis 'Jelly, mas a técnica é um pouco diferente.

Quão?

Vamos tentar a entrada [1, 2, 3]:

gÅpImPoIbS{2β* | Full program.
               | STACK: [[1, 2, 3]]
               |
g              | Push the length.
               | STACK: [3]
 Åp            | Generate the first N primes.
               | STACK: [[2, 3, 5]]
   Im          | Push the input, and apply pairwise exponentiation.
               | STACK: [2, 9, 125]
     P         | Push the product.
               | STACK: 2250
      o        | Push 2 ** N.
               | STACK: 2 ** 2250 (way too large)
       Ib      | Push the input and convert to binary.
               | STACK: [2 ** 2250, ['1', '10', '11']].
         S{    | Sort all the characters.
               | STACK: [2 ** 2250, ['0', '1', '1', '1', '1']]
           2β  | Convert from binary.
               | STACK: [2 ** 2250, 15]
             * | Multiplication.
               | STACK: [2 ** 2250 * 15]
               | Implicitly print the top of the stack (2 ** 2250 * 15).


0

JavaScript 6, 96 83 bytes

x=>(t=x.map(k=>(x[0]+=k)&&2+k.toString(2)).join``).replace(/0|2/g,'')+'0'.repeat(t)

gera uma expressão binária

([1,2]) => 3*2^21210(Decimal)
([0,1,2]) => 3*2^21210
([1,2,0]) => 3*2^2121020
([1,2,3,4]) => 31*2^212102112100(Threotically)

zero levará a uma cadeia vazia representando zero
l4m2

replace(/0|2/g,0)parece também funcionar, mas mais difícil de decodificar
l4m2

Não tenho certeza x=>(t=x.map(k=>(x[0]+=k)&&2+k.toString(2)).join``).replace(/2/g,'0'.repeat(t)). Sinta-se bem, mas não pode provar
l4m2
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.