Enumerazione dei vettori N-dimensionali


17

Dato un numero intero positivo k > 1e un numero intero non negativo i, genera una ktupla (o kvettore tridimensionale) di numeri interi non negativi. Per ogni k, la mappa da ℕ a ℕ k , deve essere biunivoca . Cioè, ogni input idovrebbe produrre una tupla diversa e ogni possibile tupla deve essere prodotta da un input i.

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

È possibile utilizzare qualsiasi formato elenco semplice, chiaro e non ambiguo per l'output.

La tua soluzione non dovrebbe imporre limiti artificiali ke, ituttavia, potresti supporre che si adattino alla dimensione intera nativa della tua lingua. Per lo meno, è necessario supportare valori fino a 255, anche se anche la dimensione intera nativa è inferiore a quella.

In ogni caso 1 < k < 32, il tuo codice dovrebbe produrre un risultato in pochi secondi (ovviamente, se la tua risposta non supporta così tanto a causa della regola precedente, il limite viene adattato di conseguenza). Questo dovrebbe essere alcun problema: è possibile risolvere questo problema in modo tale che funziona fino a 2 128 nel giro di pochi secondi, ma il limite è lì per risposte Evitare che in realtà iterare da a per trovare il risultato.i < 231i0i

Includi nella risposta una descrizione della mappatura scelta e una giustificazione del motivo per cui è biiettiva (questa non deve essere una prova formale).

Questo è il codice golf, la risposta più breve (in byte) vince.

Sfide correlate

Risposte:


5

Pyth, 15 12 byte

ms+0_%Q>_zdQ

Suite di test

La mia trasformazione è simile a quella di xnor, ma nella base 10. Funziona decomprimendo l'input in k numeri separati:

n = 21003034
k = 3

21003034
 1  3  4    134
2  0  3     203
  0  0        0

I numeri sono ordinati in posizione decrescente della cifra più a destra, in modo che siano possibili tutti gli ordini di qualsiasi gruppo di numeri.

Il modo in cui funziona il codice è invertire l'input, quindi tagliare le ultime 0, 1, ... k-1cifre, quindi prendere ogni kseconda cifra, invertire di nuovo, attaccare 0a all'inizio e convertire in int.


4

CJam, 20 byte

q~({4b2fmd2/z2fb~p}*

La mappatura è biiettiva poiché applica la mappatura da questa risposta k - 1 volte.

Il programma legge l'ingresso come i k. Provalo online nell'interprete CJam .

Idea

Possiamo costruire una mappatura biiettiva f: N → N 2 definendo f (i) come segue:

  • Converti i nella matrice delle sue cifre binarie.

  • Prependi uno 0 a questo array se c'è un numero dispari di cifre.

  • Deinterlacciare l'array risultante, formandone di nuovi nel processo.

  • Converti quelle matrici dalla base 2 all'intero. Definire f 1 (i) e f 2 (i) come risultati.

Per ottenere una mappatura biiettiva g: N → N 3 , possiamo definire g (n): = (f 1 (i), f 1 (f 2 (i)), f 2 (f 2 (i))) .

Per ottenere una mappatura biiettiva h: N → N 4 , possiamo definire h (i): = (g 1 (i), g 2 (i), f 1 (g 3 (i)), f 2 (g 3 ( i))) .

Continuando il processo sopra, arriviamo alla fine a una mappa biiettiva N → N k .

Codice

q~      e# Read and evaluate all input. This pushes i and k.
({      e# Do k-1 times:
  4b    e#   Convert the integer on the stack (initially i) to base 4.
  2fmd  e#   Replace each base-4 digit d by d/2 and d%2.
  2/    e#   Split into the chunks [d/2 d%2].
  z     e#   Transpose. This collects all quotients in one array and all
        e#   residues in another one.
  2fb   e#   Convert each array from base 2 to integer.
  ~     e#   Dump both integers on the stack.
  p     e#   Print the topmost one.
}*      e#

L'idea di xnor dà anche 20 byte (o meno se si gioca a golf meglio di me): q~2bW%1$Te]/zWf%2fbp(ordine di input opposto)
Martin Ender

3

CJam, 18 byte

q~({)2bW%_1#p))b}*

Usa una formula più stupida.

Provalo qui .

Spiegazione

q~          e# Read input.
({          e# Repeat k-1 times:
    )       e# Increment the current integer (initially i), to make it positive.
    2b      e# Convert to binary.
    W%      e# Reverse the binary.
            e# The result can be any non-empty binary string without trailing 0s.
    _1#     e# Find the position of the first 1, or the number of initial 0s.
    p       e# Print.
    )       e# Extract the final bit, which is always 1.
            e# An array that can be any binary string is left in the stack.
    )       e# Increment the 1 to make it 2.
    b       e# Convert the binary string to a number using base 2.
            e# Only the number of initial 0s doesn't affect the result,
            e# which is exactly what is printed before.
}*          e# The final integer is printed automatically when the program ends.

In breve, associa un numero intero positivo a:

  1. Il numero di zeri finali.
  2. L'intero originale con zeri finali rimossi, invertiti e 1 finale (originariamente iniziale) rimosso.

3

Python 2, 62

lambda z,k:[int('0'+bin(z)[~i:1:-k][::-1],2)for i in range(k)]

Questo codice è brutto e giocabile, ma l'idea è molto semplice.

Comprimi kle espansioni binarie in una, leggendo ogni kcifra con offset diversi. Ad esempio, con k=3, l'input è 357mappato a (3,0,7):

101100101 <- 357
  1  0  1 -> 5
 0  0  0  -> 0
1  1  1   -> 7

Riunire i numeri insieme li inverte, quindi è una biiezione. Nel fare ciò, pensa alle espansioni binarie come ad avere un numero infinito di zeri iniziali.


3

J, 38 28 27 byte

(({.,g^:_1@}.)g=:_ q:>:)~<:

Questo è un verbo diadico tacito che prende i e k come argomenti sinistro e destro. Provalo in rete con J.js .

Idea

Definiamo una mappa f: N → N k per f (i): = (α 1 ,… α k-1 , p 1 α k … p 2 α k + 1 ... - 1) , dove ⟨p n è il sequenza di numeri primi e i + 1 = p 1 α 1 p 2 α 2 .

Secondo il Teorema aritmetico fondamentale, la mappa g: N → N ω definita da g (i): = (α 1 , α 2 , ...) (esponenti della scomposizione in fattori primi di i + 1 ) è biiettiva.

Poiché f (i) = (g 1 (i),… g k-1 (i), g -1 (g k (i), g k + 1 (i),…)) , la mappa f è biiettiva come bene.

Codice

                            Left argument: i -- Right argument: k
                         <: Decerement k.
(                      )~   Reverse the order of the arguments and apply the
                            dyadic verb inside the parentheses to k-1 and i.
              g=:            Define a monadic helper verb g:
                     >:       Increment its right argument.
                 _ q:         Calculate the exponents of the prime factorization.
                             (implicit) Apply g to i.
(            )               Apply the dyadic verb inside the parentheses to k-1
                             and (g i).
           }.                 Drop the first k-1 elements of (g i)...
          @                   and...
     g^:_1                    apply the inverse of g to the result.
  {.                          Take the first k-1 elements of (g i).
    ,                         Append the rightmost result to the leftmost one.

Perché la tua funzione è biiettiva?
xnor

@xnor Almeno quello della mia spiegazione non lo era, dal momento che avevo scambiato un paio di indici per errore. Ho aggiunto uno schizzo di prova.
Dennis,

1

Python 2, 72

q=lambda z:z and z%2+2*q(z/4)
g=lambda z,k:1/k*[z]or[q(z)]+g(q(z/2),k-1)

La funzione q agisce su numeri binari prendendo ogni secondo bit a partire dalla fine. Di conseguenza q(z), q(z>>1)fornisce due numeri le cui cifre binarie si intersecano per dare z. Ad esempio, 594 si divide in 12 e 17.

1001010010   <- 594
 0 1 1 0 0   ->  12
1 0 0 0 1    ->  17

Questa è una biiezione perché possiamo comprimere nuovamente i numeri per recuperare il numero originale.

La funzione gapplica questi k-1tempi di biiezione , espandendosi da un singolo elemento a una coppia a una tripla ... a una kcoppia. Ogni volta, l'ultimo elemento viene espanso in due elementi. Questo viene fatto in modo ricorsivo mappando l'ingresso su una coppia tramite la biiezione, prendendo il primo elemento della coppia per la prima voce dell'uscita e applicando ricorsivamente la funzione con k-1il secondo elemento per produrre le voci rimanenti.


Mi sono reso conto che sto rendendo questa cosa troppo complicata ...
xnor
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.