Hotel binario di Hilbert


18

In questa sfida ti verrà chiesto di implementare qualsiasi funzione (o programma completo) che soddisfi due proprietà. Tali proprietà sono:

  • La tua funzione deve essere una funzione iniettiva (reversibile) dai polinomi con valori interi non negativi con valori interi non negativi. Ciò significa che non è possibile associare due input disuguali a un output uguale.

  • La tua funzione deve preservare il numero totale di "su bit" dal suo input al suo output. Ciò significa che se si contano 1 bit di ciascun coefficiente del polinomio, la loro somma dovrebbe essere uguale al numero di 1 bit nella rappresentazione binaria dell'output. Ad esempio 9è 1001in binario, quindi ha 2 1bit.


IO

Un polinomio intero non negativo è uguale a un elenco infinito di numeri interi non negativi tale che dopo un certo punto tutti gli interi sono zero. Pertanto, i polinomi possono essere rappresentati da liste infinite (sebbene ciò sia probabilmente indesiderabile) o da liste finite con zeri impliciti dopo la fine della lista.

La distinzione chiave tra polinomi ed elenchi finiti è che l'aggiunta di uno zero alla fine di un elenco cambierà l'elenco:

elenchi

Mentre l'aggiunta di uno zero alla fine di un polinomio non cambia il suo valore:

polinomi

Pertanto, se la tua funzione prende un elenco finito che rappresenta un polinomio come input, l'aggiunta di uno zero non deve modificarne il risultato.

Quando si rappresentano i polinomi come elenchi, è possibile rappresentarli con la prima o l'ultima voce che rappresentano il termine costante. Ad esempio potresti avere una delle seguenti possibilità:

Avanti o indietro

Nel primo caso, l'aggiunta di zeri alla fine dell'elenco non dovrebbe modificare il risultato; nel secondo caso, l'aggiunta di zeri alla parte anteriore della lista non dovrebbe cambiare il risultato.

Naturalmente se la tua lingua supporta i polinomi puoi prenderli come input.

L'output dovrebbe essere un output intero non negativo tramite qualsiasi metodo standard.


Si tratta di quindi le risposte verranno classificate in byte, con un numero inferiore di byte migliori.


È []o [0]un input valido?
JungHwan Min

1
@JungHwanMin Sì, entrambi lo sono, sono il polinomio zero.
Wheat Wizard

So che intendi mettere 1 per dividere gli zeri, ma alcuni modi potrebbero funzionare e non sembrano così buoni ...
l4m2

1
@ l4m2 Mi dispiace, ma non capisco nessuno dei tuoi commenti. Per quanto riguarda la tua domanda, portando zeri su cosa? Il polinomio, i coefficienti? Non sono sicuro di cosa intendi con "zeri non scritti".
Wheat Wizard il

1
Le immagini sono davvero necessarie (cioè non possono essere rappresentate usando il rich text) ??? Perché le persone senza la capacità di vedere le immagini non possono vedere la tua sfida nella sua interezza.
Mindwin,

Risposte:


6

Gelatina , 8 byte

BFṢḄæ«ÆẸ

Provalo online!

Inverso sinistro, 5 byte

Bċ0ÆE

Provalo online!

Come funziona

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 byte

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

Provalo online!

Accetta un polinomio f (x) come input. Valuta y * f (y), dove y = 2 ^ (f (2)!). Purtroppo, ciò significa che le uscite diventano piuttosto grandi.

La valutazione di y * f (y) conserverà il numero di 1 bit ogni volta che y è una potenza di 2 maggiore di qualsiasi coefficiente, il che è vero per il valore scelto sopra. Scegliamo y = 2 ^ (f (2)!) Per rendere il risultato iniettivo:

  • Due input diversi con lo stesso valore di y daranno output diversi perché essenzialmente stiamo leggendo due numeri diversi nella base y.
  • Se fissiamo k = f (2) e quindi y, il valore più piccolo di y * f (y) si ottiene quando l'ingresso è un polinomio costante uguale a k e il valore più grande si ottiene quando l'ingresso è il polinomio che dà la base -2 espansione di k. Nel primo caso, y * f (y) = 2 ^ (k!) * K, e nel secondo caso, y * f (y) <2 ^ (k! * Ceil (lg k)), che è inferiore di 2 ^ ((k + 1)!) * (k + 1).
  • Di conseguenza, per due polinomi f e g con f (2) <g (2), l'intero che otteniamo da f sarà inferiore all'intero che otteniamo da g.

5

Wolfram Language (Mathematica) , 61 byte

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

Provalo online!

Due numeri interi positivi possono essere associati a un singolo numero intero positivo. Sia a, bdue numeri interi positivi. Quindi a, b -> (2a - 1) 2^(b-1)c'è una biiezione da NxN a N.

Questa funzione trova la posizione di tutti i 1bit nell'input (dalla posizione 1s) e applica una variante solo iniettiva della mappa sopra a ciascuna posizione. Quindi, ogni numero risultante viene elevato alla potenza di due e tutti i numeri vengono sommati (il che va bene poiché abbiamo applicato una mappa NxN -> N iniettiva).

Per esempio:

{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 *)

Funzione inversa (124 byte)

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

Ecco una funzione inversa per verificare l'iniettività.

Provalo online!


5

Python 2 , 118 117 114 103 100 byte

100 byte di 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)

Provalo online!

103 byte con possibilità di golf 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)

Provalo online!

-15 byte grazie a Jonathan Frech

Crea un numero che prima contiene "on bit" e quindi la rappresentazione unaria dell'array interpretata come un numero trinario.

Il numero trinario viene creato convertendo i numeri in stringhe binarie ( 0bNNN), quindi sostituendolo bcon 2.

1 Avrei potuto salvare 14 byte convertendolo in un numero base 12, ma TIO ha esaurito la memoria, quindi ho deciso di utilizzare questo.


@JonathanFrech Grazie mille :)
Fergusq,

1

05AB1E , 14 byte

gÅpImPoIbS{2β*

Provalo online!

Produce gli stessi risultati della soluzione Jelly di Dennis, ma la tecnica è leggermente diversa.

Come?

Proviamo l'input [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 byte

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

genera un'espressione binaria

([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 porterà a una stringa vuota che rappresenta zero
l4m2

replace(/0|2/g,0)sembra anche funzionare, ma più difficile da decodificare
l4m2 il

Non sono sicuro x=>(t=x.map(k=>(x[0]+=k)&&2+k.toString(2)).join``).replace(/2/g,'0'.repeat(t)). Sentiti bene, ma non posso provarlo
l4m2 il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.