Enumerando vetores tridimensionais

17

Dado um número inteiro positivo k > 1e um número inteiro não negativo i, gere um número k-tuplo (ou kvetor dimensional) de números inteiros não negativos. Para cada k, o mapa de ℕ para ℕ k , deve ser bijective . Ou seja, toda entrada ideve produzir uma tupla diferente, e toda tupla possível deve ser produzida por alguma entrada i.

Você pode escrever um programa ou função, recebendo entrada via STDIN (ou alternativa mais próxima), argumento da linha de comando ou argumento da função e emitindo o resultado via STDOUT (ou alternativa mais próxima), valor de retorno da função ou parâmetro da função (saída).

Você pode usar qualquer formato de lista simples, conveniente e inequívoco para a saída.

Sua solução não deve impor limites artificiais ke, imas você pode assumir que eles se encaixam no tamanho inteiro nativo do seu idioma. No mínimo, você deve suportar valores de até 255, mesmo que o tamanho inteiro nativo seja menor que isso.

De qualquer forma 1 < k < 32, seu código deve produzir um resultado em questão de segundos (é claro, se sua resposta não suportar esse tamanho devido à regra anterior, o limite será ajustado de acordo). Este deve ser nenhum problema: é possível resolver este desafio de tal forma que ele funciona até 2 128 em poucos segundos, mas o limite é de lá para respostas a evitar que, na verdade, iterate a partir de para encontrar o resultado.i < 231i0i

Inclua na sua resposta uma descrição do mapeamento escolhido e uma justificativa para o motivo de ele ser bijetivo (isso não precisa ser uma prova formal).

Este é o código golf, a resposta mais curta (em bytes) vence.

Desafios relacionados

Martin Ender
fonte

Respostas:

5

Pitão, 15 12 bytes

ms+0_%Q>_zdQ

Suíte de teste

Minha transformação é semelhante a uma das xnor, mas na base 10. Ela funciona descompactando a entrada em k números separados:

n = 21003034
k = 3

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

Os números são ordenados na posição decrescente do dígito mais à direita, para que todos os pedidos de qualquer grupo de números sejam possíveis.

A maneira como o código funciona é que invertemos a entrada, depois cortamos os últimos 0, 1, ... k-1dígitos, pegamos cada kdígito, invertemos novamente, colamos um 0no início e convertemos para int.

isaacg
fonte
4

CJam, 20 bytes

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

O mapeamento é bijetivo, pois aplica o mapeamento desta resposta k - 1 vezes.

O programa lê a entrada como i k. Experimente online no intérprete CJam .

Idéia

Podemos construir um mapeamento bijetivo f: N → N 2 definindo f (i) da seguinte maneira:

  • Converta i na matriz de seus dígitos binários.

  • Anexe um 0 a esta matriz se houver um número ímpar de dígitos.

  • Desintercalar a matriz resultante, formando novas no processo.

  • Converta essas matrizes da base 2 para inteiro. Definir f um (i) e f 2 (i) como os resultados.

Para obter um mapeamento bijetivo g: N → N 3 , podemos definir g (n): = (f 1 (i), f 1 (f 2 (i)), f 2 (f 2 (i))) .

Para obter um mapeamento bijetivo h: N → N 4 , podemos definir h (i): = (g 1 (i), g 2 (i), f 1 (g 3 (i)), f 2 (g 3 ( i))) .

Continuando o processo acima, finalmente chegamos a um mapa bijetivo N → N k .

Código

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#
Dennis
fonte
A ideia de xnor também dá 20 bytes (ou menos se você golf-lo melhor do que eu fiz): q~2bW%1$Te]/zWf%2fbp(ordem inversa de entrada)
Martin Ender
3

CJam, 18 bytes

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

Ele usa uma fórmula mais estúpida.

Experimente aqui .

Explicação

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.

Em resumo, ele mapeia um número inteiro positivo para:

  1. O número de zeros à direita.
  2. O número inteiro original com zeros à direita removidos, revertidos e o à direita (originalmente inicial) 1 removido.
jimmy23013
fonte
3

Python 2, 62

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

Esse código é feio e jogável, mas a idéia é muito simples.

Embalar kexpansões binárias em um por ler todos os kdígitos th com diferentes deslocamentos. Por exemplo, com k=3, a entrada é 357mapeada para (3,0,7):

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

Fechar os números novamente reverte-o, então é uma bijeção. Ao fazer isso, pense nas expansões binárias como tendo um número infinito de zeros à esquerda.

xnor
fonte
3

J, 38 28 27 bytes

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

Este é um verbo tácito, dyadic que leva i e k como argumentos esquerda e direita. Experimente online com J.js .

Idéia

Nós definimos um mapa f: N → N k por f (i): = (α 1 , ... α k-1 , p 1 α k ... p 2 α k + 1 ... - 1) , onde ⟨p n é a sequência de números primos e i + 1 = p 1 α 1 p 2 α 2 .

Pelo teorema aritmético fundamental, o mapa g: N → N ω definido por g (i): = (α 1 , α 2 ,…) (expoentes da fatoração primária de i + 1 ) é bijetivo.

Como f (i) = (g 1 (i),… g k-1 (i), g -1 (g k (i), g k + 1 (i),…)) , o mapa f é bijetivo como bem.

Código

                            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.
Dennis
fonte
Por que sua função é bijetiva?
Xnor
@xnor Pelo menos o da minha explicação não foi, desde que eu troquei alguns índices por engano. Eu adicionei um esboço de 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)

A função qatua em números binários, pegando cada segundo bit a partir do final. Como resultado, q(z), q(z>>1)fornece dois números cujos dígitos binários se intercalam para fornecer z. Por exemplo, 594 se divide em 12 e 17.

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

Esta é uma bijeção porque podemos compactar os números novamente para recuperar o número original.

A função gaplica esses k-1tempos de bijeção , expandindo de um único elemento para um par para um triplo ... para um ktriplo. Cada vez, o último elemento é expandido para dois elementos. Isso é feito recursivamente, mapeando a entrada para um par via bijeção, pegando o primeiro elemento do par para a primeira entrada da saída e aplicando a função recursivamente k-1ao segundo elemento para produzir as entradas restantes.

xnor
fonte
Percebi que estou tornando este caminho muito complicado ... #
214