Feliz dia Pi todos! Por nenhuma razão, estou tentando construir um estimador de Pi de Monte Carlo o mais curto possível. Podemos construir um que possa caber em um tweet?
Para esclarecer, o que tenho em mente é a abordagem típica de desenhar pontos aleatórios a partir do quadrado unitário e calcular a proporção que se enquadra no círculo unitário. O número de amostras pode ser codificado ou não. Se você codificá-los, use pelo menos 1000 amostras. O resultado pode ser retornado ou impresso como um ponto flutuante, ponto fixo ou número racional.
Nenhuma função trigonométrica ou constante Pi deve ser uma abordagem de Monte Carlo.
Isso é código de golfe, então a submissão mais curta (em bytes) vence.
code-golf
random
pi
approximation
keegan
fonte
fonte
((0..4e9).map{rand**2+rand**2<1}.to_s.sub(/./,"$1.")
map
lhe dá uma matriz detrue
efalse
?.filter{...}.size
deve funcionar, no entanto.Respostas:
Código da máquina 80386,
4038 bytesHexdump do código:
Como obter este código (da linguagem assembly):
Esta é uma função que usa a
fastcall
convenção de chamada da Microsoft (o número de iterações é passado no registroecx
). Retorna o resultado nost
registro.Coisas divertidas sobre este código:
rdrand
- apenas 3 bytes para gerar um número aleatório!D
) com o raio ao quadrado (2^32
) é realizada automaticamente - a bandeira de transporte contém o resultado.fonte
eax
; omul
comando multiplica por si mesmo e coloca a parte altaedx
; a parte baixaeax
é descartada.Matlab / Octave, 27 bytes
Eu sei que já existe uma resposta do Matlab / Octave, mas tentei minha própria abordagem. Eu usei o fato de que a integral
4/(1+x^2)
entre 0 e 1 é pi.fonte
R, 40 (ou 28 ou 24 usando outros métodos)
Python 2, 56
Outro Python, se numpy for permitido, mas bem parecido com o Matlab / Octave:
fonte
Mathematica,
424039 bytes (ou 31/29?)Eu tenho três soluções, todas em 42 bytes:
Todas são funções sem nome que recebem o número de amostras e
n
retornam uma aproximação racional π. Primeiro, todos eles geramn
pontos no quadrado da unidade no quadrante positivo. Em seguida, eles determinam o número daquelas amostras que estão dentro do círculo unitário e depois dividem pelo número de amostras e multiplicam por4
. A única diferença está em como eles determinam o número de lamelas dentro do círculo unitário:Count
com a condição de queNorm[p] < 1
.1
e depois arredonda para cima. Isso transforma os números dentro do círculo da unidade1
e os de fora para0
. Depois, apenas resumo todos elesTr
.1.5
, para que eu possa usar emRound
vez deCeiling
.Aaaaaand, enquanto escrevia isso, ocorreu-me que há realmente uma solução mais curta, se eu apenas subtrair
2
e depois usarFloor
:ou salvar outro byte usando os operadores de piso ou teto Unicode:
Observe que as três soluções baseadas em arredondamento também podem ser escritas com, em
Mean
vez deTr
e sem o/#
, novamente para os mesmos bytes.Se outras abordagens baseadas em Monte Carlo forem boas (especificamente a escolhida por Peter), eu posso fazer 31 bytes estimando a integral de ou 29 usando a integral de , desta vez dado como um número de ponto flutuante:
√(1-x2)
1/(1+x2)
fonte
CJam,
27 2322 ou 20 bytes2 bytes economizados graças ao Runner112, 1 byte economizado graças ao Sp3000
Leva a contagem de iterações de STDIN como uma entrada.
Isso é o mais direto possível. Estes são os principais passos envolvidos:
Expansão do código :
Experimente online aqui
Se o valor médio de
1/(1+x^2)
também for considerado como Monte Carlo, isso poderá ser feito em 20 bytes:Experimente aqui
fonte
1dmr
vez deKmrK/
e verificar se a soma dos quadrados é maior que 1 com emi
vez de1>
(eu pensei que este era particularmente inteligente) .i
truque é realmente legal! E maldita falta de documentação para1dmr
Python 2,
7775 bytesUsa 4000 amostras para salvar bytes
1e3
.fonte
...*8000;print a/2e3
.Commodore 64 Básico, 45 bytes
Substituições PETSCII:
─
=SHIFT+E
,/
=SHIFT+N
,┌
=SHIFT+O
Gera 1000 pontos no primeiro quadrante; para cada um, adiciona a veracidade de "x ^ 2 + y ^ 2 <1" a uma contagem contínua e depois divide a contagem por 250 para obter
pi
. (A presença de um sinal de menos é porque no C64, "true" = -1.)fonte
(1)
faz?/
não é o símbolo de divisão, é o personagem produzido digitandoSHIFT+N
em um teclado Commodore 64.R/(1)
é o formulário de atalho paraRND(1)
, ie. "produz um número aleatório entre 0 e 1 usando a semente RNG atual".J, 17 bytes
Calcula o valor médio dos
40000
valores de amostra da função4*sqrt(1-sqr(x))
no intervalo[0,1]
.Com folga
0 o.x
retornossqrt(1-sqr(x))
.fonte
> <> (Peixe) , 114 bytes
Agora,> <> não possui um gerador de números aleatórios embutido. No entanto, possui uma função que envia o ponteiro em uma direção aleatória. O gerador de números aleatórios no meu código:
Basicamente, gera bits aleatórios que compõem um número binário e, em seguida, converte esse número binário aleatório em decimal.
O resto são apenas os pontos regulares na abordagem quadrada.
Uso: ao executar o código, você deve preencher previamente a pilha (-v no interpretador python) com o número de amostras, por exemplo
retorna
fonte
Matlab ou Octave 29 bytes (graças a flawr!)
(Não tenho certeza se <1 está OK. Li que deveria ser <= 1. Mas qual é a probabilidade de desenhar exatamente 1 ...)
Matlab ou Octave 31 bytes
fonte
mean(sum(rand(2,4e6).^2)<1)*4
.Java, 108 bytes
Quatro mil iterações, adicionando 0,001 cada vez que o ponto está dentro do círculo unitário. Coisas bem básicas.
Nota: Sim, sei que posso eliminar quatro bytes mudando
π
para um caractere de byte único. Eu gosto assim.fonte
Javascript: 62 bytes
Usei a resposta javascript anterior (agora excluída) e depilei 5 bytes.
fonte
GolfScript (34 caracteres)
Demonstração online
Isso usa ponto fixo porque o GS realmente não tem ponto flutuante. Abusa levemente o uso do ponto fixo; portanto, se você quiser alterar a contagem de iterações, verifique se é duas vezes a potência de dez.
Crédito para xnor pelo método particular de Monte Carlo empregado.
fonte
Python 2,
908581 bytesretorna
3.14120037157
por exemplo. A contagem da amostra é 4782969 (9 ^ 7). Você pode obter um pi melhor com 9 ^ 9, mas terá que ser paciente.fonte
range(9**7)
por[0]*9**7
ou algo assim, já que não o usai
. E a lista não é muito longa para encontrar problemas de memória.range()
mas havia esquecido completamente esse truque.[0]9**7
sintaxe não é válida.Ruby, 39 bytes
Um dos destaques é que este é capaz de usar
8e5
notação, o que torna extensível até ~ 8e9 amostras na mesma contagem de bytes de programa.fonte
Perl 6 , 33 bytes
Experimente online!
Essa é uma função que recebe o número de amostras como argumento.
fonte
Scala,
877766 bytesfonte
1000
com8000
e250d
com2e4
ambos salvar um byte e aumentar o número de amostras por um fator de 8.Pure Bash, 65 bytes
Toma um único parâmetro de linha de comando multiplicado por 4 para fornecer o número de amostras. A aritmética do Bash é apenas um número inteiro; portanto, é racional um resultado. Isso pode ser canalizado
bc -l
para a divisão final:fonte
Joe ,
2019 bytesNota: esta resposta não é competitiva, porque a versão 0.1.2, que adicionou aleatoriedade, foi lançada após esse desafio.
Função nomeada F:
Função sem nome:
Ambos pegam a contagem da amostra como argumento e retornam o resultado. Como eles funcionam?
Exemplo é executado:
fonte
dc, 59 caracteres (o espaço em branco é ignorado)
Eu testei isso no Plan 9 e no OpenBSD, então imagino que funcione no Linux (GNU?)
dc
.Explicação por linha:
i
se 1 for maior que a soma dos quadrados] no registrou
.x
em 1] no registroi
.u
, incrementar o registrom
e depois executar o registroz
se o registrom
for maior que o registron
] no registroz
.Defina a escala para 5 pontos decimais.
z
.x
(o número de ocorrências) pelo registron
(o número de pontos), multiplique o resultado por 4 e imprima.No entanto, eu trapacei:
O programa precisa de um fornecimento de carros alegóricos aleatórios entre 0 e 1.
Uso:
Execução de teste:
Agora com menos trapaça (100 bytes)
Alguém apontou que eu poderia incluir uma simples impressão.
http://en.wikipedia.org/wiki/RANDU
Ungolfed
Execução de teste:
fonte
Pyth, 19
Forneça o número desejado de iterações como entrada.
Demonstração
Como Pyth não tem uma função "Número flutuante aleatório", tive que improvisar. O programa escolhe dois números inteiros positivos aleatórios menores que a entrada, quadrados, somas e comparados com a entrada ao quadrado. Isso executou um número de vezes igual à entrada e, em seguida, o resultado é multiplicado por 4 e dividido pela entrada.
Em notícias relacionadas, estarei adicionando uma operação aleatória de número de ponto flutuante ao Pyth em breve. Este programa não usa esse recurso, no entanto.
Se interpretarmos "O resultado pode ser retornado ou impresso como um ponto flutuante, ponto fixo ou número racional". liberalmente, a impressão do numerador e denominador da fração resultante deve ser suficiente. Nesse caso:
Pyth, 18
Este é um programa idêntico, com a operação de divisão de ponto flutuante (
c
) removida.fonte
Julia, 37 bytes
O número de amostras é 65536 (= 4 ^ 8).
Uma variante ligeiramente mais longa: uma função com o número de amostras
s
como o único argumento:fonte
C, 130 bytes
Ungolfed:
fonte
f()
. Qual compilador você usou? Veja tio.run/##Pc49C4JAHIDx3U9xGMG9ZdYgwWkgtNbQ1BZ6L/UHO8M07hA/…Na verdade , 14 bytes (não concorrentes)
Experimente online!
Esta solução não é competitiva porque o idioma pós-desafio. O número de amostras é dado como entrada (em vez de codificado).
Explicação:
fonte
Raquete 63 bytes
Usando o método da linguagem R, responda por @Matt:
Ungolfed:
Teste:
Saída (fração):
Como decimal:
fonte
Fortran (GFortran) ,
8483 bytesExperimente online!
Este código é muito ruim escreveu. Ele falhará se o gfortran decidir inicializar a variável
A
com outro valor, então 0 (que ocorre aproximadamente 50% das compilações) e, seA
for inicializado como 0, sempre gerará a mesma sequência aleatória para a semente especificada. Em seguida, o mesmo valor para Pi é impresso sempre.Este é um programa muito melhor:
Fortran (GFortran) ,
10099 bytesExperimente online!
(Um byte salvo em cada versão; obrigado Penguino).
fonte
Japt , 26 ou 18 bytes
Experimente online!
Análogo à resposta do Optimizer , principalmente apenas tentando aprender japonês.
Leva o número de iterações a serem executadas como entrada implícita
U
.Se
1/(1+x^2)
for permitido (em vez de dois randoms separados), podemos obter 18 bytes com a mesma lógica.fonte
Mh
calcular a hipotenusa em vez de fazer você mesmo ;-) Além disso, você pode usarx
a soma de uma matriz, em vez de reduzir por adição:o x@MhMr Mr)<1Ã*4/U
Mh
assim, obrigado! Sua resposta aleatória é quase tão curta quanto a minha resposta com apenas uma aleatória, isso é bem legal. Eu mantereix
em mente que costumo usar muito a redução ao tentar jogar coisas de golfe, então isso será muito útil.F #, 149 bytes
Experimente online!
Tanto quanto eu posso entender, para fazer esse tipo de execução total em F #, é mais curto criar uma matriz de números e usar o método
Seq.sumBy
método do que usar umfor..to..do
bloco.O que esse código faz é que ele cria uma coleção de números de ponto flutuante de 1 a
s
, executa a funçãofun x->...
para o número de elementos na coleção e soma o resultado. tems
elementos na coleção, portanto o teste aleatório é realizado váriass
vezes. Os números reais na coleção são ignorados (fun x->
, masx
não são usados).Isso também significa que o aplicativo deve primeiro criar e preencher a matriz e, em seguida, iterar sobre ela. Portanto, é provavelmente duas vezes mais lento que um
for..to..do
loop. E com a criação da matriz, o uso da memória fica na região de O (f ** k)!Para o teste em si, em vez de usar uma
if then else
instrução, ele calcula a distância (q()+q()|>Math.Sqrt
) e arredondá-la para baixoMath.Floor
. Se a distância estiver dentro do círculo, será arredondado para 0. Se a distância estiver fora do círculo, será arredondado para 1. OSeq.sumBy
método totalizará esses resultados.Note então que
Seq.sumBy
totalizou não são os pontos dentro do círculo, mas os pontos fora dele. Portanto, para o resultado obtidos
(nosso tamanho de amostra) e subtrai o total dele.Parece também que tomar um tamanho de amostra como parâmetro é mais curto do que codificar o valor. Então, eu estou trapaceando um pouco ...
fonte
Haskell,
11611411096 bytesComo lidar com isso
import System.Random; r=randoms(mkStdGen 2)
exigiria muitos bytes preciosos, eu gero uma lista infinita de números aleatórios com o gerador congruencial linear que alguns dizem ser quase criptograficamente forte:x↦x*9+1 mod 8^9
qual, pelo Teorema de Hull-Dobell, tem o período completo8^9
.g
rendimentos4
se o ponto do número aleatório estiver dentro do círculo para pares de números aleatórios[0..8^9-1]
porque isso elimina uma multiplicação na fórmula usada.Uso:
Experimente online!
fonte
Perl 5, 34 bytes
O número de amostras é retirado do stdin. Requer
-p
.Funciona porque:
Experimente online!
fonte