Doğal Pi # 0 - Kaya


39

Hedef

Girdi alan bir program / işlev oluşturun N, Nrastgele tamsayı çiftlerinin asal olup olmadığını kontrol edin ve geri dönün sqrt(6 * N / #coprime).

TL; DR

Bu zorluklar Pi'ye yaklaşmak için sadece doğa ve beyninizi (ve belki de bazı yeniden kullanılabilir kaynakları) gerektiren algoritmaların simülasyonudur. Zombi kıyameti sırasında Pi'ye gerçekten ihtiyacınız varsa, bu yöntemler cephaneyi boşa harcamaz ! Gelecek sekiz zorluk daha var. Öneriler yapmak için sanal alan gönderisine göz atın .

Simülasyon

Neyi simüle ediyoruz? Eh, iki rastgele tamsayının göreceli olarak asal olma olasılığı (yani, coprime veya gcd == 1), yani, Pi'yi 6/Pi/Pihesaplamanın doğal bir yolu, iki kova kaya (veya avuç dolusu) çıkarmak olacaktır; onları say; gcd'lerinin 1 olup olmadığını görün ; tekrar et. Bunu birkaç kez yaptıktan sonra , sqrt(6.0 * total / num_coprimes)doğru eğilim olacaktır Pi. Kıyamet sonrası dünyada karekök hesaplamak sizi tedirgin ediyorsa, endişelenmeyin! Bunun için Newton'un Yöntemi var.

Bunu nasıl simüle ediyoruz?

  • Giriş almak N
  • Aşağıdaki Nsaatleri yapın:
    • Düzgün bir şekilde rastgele pozitif tamsayılar üretir ivej
    • İle 1 <= i , j <= 10^6
    • Eğer gcd(i , j) == 1:result = 1
    • Başka: result = 0
  • NSonuçların toplamını alın ,S
  • Dönüş sqrt(6 * N / S)

görüntü tanımını buraya girin

Şartname

  • Giriş
    • Esnek, herhangi bir standart yoldan (örn. Function parametresi, STDIN) ve herhangi bir standart formatta (örn. String, Binary) girdi alın
  • Çıktı
    • Esnek, standart yollardan herhangi birinde çıktı ver (ör. İade, baskı)
    • Beyaz boşluk, arkadaki boşluk ve beyaz boşluk kabul edilebilir
    • Doğruluk, lütfen en az 4 ondalık doğruluk yeri sağlayın (örn. 3.1416)
  • puanlama
    • En kısa kod kazanır!

Test Kılıfları

Çıktınız rastgele şans nedeniyle bunlarla aynı çizgide olmayabilir. Ancak ortalama olarak, verilen değer için bu kadar doğruluk elde etmelisiniz 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
Cevabımızın çalışması gerekiyor mu N = 1000000yoksa program Nçok büyükse, örneğin bir yığın taşması döndürürse sorun olur mu?
16'da

@ Dilin bir kısıtlaması ise, kesin, kesin. Aksi takdirde işlem yapmanız gerekir N=10^6.
NonlinearFruit


2
Hedef yanıltıcıdır, sadece bir tamsayı çiftinin işaretlendiğini belirtir.
user253751,

1
Üretilen rastgele sayıların üst sınırının tam olarak 1000000 olması gerekiyor mu? Daha büyük bir üst sınır kabul edilebilir mi?
Sok

Yanıtlar:


12

APL, 23 bayt

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

Açıklama:

  • ?⍵2⍴1e6: aralıkta rastgele sayılarla 2x ⍵ matrisini üretir [1..10 6 ]
  • 1+.=∨/: her çiftin GCD'sini alın ve kaç tanesinin 1'e eşit olduğunu görün.
  • .5*⍨6×⍵÷: (6 × ⍵ ÷ S) 0.5

11

Jöle , 20 18 16 bayt

@ Pietu1998 sayesinde -2 bayt ( ċ1toplamda ikiden az yerine , zincir ve kullanım sayısı 1 <2S)

@Dennis sayesinde -2 bayt (zincirlemeyi önlemek için örneklemeden önce 1e6'yı birçok kez tekrarlayın)

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

(Rastgele işlev nedeniyle son derece yavaş)

Nasıl?

Ḥȷ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÷½2 bayt kaydeder. ( ȷ6tek bir niladın 10 ^ 6'sı ċ1sayılır)
PurkkaKoodari

Ah, nasıl böyle zincirleyeceğimi çözemedim (birkaç şey denedim) ve 1 numarayı unuttum - teşekkürler (sanırım ȷ²daha hızlı küçük bir parça ȷ6)
Jonathan Allan

Olabilir. Şimdi düşündüm ki, ȷ²burada iki bağlantı olmak zarar görmez, ancak ekstra bir bağlantı veya ¤bazı kullanım durumları için gerektirir
PurkkaKoodari

1
Ḥȷ6xX€rastgele örnekleme için çalışmalı.
Dennis,

9

Python 2, 143 140 132 124 122 124 122 bayt

Golf oynamaya başladığımdan bu yana epey zaman geçti, bu yüzden burada bir şeyi kaçırmış olabilirim! Bunu kısaltdıkça güncellenecek.

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

Beni burada test et !

İki baytlık tasarruf için Jonathan Allan'a teşekkürler :)


OP’ye göre 1 <= i , j <= 10^6kullanmanız gerekiyor randrange(1,1e6+1).
mbomb007

1
Ayrıca, repl.it linkinin dil ismi içerisinde olması da çok garip. Dil ismindeki bir bağlantı, eğer varsa, dilin ana sayfasına olmalıdır. Repl.it bağlantınızı kodunuzun altına ayrı bir bağlantı olarak yerleştirin.
mbomb007

@ mbomb007 İyi nokta, ben düzelttim :) Bir süre oldu!
Kade

1
k=lambda:r.randrange(1e6)+1iki bayttan tasarruf etti
Jonathan Allan

1
@JonathanAllan iyi yakalamak, teşekkürler!
Kade


8

R, 103 99 95 99 98 94 bayt

Büyük olasılıkla biraz aşağı golf olabilir. İçin bir takma ad tanımlayarak bağlı @ Antoine-kese 4 bayt ve başka bir 4 bayt azaltın samplekullanılarak ^.5yerine sqrtve 1e6yerine 10^6. Örnekleme ive jgerçekten tekdüze olmasını sağlamak için 4 bayt eklendi . Ben fark ardına bayt kaldırıldı 6*N/sum(x)aynıdır 6/mean(x). 4 bayt kaydetmek pryr::fyerine kullanılır function(x,y).

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

Örnek çıktı:

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

1
Basitçe kullanabilirsiniz sample(10^6,N). Sadece daha kısa değil, aynı zamanda çok daha verimli.
asac - Monica'yı yeniden kurun

Yanlış olabilirim, ancak örnek düzgün bir şekilde rastgele tamsayılar için yerine = T ile kullanılmamalıdır. Örneğin sample(10,10), tüm sayıları 1: 10'da döndürmek garanti edilir, oysa sample(10,10,T)sayıların tekrarlanabileceği rastgele bir seçim üretecektir.
MickyT

@MickyT Kesinlikle haklısın, bunu birkaç dakika önce kendim anladım. Bu durumda bunun matematiksel olarak nasıl yürüdüğünden tam olarak emin değilim - söyleyebileceğim kadarıyla, her iki yöntem de kabaca eşit derecede doğru. Bu bilgiyi eklemek için gönderimi düzenleyeceğim.
rturnbull

Her iki yöntem de N << 10 ^ 6 olduğunda eşit derecede doğrudur. Keyfi olarak büyük N ile başa çıkmak için, değiştirme, iyi yakalama ile örneklemelisiniz.
asac - Monica,

7

Aslında, 19 bayt

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

Çevrimiçi deneyin!

Açıklama:

`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'nin 0 olmasına izin verilmiyor
isaacg

1
@ isaacg Onlar değil. Açıklamayı okuyacaksanız, rastgele değerlerin [0, 10 ** 6) arasından seçildiğini ve ardından artırıldığını söyler.
Mego

7

MATL , 22 bayt

1e6Hi3$YrZ}Zd1=Ym6w/X^

Çevrimiçi deneyin!

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 bayt

@*6cQ/iMcmhO^T6yQ2lN2

Çevrimiçi deneyin.

açıklama

                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 bayt

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)}

Açıklama:

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
  )
}

Ben <3 Scala! Özellikle, çünkü bazen gerçekten bir açıklamaya ihtiyaç duyuyor.
Roman Gräf

RomanGräf Dürüst olmak gerekirse @, sanırım tek şey olabilir belirsiz olabilir 6f, Seq.fillve math.random.
corvus_192

5

Raket 92 bayt

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

Ungolfed:

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

Test yapmak:

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

Çıktı:

2.970442628930023
3.188964020716403
3.144483068444827

5

JavaScript (ES7), 107 95 94 bayt

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

ES6 sürümü tam olarak 99 bayttır, ancak ES7 üs işletmecisi **5 bayttan tasarruf sağlar Math.sqrt.

Ungolfed

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));
}

Ungolfed Versiyonunda gcdfonksiyonu çağırıyorg
Roman Gräf

r=_=>Bu kod mu yoksa çizim mi?
16'ya kadar

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 daha kısa
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
l4m2

5

PHP, 82 77 74 bayt

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

Bu şekilde koş:

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

açıklama

Teneke ne diyor yok. PHP_GMP gerektirir gcd.

Düzenlemeler

  • Kullanarak 3 bayt kaydedildi $argn

4

Perl, 64 bayt

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

-pMntheory=gcd13 olarak sayılan komut satırı seçeneğini gerektirir . Girdi stdin'den alınır.

Örnek Kullanım

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

4

R, 94 bayt

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

Nispeten yavaş ama yine de çalışıyor. N kez 2 rasgele sayı alan (1'den 1e6'ya kadar) bir fonksiyonun çoğaltılması ve gcd'lerinin 2'den az olup olmadığını kontrol et (benim eski bir gcd fonksiyonunu kullanarak ).


1
Uyarılar için endişelenmiyorsanız 1:xişe yarayacaktır.
MickyT

4

PowerShell v2 +, 118 114 bayt

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)

Girdiyi alır $n, eşit forolana kadar bir döngü başlatır ( ilk döngüye girdikten sonra örtülü ). Her yineleme, yeni sayılar alır ve (en büyük bayrak , OP'den daha büyük olduğundan izin verilen maksimum bayrağa izin vermemizi ve izin vermememizi sağlar ).$k$n$k=0Random$i$j-mi1>=1[int]::MaxValue10e6

Daha sonra bir GCD whiledöngüsüne giriyoruz . Daha sonra, GCD olduğu sürece 1, $oartırılır. forDöngünün sonunda [math]::Sqrt(), boru hattında kalan ve çıkışın örtülü olduğu basit bir çağrı yaparız .

10000~ 1 yaşındaki Core i5 dizüstü bilgisayarımda girdiyle çalışmak yaklaşık 15 dakika sürüyor .

Örnekler

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 bayt

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);}

açıklama

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
}

Test Demeti

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);}
        );
    }
}

Güncelleme

  • -13 [16-10-05] @TNT ve test kablo demeti sayesinde

1
İlk parantez içine ihtiyacınız yok n, t+=1olabilirsiniz t++, intbildirimlerinizi tek bir satırda yoğunlaştırabilirsiniz , yani int c=n,t=0,x,y;ve !=0(sanırım) olabilir >0. Bu toplam 12 bayt kurtarmalıdır. Yine de, x ve y'nin GCD'sini bulmak için temiz bir yol.
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]

Şanslı oldum: g = n = ... bir bayttan fazla g = 0 n = ... ; ve % 1 gcd () (0,1) vs (1,0) 'i verir, böylece çıkarabilirim. Ve şanssız: n preassigned ve bir döngü değişkenleri ve bunların sınırları, yerel ve döngü dışında tanımsız olduğundan kullandı.

gereksiz sözlerle dolu

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 ½

90 bayt ve 88 karakter.
Hesap MakinesiFeline

Onu yakaladığın için teşekkürler. Yeni satırları saymadım ve ² iken ³ sadece 1 bayt ⁶ daha fazla. Son satır olmadan 89 byte'a düzelttim.
maybeso

Ayrıntılı kodu düzeltmediniz.
Hesap MakinesiFeline

Boşluk, tırnak ve rakamlar vb.
İle bire bir eşleşmiyor

1

AWK , 109 bayt

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

Çevrimiçi deneyin!

1000000 için makul bir sürede çalıştığına şaşırdım.


1

Pyt , 37 35 bayt

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

Açıklama:

←Đ                                              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 Bayt

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

Açıklama:

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

Bir ile oldukça şanslı Got 3.14157için N = 10000000aldı, 2.44saniye.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.