Pi Alami 0 - Rock


39

Tujuan

Buat program / fungsi yang mengambil input N, periksa apakah Npasangan acak bilangan bulat relatif prima, dan kembali sqrt(6 * N / #coprime).

TL; DR

Tantangan-tantangan ini adalah simulasi algoritma yang hanya membutuhkan alam dan otak Anda (dan mungkin beberapa sumber daya yang dapat digunakan kembali) untuk memperkirakan Pi. Jika Anda benar-benar membutuhkan Pi selama kiamat zombie, metode ini tidak membuang - buang amunisi ! Ada delapan tantangan lagi yang akan datang. Periksa pos kotak pasir untuk membuat rekomendasi.

Simulasi

Apa yang kita simulasikan? Nah, probabilitas bahwa dua bilangan bulat acak relatif prima (yaitu coprime atau gcd == 1) adalah 6/Pi/Pi, jadi cara alami untuk menghitung Pi adalah dengan meraup dua ember (atau beberapa genggam) batu; hitung mereka; lihat apakah gcd mereka adalah 1; ulangi. Setelah melakukan ini beberapa kali, sqrt(6.0 * total / num_coprimes)akan cenderung ke arah Pi. Jika menghitung akar kuadrat dalam dunia pasca-apokaliptik membuat Anda gugup, jangan khawatir! Ada Metode Newton untuk itu.

Bagaimana kita mensimulasikan ini?

  • Ambil input N
  • Lakukan waktu berikut N:
    • Secara seragam menghasilkan bilangan bulat positif acak, idanj
    • Dengan 1 <= i , j <= 10^6
    • Jika gcd(i , j) == 1:result = 1
    • Lain: result = 0
  • Ambil jumlah Nhasil,S
  • Kembali sqrt(6 * N / S)

masukkan deskripsi gambar di sini

Spesifikasi

  • Memasukkan
    • Fleksibel, mengambil input dengan cara standar apa pun (mis. Parameter fungsi, STDIN) dan dalam format standar apa pun (mis. String, Binary)
  • Keluaran
    • Fleksibel, memberikan hasil dengan cara standar apa pun (mis. Mengembalikan, mencetak)
    • Ruang putih, trailing dan ruang putih utama dapat diterima
    • Akurasi, harap berikan setidaknya 4 tempat desimal akurasi (yaitu 3.1416)
  • Mencetak gol
    • Kode terpendek menang!

Uji Kasus

Output Anda mungkin tidak sejalan dengan ini, karena kebetulan acak. Tetapi rata-rata, Anda harus mendapatkan akurasi sebanyak ini untuk nilai yang diberikan N.

Input     ->  Output 
-----         ------
100       ->  3.????
10000     ->  3.1???
1000000   ->  3.14??
code-golf  math  random  pi  approximation  popularity-contest  code-golf  sequence  number-theory  binary  coding-theory  code-golf  math  3d  code-golf  code-golf  math  number  code-golf  kolmogorov-complexity  code-golf  ascii-art  graphical-output  binary-tree  code-golf  ascii-art  code-golf  ascii-art  kolmogorov-complexity  code-golf  array-manipulation  hexadecimal  code-golf  math  number  set-theory  code-golf  math  arithmetic  number-theory  integer  code-golf  string  kolmogorov-complexity  code-golf  math  sequence  arithmetic  decision-problem  code-golf  code-golf  ascii-art  code-golf  array-manipulation  parsing  code-golf  string  ascii-art  kolmogorov-complexity  code-challenge  code-golf  sequence  code-golf  number  array-manipulation  sorting  code-golf  string  function  code-golf  arithmetic  code-golf  math  sequence  number-theory  primes  restricted-source  javascript  code-challenge  polyglot  rosetta-stone  code-golf  code-golf  regular-expression  code-golf  math  code-golf  math  primes  code-golf  ascii-art  kolmogorov-complexity  binary  code-golf  math  sequence  code-golf  sequence  subsequence  code-golf  string  code-golf  parsing  music  code-golf  grid  game  path-finding  board-game  code-golf  string  binary  code-golf  array-manipulation  balanced-string  code-golf  code-golf  algorithm  code-golf  string  number  arithmetic  array-manipulation  code-golf  array-manipulation  binary-tree  tree-traversal  code-golf  code-golf  tips  code-golf  string  base-conversion  code-golf  tips  s.i.l.o.s  code-golf  string  ascii-art  code-golf  code-challenge  code-golf  game 

1
Apakah jawaban kita perlu bekerja N = 1000000atau apakah itu ok jika program kembali misalnya stack overflow jika Nterlalu besar?
Fatalkan

@Falisasi jika itu adalah batasan bahasa, tentu saja. Kalau tidak, Anda harus menanganinya N=10^6.
NonlinearFruit


2
Tujuannya menyesatkan, hanya menyatakan satu pasangan bilangan bulat diperiksa.
user253751

1
Apakah batas atas ke angka acak yang dihasilkan harus tepat 1000000? Apakah batas atas yang lebih besar dapat diterima?
Sok

Jawaban:


12

APL, 23 byte

{.5*⍨6×⍵÷1+.=∨/?⍵2⍴1e6}

Penjelasan:

  • ?⍵2⍴1e6: menghasilkan matriks 2-by-⍵ dari angka acak dalam rentang [1..10 6 ]
  • 1+.=∨/: dapatkan GCD dari setiap pasangan dan lihat berapa banyak yang sama dengan 1. Ini menghitung S.
  • .5*⍨6×⍵÷: (6 × ⍵ ÷ S) 0,5

11

Jelly , 20 18 16 byte

-2 bytes terima kasih kepada @ Pietu1998 (rantai & gunakan hitungan 1s, ċ1di tempat kurang dari dua dijumlahkan <2S)

-2 byte terima kasih kepada @Dennis (ulangi 1e6 beberapa kali sebelum pengambilan sampel untuk menghindari rantai)

Ḥȷ6xX€g2/ċ1÷³6÷½

(Sangat lambat karena fungsi acak)

Bagaimana?

Ḥȷ6xX€g2/ċ1÷³6÷½ - Main link: n
 ȷ6              - 1e6
   x             - repeat
Ḥ                -     double, 2n
    X€           - random integer in [1,1e6] for each
       2/        - pairwise reduce with
      g          -     gcd
         ċ1      - count 1s
           ÷     - divide
            ³    - first input, n
             6   - literal 6
              ÷  - divide
               ½ - square root

TryItOnline


ḤRµȷ6Xµ€g2/ċ1÷³6÷½menghemat 2 byte. ( ȷ6adalah 10 ^ 6 dalam satu nilad, ċ1termasuk yang)
PurkkaKoodari

Ah, saya tidak tahu bagaimana cara menjalinnya seperti itu (saya mencoba beberapa hal), dan lupa trik hitungan 1 - terima kasih (saya pikir ȷ²ini sedikit lebih cepat daripada ȷ6)
Jonathan Allan

Mungkin. Sekarang saya memikirkannya, ȷ²menjadi dua tautan tidak ada salahnya di sini, tetapi akan membutuhkan tautan tambahan atau ¤untuk beberapa kasus penggunaan
PurkkaKoodari

1
Ḥȷ6xX€harus bekerja untuk pengambilan sampel acak.
Dennis

9

Python 2, 143 140 132 124 122 124 122 byte

Sudah cukup lama sejak saya mencoba bermain golf, jadi saya mungkin melewatkan sesuatu di sini! Akan memperbarui saat saya mempersingkat ini.

import random as r,fractions as f
n,s=input(),0
k=lambda:r.randrange(1e6)+1
exec's+=f.gcd(k(),k())<2;'*n
print(6.*n/s)**.5

Uji saya di sini!

terima kasih kepada Jonathan Allan untuk save dua byte :)


Menurut OP 1 <= i , j <= 10^6,, jadi Anda perlu menggunakannya randrange(1,1e6+1).
mbomb007

1
Juga, benar-benar aneh memiliki tautan repl.it dalam nama bahasa. Tautan dalam nama lang harus ke beranda bahasa, jika ada. Letakkan tautan repl.it Anda sebagai tautan terpisah di bawah kode Anda.
mbomb007

@ mbomb007 Poin bagus, saya sudah memperbaikinya :) Sudah lama!
Kade

1
k=lambda:r.randrange(1e6)+1menghemat dua byte
Jonathan Allan

1
@ Jonathan Allan tangkapan bagus, terima kasih!
Kade

8

Mathematica, 49 48 51 byte

Menyimpan satu byte dan memperbaiki satu bug berkat @ LegionMammal978 .

(6#/Count[GCD@@{1,1*^6}~RandomInteger~{2,#},1])^.5&

1
Anda dapat menyimpan byte:(6#/Count[GCD@@1*^6~RandomInteger~{2,#},1])^.5&
LegionMammal978

1
Juga, 1*^6harus diganti dengan {1,1*^6}untuk memastikan bahwa saya , j ≠ 0.
LegionMammal978

8

R, 103 99 95 99 98 94 byte

Mungkin bisa bermain golf sedikit. Kurangi 4 byte karena @ antoine-sac, dan 4 byte lainnya dengan mendefinisikan alias untuk sample, menggunakan ^.5bukan sqrt, dan 1e6bukannya 10^6. Menambahkan 4 byte untuk memastikan bahwa pengambilan sampel idan jbenar-benar seragam. Dihapus satu byte setelah saya menyadari bahwa 6*N/sum(x)itu sama dengan 6/mean(x). Digunakan pryr::falih-alih function(x,y)menyimpan 4 byte.

N=scan()
s=sample
g=pryr::f(ifelse(o<-x%%y,g(y,o),y))
(6/mean(g(s(1e6,N,1),s(1e6,N,1))==1))^.5

Output sampel:

N=100     -> 3.333333
N=10000   -> 3.137794
N=1000000 -> 3.141709

1
Anda cukup menggunakan sample(10^6,N). Tidak hanya lebih pendek, tetapi juga jauh lebih efisien.
asac

Saya mungkin salah, tetapi tidak boleh sampel digunakan dengan ganti = T untuk bilangan bulat acak seragam yang benar. Misalnya sample(10,10)dijamin untuk mengembalikan semua angka dalam 1:10, sedangkan sample(10,10,T)akan menghasilkan pemilihan acak di mana angka dapat diulang.
MickyT

@MickyT Anda benar sekali, saya baru menyadarinya beberapa menit yang lalu. Saya tidak sepenuhnya yakin bagaimana ini dimainkan secara matematis dalam hal ini - sejauh yang saya tahu, kedua metode ini kira-kira sama-sama akurat. Saya akan mengedit posting saya untuk menambahkan informasi ini.
rturnbull

Kedua metode sama-sama akurat ketika N << 10 ^ 6. Untuk menangani N besar yang sewenang-wenang, Anda harus mengambil sampel dengan penggantian yang bagus.
asac

7

Sebenarnya, 19 byte

`6╤;Ju@Ju┤`nkΣß6*/√

Cobalah online!

Penjelasan:

`6╤;Ju@Ju┤`nkΣß6*/√
`6╤;Ju@Ju┤`n         do this N times:
 6╤;                   two copies of 10**6
    Ju                 random integer in [0, 10**6), increment
      @Ju              another random integer in [0, 10**6), increment
         ┤             1 if coprime else 0
            kΣ       sum the results
              ß      first input again
               6*    multiply by 6
                 /   divide by sum
                  √  square root

i, j tidak boleh 0
isaacg

1
@isaacg Mereka tidak. Jika Anda akan membaca penjelasannya, dikatakan bahwa nilai acak dipilih dari [0, 10 ** 6), lalu ditambahkan.
Mego

7

MATL , 22 byte

1e6Hi3$YrZ}Zd1=Ym6w/X^

Cobalah online!

1e6      % Push 1e6
H        % Push 2
i        % Push input, N
3$Yr     % 2×N matrix of uniformly random integer values between 1 and 1e6
Z}       % Split into its two rows. Gives two 1×N arrays
Zd       % GCD, element-wise. Gives a 1×N array
1=       % Compare each entry with 1. Sets 1 to 0, and other values to 0
Ym       % Mean of the array
6w/      % 6 divided by that
X^       % Square root. Implicitly display

6

Pyth, 21 byte

@*6cQ/iMcmhO^T6yQ2lN2

Cobalah online.

Penjelasan

                Q          input number
               y           twice that
         m                 map numbers 0 to n-1:
             T                 10
            ^ 6                to the 6th power
           O                   random number from 0 to n-1
          h                    add one
        c        2         split into pairs
      iM                   gcd of each pair
     /            lN       count ones
   cQ                      divide input number by the result
 *6                        multiply by 6
@                   2      square root

6

Scala, 149 126 byte

val& =BigInt
def f(n: Int)={math.sqrt(6f*n/Seq.fill(n){val i,j=(math.random*99999+1).toInt
if(&(i).gcd(&(j))>1)0 else 1}.sum)}

Penjelasan:

val& =BigInt                //define & as an alias to the object BigInt, because it has a gcd method
def f(n:Int)={              //define a method
  math.sqrt(                //take the sqrt of...
    6f * n /                //6 * n (6f is a floating-point literal to prevent integer division)
    Seq.fill(n){            //Build a sequence with n elements, where each element is..
      val i,j=(math.random*99999+1).toInt //take 2 random integers
      if(&(i).gcd(&(j))>1)0 else 1        //put 0 or 1 in the list by calling
                                          //the apply method of & to convert the numbers to
                                          //BigInt and calling its bcd method
    }.sum                   //calculate the sum
  )
}

Saya <3 Scala! Terutama, karena terkadang sangat membutuhkan penjelasan.
Roman Gräf

@ RomanGräf Sejujurnya, satu-satunya hal yang saya pikir mungkin tidak jelas adalah 6f, Seq.filldan math.random.
corvus_192

5

Racket 92 byte

(λ(N)(sqrt(/(* 6 N)(for/sum((c N))(if(= 1(gcd(random 1 1000000)(random 1 1000000)))1 0)))))

Tidak Disatukan:

(define f
  (λ (N)
    (sqrt(/ (* 6 N) 
            (for/sum ((c N))
              (if (= 1
                     (gcd (random 1 1000000)
                          (random 1 1000000)))
                  1 0)
              )))))

Pengujian:

(f 100)
(f 1000)
(f 100000)

Keluaran:

2.970442628930023
3.188964020716403
3.144483068444827

5

JavaScript (ES7), 107 95 94 byte

n=>(n*6/(r=_=>Math.random()*1e6+1|0,g=(a,b)=>b?g(b,a%b):a<2,q=n=>n&&g(r(),r())+q(n-1))(n))**.5

Versi ES6 tepat 99 byte, tetapi operator eksponensial ES7 **menghemat lebih dari 5 byteMath.sqrt .

Tidak disatukan

function pi(n) {
  function random() {
    return Math.floor(Math.random() * 1e6) + 1;
  }
  function gcd(a, b) {
    if (b == 0)
      return a;
    return gcd(b, a % b);
  }
  function q(n) {
    if (n == 0)
      return 0;
    return (gcd(random(), random()) == 1 ? 1 : 0) + q(n - 1));
  }
  return Math.sqrt(n * 6 / q(n));
}

Dalam Ungolfed Version gcdmemanggil fungsig
Roman Gräf

r=_=>apakah itu kode atau gambar?
aross

n=>(n*6/(r=_=>Math.random()*1e6,g=(a,b)=>b?g(b,a%b):a>-2,q=n=>n&&g(~r(),~r())+q(n-1))(n))**.51B lebih pendek
l4m2

n=>(n*6/(q=_=>n--&&q(r=_=>Math.random()*1e6)+g(~r(),~r()))(g=(a,b)=>b?g(b,a%b):a>-2))**.5
14m2

5

PHP, 82 77 74 byte

for(;$i++<$argn;)$s+=2>gmp_gcd(rand(1,1e6),rand(1,1e6));echo(6*$i/$s)**.5;

Jalankan seperti ini:

echo 10000 | php -R 'for(;$i++<$argn;)$s+=2>gmp_gcd(rand(1,1e6),rand(1,1e6));echo(6*$i/$s)**.5;' 2>/dev/null;echo

Penjelasan

Lakukan apa yang tertulis di kaleng. Membutuhkan PHP_GMP untuk gcd.

Tweaks

  • Disimpan 3 byte dengan menggunakan $argn

4

Perl, 64 byte

sub r{1+~~rand 9x6}$_=sqrt$_*6/grep{2>gcd r,r}1..$_

Membutuhkan opsi baris perintah -pMntheory=gcd, dihitung sebagai 13. Input diambil dari stdin.

Contoh Penggunaan

$ echo 1000 | perl -pMntheory=gcd pi-rock.pl
3.14140431218772

4

R, 94 byte

N=scan();a=replicate(N,{x=sample(1e6,2);q=1:x[1];max(q[!x[1]%%q&!x[2]%%q])<2});(6*N/sum(a))^.5

Relatif lambat tapi masih berfungsi. Gandakan N kali fungsi yang mengambil 2 angka acak (dari 1 hingga 1e6) dan memeriksa apakah gcdnya kurang dari 2 (menggunakan fungsi gcd lama milik saya ).


1
Jika Anda tidak khawatir tentang peringatan, 1:xakan berhasil.
MickyT

4

PowerShell v2 +, 118 114 byte

param($n)for(;$k-le$n;$k++){$i,$j=0,1|%{Random -mi 1};while($j){$i,$j=$j,($i%$j)}$o+=!($i-1)}[math]::Sqrt(6*$n/$o)

Mengambil input $n, memulai forloop hingga $ksama dengan $n(tersirat $k=0saat pertama kali memasuki loop). Setiap iterasi, dapatkan Randomnomor baru $idan $j( flag -minimum 1memastikan kami >=1dan tidak ada flag maksimum [int]::MaxValueyang diizinkan, yang diizinkan oleh OP karena lebih besar dari10e6 ).

Kami kemudian pergi ke loop GCDwhile . Lalu, selama GCD 1, $obertambah. Pada akhir forloop, kami melakukan [math]::Sqrt()panggilan sederhana , yang dibiarkan pada pipa dan output tersirat.

Butuh sekitar 15 menit untuk menjalankan dengan input 10000pada laptop Core i5 saya ~ 1 tahun.

Contohnya

PS C:\Tools\Scripts\golfing> .\natural-pi-0-rock.ps1 100
3.11085508419128

PS C:\Tools\Scripts\golfing> .\natural-pi-0-rock.ps1 1000
3.17820863081864

PS C:\Tools\Scripts\golfing> .\natural-pi-0-rock.ps1 10000
3.16756133579975

3

Java 8, 164 151 byte

n->{int c=n,t=0,x,y;while(c-->0){x=1+(int)(Math.random()*10e6);y=1+(int)(Math.random()*10e6);while(y>0)y=x%(x=y);if(x<2)t++;}return Math.sqrt(6f*n/t);}

Penjelasan

n->{
    int c=n,t=0,x,y;
    while(c-->0){                          // Repeat n times
        x=1+(int)(Math.random()*10e6);     // Random x
        y=1+(int)(Math.random()*10e6);     // Random y
        while(y>0)y=x%(x=y);               // GCD
        if(x<2)t++;                        // Coprime?
    }
    return Math.sqrt(6f*n/t);              // Pi
}

Uji Harness

class Main {
    public static interface F{ double f(int n); }
    public static void g(F s){
        System.out.println(s.f(100));
        System.out.println(s.f(1000));
        System.out.println(s.f(10000));
    }
    public static void main(String[] args) {
        g(
            n->{int c=n,t=0,y,x;while(c-->0){x=1+(int)(Math.random()*10e6);y=1+(int)(Math.random()*10e6);while(y>0)y=x%(x=y);if(x<2)t++;}return Math.sqrt(6f*n/t);}
        );
    }
}

Memperbarui

  • -13 [ 16-10-05 ] Terima kasih kepada @TNT dan menambahkan test harness

1
Anda tidak perlu tanda kurung di sekitar yang pertama n, t+=1bisa menjadi t++, Anda bisa menyingkat intdeklarasi Anda menjadi satu baris, yaitu int c=n,t=0,x,y;, dan !=0(saya pikir) bisa menjadi >0. Itu harus menyimpan 12 byte secara keseluruhan. Itu cara yang rapi untuk menemukan GCD x dan y.
TNT


1

Frink, 84 89

r[]:=random[10^6]+1
g=n=eval[input[1]]
for a=1to n
g=g-1%gcd[r[],r[]]
println[(6*n/g)^.5]

Saya beruntung: g = n = ... menyimpan byte lebih dari g = 0 n = ... ; dan 1% gcd () memberi (0,1) vs (1,0) sehingga saya bisa mengurangi. Dan sial: n sudah ditugaskan dan a digunakan karena variabel lingkaran dan batas mereka lokal dan terdefinisi luar loop.

Verbose

r[] := random[10^6] + 1     // function. Frink parses Unicode superscript!
g = n = eval[input[""]]     // input number, [1] works too
for a = 1 to n              // repeat n times
   g = g - 1%gcd[r[], r[]]  // subtract 1 if gcd(i, j) > 1
println[(6*n/g)^.5]         // ^.5 is shorter than sqrt[x], but no super ".", no ½

Itu 90 byte dan 88 karakter ...?
CalculatorFeline

Terima kasih sudah menangkapnya. Saya tidak menghitung baris baru, dan sementara ², ³ hanya 1 byte more lebih. Saya memperbaikinya menjadi 89 byte tanpa baris akhir.
maybeso

Anda belum memperbaiki kode verbose.
CalculatorFeline


1

AWK , 109 byte

func G(p,q){return(q?G(q,p%q):p)}{for(;i++<$0;)x+=G(int(1e6*rand()+1),int(1e6*rand()+1))==1;$0=sqrt(6*$0/x)}1

Cobalah online!

Saya terkejut bahwa itu berjalan dalam jumlah waktu yang wajar untuk 1000000.


1

Pyt , 37 35 byte

←Đ0⇹`25*⁶⁺Đ1⇹ɾ⇹1⇹ɾǤ1=⇹3Ș+⇹⁻łŕ⇹6*⇹/√

Penjelasan:

←Đ                                              Push input onto stack twice
  0                                             Push 0
   ⇹                                            Swap top two elements of stack
    `                      ł                    Repeat until top of stack is 0
     25*⁶⁺Đ1⇹ɾ⇹1⇹ɾ                              Randomly generate two integers in the range [1,10^6]
                  Ǥ1=                           Is their GCD 1?
                     ⇹3Ș                        Reposition top three elements of stack
                        +                       Add the top 2 on the stack
                         ⇹⁻                     Swap the top two and subtract one from the new top of the stack
                            ŕ                   Remove the counter from the stack
                             ⇹                  Swap the top two on the stack
                              6*                Multiply top by 6
                                ⇹               Swap top two
                                 /              Divide the second on the stack by the first
                                  √             Get the square root

1

J, 27 Bytes

3 :'%:6*y%+/(1:=?+.?)y#1e6'

Penjelasan:

3 :'                      '  | Explicit verb definition
                     y#1e6   | List of y copies of 1e6 = 1000000
            (1:=?+.?)        | for each item, generate i and j, and test whether their gcd is 1
          +/                 | Sum the resulting list
      6*y%                   | Divide y by it and multiply by six
    %:                       | Square root

Cukup beruntung dengan 3.14157for N = 10000000, yang butuh beberapa 2.44detik.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.