O desafio
Escreva um programa ou função que não aceite nenhuma entrada e produza um vetor de comprimento em uma direção aleatória teoricamente uniforme .
Isso é equivalente a um ponto aleatório na esfera descrito por
resultando em uma distribuição como essa
Saída
Três flutuadores de uma distribuição aleatória teoricamente uniforme para a qual a equação é verdadeira para os limites de precisão.
Comentários do desafio
- A distribuição aleatória precisa ser teoricamente uniforme . Ou seja, se o gerador de números pseudo-aleatórios fosse substituído por um RNG verdadeiro a partir dos números reais , isso resultaria em uma distribuição aleatória uniforme de pontos na esfera.
- Gerar três números aleatórios a partir de uma distribuição uniforme e normalizá-los é inválido: haverá um viés nos cantos do espaço tridimensional.
- Da mesma forma, gerar dois números aleatórios a partir de uma distribuição uniforme e usá-los como coordenadas esféricas é inválido: haverá um viés em direção aos pólos da esfera.
- A uniformidade adequada pode ser alcançada por algoritmos, incluindo, entre outros:
- Gerar três números aleatórios de , e de um normal de distribuição (Gaussiana) em torno de e normalizar-los.
- Gerar três números aleatórios de , e a partir de uma uniforme distribuição na gama de . Calcule o comprimento do vetor por . Então, se, rejeite o vetor e gere um novo conjunto de números. Caso contrário, se, normalize o vetor e retorne o resultado.
- Gerar dois números aleatórios e de uma uniforme distribuição na gama e convertê-los em coordenadas esféricas assim: para que,epossam ser calculados por
- Forneça na sua resposta uma breve descrição do algoritmo que você está usando.
- Leia mais sobre a escolha de pontos de esfera no MathWorld .
Exemplos de saída
[ 0.72422852 -0.58643067 0.36275628]
[-0.79158628 -0.17595886 0.58517488]
[-0.16428481 -0.90804027 0.38532243]
[ 0.61238768 0.75123833 -0.24621596]
[-0.81111161 -0.46269121 0.35779156]
Observações gerais
- Isso é código-golfe , então a resposta usando o menor número de bytes em cada idioma vence.
- Regras padrão , regras de E / S e regras de brecha são aplicadas.
- Inclua um link Experimente online ou equivalente para demonstrar o funcionamento do seu código.
- Motive sua resposta com uma explicação do seu código.
pi/6 ≈ 0.5236
de produzir uma saída. Essa é a área da esfera inscrita no cubo de área unitáriaRespostas:
Wolfram Language (Mathematica) , 20 bytes
Experimente online!
Faz exatamente o que diz na lata.
fonte
R , 23 bytes
Experimente online!
Gera 3 realizações da distribuiçãoN(0,1) e normaliza o vetor resultante.
Gráfico de 1000 realizações:
fonte
x86-64 Código da máquina -
63 62 5549 bytesUsa o segundo algoritmo, modificado. Retorna o vetor de
[x, y, z, 0]
em xmm0.Explicação:
Empurra o valor para 1 e 2 ^ 31 como um float para a pilha. Os dados se sobrepõem devido à extensão do sinal, economizando alguns bytes.
vbroadcastss xmm1,dword ptr [rsp+5]
Carrega o valor de 2 ^ 31 em 4 posições de xmm1.Gera um número inteiro aleatório de 32 bits e o carrega na parte inferior de xmm0.
Gera um número inteiro aleatório de 32 bits, converte-o em float (assinado) e divida por 2 ^ 31 para obter números entre -1 e 1.
vdpps xmm2,xmm0,xmm0,7Fh
adiciona os quadrados dos 3 carros alegóricos inferiores usando um produto pontilhado, mascarando o carro alegórico superior. Isso dá o comprimentoCompara o comprimento ao quadrado com 1 e rejeita os valores se não for igual a 1. Se o comprimento ao quadrado for um, o comprimento também será um. Isso significa que o vetor já está normalizado e salva uma raiz quadrada e divide.
Restaure a pilha.
ret
retorna valor em xmm0Experimente online .
fonte
aesenc
para produzir 128 bits "aleatórios" é simplesmente bonito.Python 2 , 86 bytes
Experimente online!
Gera a coordenada z uniformemente de -1 a 1. Em seguida, as coordenadas x e y são amostradas uniformemente em um círculo de raio
(1-z*z)**.5
.Pode não ser óbvio que a distribuição esférica seja fator uniforme sobre a coordenada z (e também sobre todas as coordenadas). Isso é algo especial para a dimensão 3. Veja esta prova de que a área de superfície de uma fatia horizontal de uma esfera é proporcional à sua altura. Embora as fatias próximas ao equador tenham um raio maior, as fatias próximas ao polo têm mais um título para dentro, e esses dois efeitos são exatamente cancelados.
Para gerar um ângulo aleatório nesse círculo, elevamos a unidade imaginária
1j
a uma potência aleatória uniforme entre 0 e 4, o que nos impede de precisar de funções trigonométricas, pi ou e, qualquer uma das quais precisaria de uma importação. Extraímos então a parte imaginária real. Se pudermos gerar um número complexo para duas das coordenadas, a última linha pode ser apenasprint a,z
.86 bytes
Experimente online!
Gera três normais e dimensiona o resultado.
Python 2 com numpy, 57 bytes
Experimente online!
sum(a*a)**.5
é mais curto quelinalg.norm(a)
. Também poderíamos fazerdot(a,a)
o mesmo tamanho quesum(a*a)
. No Python 3, isso pode ser reduzido para oa@a
uso do novo operador@
.fonte
z
, a partir de uma distribuição uniforme, não for modificado.z
e o consertei por alguns bytes.Oitava ,
40 3322 bytesAmostramos de uma distribuição normal padrão 3d e normalizamos o vetor:
Experimente online!
fonte
disp
:)Unidade C # , 34 bytes
O Unity tem um builtin para valores aleatórios da esfera unitária, então pensei em publicá-lo.
fonte
f=>Random.onUnitSphere
f
o Tipo; usandovar
apenas funciona dentro de um método eSystem.Func<Vector3>
era mais longo.f=>Random.onUnitSphere
é uma submissão perfeitamente válidaf=>UnityEngine.Random.onUnitSphere
você economiza ousing
MATL , 10 bytes
Experimente online!
Explicação
Isso usa a primeira abordagem descrita no desafio.
fonte
Ruby ,
34 5049 bytesExperimente online!
Retorna uma matriz de 3 números
[z,y,x]
.x
ey
são gerados pelo aumentoi
(raiz quadrada de -1) de uma potência aleatória entre 0 e 4. Esse número complexo precisa ser dimensionado adequadamente de acordo com oz
valor de acordo com o teorema de Pitágoras:(x**2 + y**2) + z**2 = 1.
A
z
coordenada (que é gerada primeiro) é simplesmente um número uniformemente distribuído entre -1 e 1. Embora não seja imediatamente óbvio, dA / dz para uma fatia na esfera é constante (e igual ao perímetro de um círculo com o mesmo raio que toda a esfera).Aparentemente, isso foi descoberto por Arquimedes, que o descreveu de uma maneira muito não-calculista, e é conhecido como teorema de Archimedes Hat-Box. Veja https://brilliant.org/wiki/surface-area-sphere/
Outra referência dos comentários sobre a resposta do xnor. Um URL surpreendentemente curto, descrevendo uma fórmula surpreendentemente simples: http://mathworld.wolfram.com/Zone.html
fonte
[z, x+yi]
deixarei como está, a menos que você diga que está tudo bem.z*z
vez dez**2
?z*z
. Eu editei agora. A outra coisa que eu poderia fazer é substituirrand*4
por algo comoz*99
oux*9E9
(efetivamente limitando os valores possíveis a uma espiral muito fina na esfera), mas acho que isso reduz a qualidade do acaso.05AB1E ,
2322 bytesImplementa o segundo algoritmo.
Experimente online ou obtenha mais algumas saídas aleatórias .
Explicação:
5
para9
no código (embora se torne bastante lento ..).fonte
TI-BASIC, 15 bytes *
Usando o algoritmo "gere 3 valores normalmente distribuídos e normalize esse vetor".
O encerramento de um programa com uma expressão imprime automaticamente o resultado na Tela inicial após o término do programa, para que o resultado seja realmente mostrado, não apenas gerado e perfurado.
*:
randNorm(
é um token de dois bytes , o restante são tokens de um byte . Eu contei o inicial (inevitável):
, sem isso, seriam 14 bytes. Salvo como um programa com um nome de uma letra, são necessários 24 bytes de memória, que incluem os 9 bytes de sobrecarga do sistema de arquivos.fonte
JavaScript (ES7),
77 7675 bytesExperimente online!
Comentado
JavaScript (ES6), 79 bytes
Implementa o 2º algoritmo.
Experimente online!
Comentado
fonte
Processando 26 bytes
Programa completo
Esta é a implementação https://github.com/processing/processing/blob/master/core/src/processing/core/PVector.java
fonte
Python 2 , 86 bytes
Experimente online!
Implementa o primeiro algoritmo.
Python 2 ,
107103 bytesExperimente online!
Implementa o segundo algoritmo.
fonte
Haskell ,
125123119118 bytesExperimente online!
Faz três randoms uniformes e amostragem de rejeição.
fonte
JavaScript, 95 bytes
Você
nãoprecisa não inserira
.fonte
Julia 1.0 , 24 bytes
Experimente online!
Desenha um vetor de 3 valores, desenhado a partir de uma distribuição normal em torno de 0 com desvio padrão 1. Em seguida, apenas os normaliza.
fonte
randn()
, em alguns testes rápidos, não parece estar vinculado ao intervalo necessário. Além disso, isso não inclui uma verificação parahypot()
retornar um valor>1
, que deve ser rejeitado.randn
simular a partir de uma distribuição normal padrão, em vez de uma distribuição uniforme (0,1), portanto essa abordagem é idêntica à R.[-1,1)
divisão por eles pelo hipotenusa, qual será>1
, compensa isso? Isso me leva a pensar se o ternário da minha solução é necessário ...MathGolf ,
211918 bytesImplementação do 2º algoritmo.
Experimente online ou veja mais algumas saídas ao mesmo tempo .
Explicação:
fonte
Java 8 ( terceiro algoritmo modificado por @Arnauld ),
131126119111109 bytesPorta da resposta JavaScript de @Arnauld , certifique-se de vomitá-lo!
-2 bytes graças a @ OlivierGrégoire .
Isso é implementado como:
Experimente online.
Implementação anterior do terceiro algoritmo (
131126119 bytes):Implementado como:
Experimente online.
Explicação:
Java 8 (segundo algoritmo),
153143 bytesExperimente online.
2º algoritmo:
fonte
sqrt(1-k*k)
realmente salva mais bytes em Java do que em JS. :)M.sin
, 1xM.cos
e 1xM.acos
, sua abordagem usa 2xM.sin
e 1xM.sqrt
, que é a origem dos bytes salvos adicionais. :)double[]
não alterar a contagem de bytes).Japonês , 20 bytes
Implementação do 2º algoritmo de Port of Arnauld .
Teste-o
fonte
Pitão , 24 bytes
Experimente online!
Usa o algoritmo nº 2
fonte
OCaml ,
1109995 bytesEDIT: Raspado alguns bytes, inliningEu e j , substituindo o primeiro
let ... in
por afun
e aproveitando a associatividade do operador para evitar alguns parênteses()
.Experimente online
Solução original:
Primeiro eu defino:
A
Random.float
função do OCaml inclui os limites. Então,Isso é muito semelhante ao terceiro exemplo de implementação (comϕ = p e θ = t ) - exceto que eu escolho Eu e j em intervalos maiores para evitar a multiplicação (com 2) posteriormente.
fonte
0
e1
diretamente como coordenadas esféricas. Isso está incorreto, como mostrado nas observações 3 e 4 do desafio, uma vez que você acaba com um viés em direção aos pólos da esfera. Você pode corrigir isso aplicando o método mostrado na observação 4.