Natural Pi # 0 - Đá


39

Mục tiêu

Tạo một chương trình / hàm lấy đầu vào N, kiểm tra xem Ncác cặp số nguyên ngẫu nhiên có tương đối nguyên tố hay không và trả về sqrt(6 * N / #coprime).

TL; DR

Những thách thức này là mô phỏng các thuật toán chỉ yêu cầu tự nhiên và bộ não của bạn (và có thể một số tài nguyên có thể sử dụng lại) để ước tính Pi. Nếu bạn thực sự cần Pi trong ngày tận thế zombie, những phương pháp này không lãng phí đạn ! Có tám thử thách sắp tới. Kiểm tra bài sandbox để đưa ra khuyến nghị.

Mô phỏng

Chúng ta đang mô phỏng cái gì? Chà, xác suất để hai số nguyên ngẫu nhiên tương đối nguyên tố (ví dụ: coprime hoặc gcd == 1) là 6/Pi/Pimột cách tự nhiên để tính Pi sẽ là múc hai xô (hoặc số ít) đá; đếm chúng; xem nếu gcd của họ là 1; nói lại. Sau khi làm điều này một vài lần, sqrt(6.0 * total / num_coprimes)sẽ có xu hướng Pi. Nếu việc tính căn bậc hai trong thế giới hậu tận thế khiến bạn lo lắng, đừng lo lắng! Có phương pháp của Newton cho điều đó.

Làm thế nào chúng ta mô phỏng điều này?

  • Lấy đầu vào N
  • Làm những Nlần sau :
    • Tạo số nguyên dương ngẫu nhiên ij
    • Với 1 <= i , j <= 10^6
    • Nếu gcd(i , j) == 1:result = 1
    • Khác: result = 0
  • Lấy tổng số Nkết quả,S
  • Trở về sqrt(6 * N / S)

nhập mô tả hình ảnh ở đây

Đặc điểm kỹ thuật

  • Đầu vào
    • Linh hoạt, nhận đầu vào theo bất kỳ cách tiêu chuẩn nào (ví dụ: tham số hàm, STDIN) và ở bất kỳ định dạng chuẩn nào (ví dụ: Chuỗi, Nhị phân)
  • Đầu ra
    • Linh hoạt, cung cấp đầu ra theo bất kỳ cách tiêu chuẩn nào (ví dụ: trả lại, in)
    • Không gian màu trắng, dấu vết và khoảng trắng hàng đầu được chấp nhận
    • Độ chính xác, vui lòng cung cấp ít nhất 4 chữ số thập phân chính xác (nghĩa là 3.1416)
  • Chấm điểm
    • Mã ngắn nhất sẽ thắng!

Các trường hợp thử nghiệm

Đầu ra của bạn có thể không phù hợp với những điều này, vì cơ hội ngẫu nhiên. Nhưng trung bình, bạn sẽ nhận được nhiều về độ chính xác này cho giá trị đã cho 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
Câu trả lời của chúng tôi có cần phải làm việc không N = 1000000hoặc có ổn không nếu chương trình trả về, ví dụ như tràn ngăn xếp nếu Nquá lớn?
Gây tử vong vào

@Firthize nếu đó là một hạn chế của ngôn ngữ, chắc chắn. Nếu không, bạn cần phải xử lý N=10^6.
Phi tuyến


2
Mục tiêu là sai lệch, nó chỉ nêu một cặp số nguyên được kiểm tra.
dùng253751

1
Có giới hạn trên cho các số ngẫu nhiên được tạo ra cần phải chính xác 1000000 không? Một giới hạn trên lớn hơn sẽ được chấp nhận?
Sok

Câu trả lời:


12

APL, 23 byte

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

Giải trình:

  • ?⍵2⍴1e6: tạo ma trận 2-by-các số ngẫu nhiên trong phạm vi [1..10 6 ]
  • 1+.=∨/: lấy GCD của mỗi cặp và xem có bao nhiêu bằng 1. Điều này tính S.
  • .5*⍨6×⍵÷: (6 × S) 0,5

11

Thạch , 20 18 16 byte

-2 byte nhờ @ Pietu1998 (chuỗi & số lần sử dụng 1s, ċ1thay cho ít hơn hai lần tổng <2S)

-2 byte nhờ @Dennis (lặp lại 1e6 nhiều lần trước khi lấy mẫu để tránh xích)

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

(Rất chậm do chức năng ngẫu nhiên)

Làm sao?

Ḥȷ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

Dùng thử


ḤRµȷ6Xµ€g2/ċ1÷³6÷½tiết kiệm 2 byte. ( ȷ6là 10 ^ 6 trong một nilad, ċ1đếm số người)
PurkkaKoodari

À tôi không thể tìm ra cách xâu chuỗi nó như thế (tôi đã thử một vài thứ) và quên đi mẹo 1 - cảm ơn (tôi nghĩ ȷ²là nhanh hơn một chút nhỏ hơn ȷ6)
Jonathan Allan

Có thể là. Bây giờ tôi nghĩ về nó, ȷ²việc hai liên kết không bị tổn thương ở đây, nhưng sẽ yêu cầu một liên kết bổ sung hoặc ¤cho một số trường hợp sử dụng
PurkkaKoodari

1
Ḥȷ6xX€nên làm việc để lấy mẫu ngẫu nhiên.
Dennis

9

Python 2, 143 140 132 124 122 124 122 byte

Đã khá lâu kể từ khi tôi thử chơi golf, vì vậy tôi có thể đã bỏ lỡ điều gì đó ở đây! Sẽ được cập nhật khi tôi rút ngắn điều này.

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

Kiểm tra tôi ở đây!

cảm ơn Jonathan Allan vì đã lưu hai byte :)


Theo OP, 1 <= i , j <= 10^6vì vậy bạn cần sử dụng randrange(1,1e6+1).
mbomb007

1
Ngoài ra, thật lạ khi có liên kết repl.it trong tên ngôn ngữ. Một liên kết trong tên lang nên đến trang chủ của ngôn ngữ, nếu có. Đặt liên kết repl.it của bạn dưới dạng một liên kết riêng bên dưới mã của bạn.
mbomb007

@ mbomb007 Điểm tốt, tôi đã sửa nó :) Đã được một lúc!
Kade

1
k=lambda:r.randrange(1e6)+1lưu hai byte
Jonathan Allan

1
@Jonathan ALLan bắt tốt, cảm ơn!
Kade

8

Toán học, 49 48 51 byte

Đã lưu một byte và sửa một lỗi nhờ @ LegionMammal978 .

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

1
Bạn có thể lưu một byte:(6#/Count[GCD@@1*^6~RandomInteger~{2,#},1])^.5&
LegionMammal978

1
Ngoài ra, 1*^6nên được thay thế bằng {1,1*^6}để đảm bảo rằng i , j ≠ 0.
LegionMammal978

8

R, 103 99 95 99 98 94 byte

Có thể có khả năng bị đánh golf xuống một chút. Cắt giảm 4 byte do @ antoine-sac và 4 byte khác bằng cách xác định bí danh cho sample, sử dụng ^.5thay vì sqrt1e6thay vì 10^6. Đã thêm 4 byte để đảm bảo rằng việc lấy mẫu ijthực sự đồng nhất. Đã xóa một byte sau khi tôi nhận ra nó 6*N/sum(x)giống như 6/mean(x). Được sử dụng pryr::fthay vì function(x,y)để lưu 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

Đầu ra mẫu:

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

1
Bạn chỉ có thể sử dụng sample(10^6,N). Không chỉ ngắn hơn, nó còn hiệu quả hơn nhiều.
asac - Phục hồi Monica

Tôi có thể sai, nhưng không nên sử dụng mẫu với thay thế = T cho số nguyên ngẫu nhiên thống nhất đúng. Ví dụ, sample(10,10)được đảm bảo trả về tất cả các số trong 1:10, trong khi đó sample(10,10,T)sẽ tạo ra một lựa chọn ngẫu nhiên trong đó các số có thể được lặp lại.
MickyT

@MickyT Bạn hoàn toàn chính xác, tôi mới nhận ra điều này vài phút trước đây. Tôi không hoàn toàn chắc chắn làm thế nào điều này diễn ra theo toán học trong trường hợp này - theo như tôi có thể nói, cả hai phương pháp đều có độ chính xác gần như nhau. Tôi sẽ chỉnh sửa bài viết của mình để thêm thông tin này.
rturnbull

Cả hai phương pháp đều chính xác như nhau khi N << 10 ^ 6. Để xử lý N lớn tùy ý, bạn phải lấy mẫu thay thế, bắt tốt.
asac - Phục hồi Monica

7

Trên thực tế, 19 byte

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

Hãy thử trực tuyến!

Giải trình:

`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 không được phép là 0
isaacg

1
@isaacg Họ không. Nếu bạn sẽ đọc phần giải thích, nó nói rằng các giá trị ngẫu nhiên được chọn từ [0, 10 ** 6), sau đó tăng dần.
Mego

7

MATL , 22 byte

1e6Hi3$YrZ}Zd1=Ym6w/X^

Hãy thử trực tuyến!

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

Bình thường, 21 byte

@*6cQ/iMcmhO^T6yQ2lN2

Hãy thử trực tuyến.

Giải trình

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

Giải trình:

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

Tôi <3 Scala! Đặc biệt, bởi vì đôi khi nó thực sự cần một lời giải thích.
Roman Gräf

@ RomanGräf Thành thật mà nói, những điều duy nhất tôi nghĩ có thể không rõ ràng là 6f, Seq.fillmath.random.
corvus_192

5

Vợt 92 byte

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

Ung dung:

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

Kiểm tra:

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

Đầu ra:

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

Phiên bản ES6 chính xác là 99 byte, nhưng toán tử lũy thừa ES7 **tiết kiệm hơn 5 byte Math.sqrt.

Bị đánh cắp

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

Trong phiên bản Ungolfed gcdgọi hàmg
Roman Gräf

r=_=>Đó là mã hay một bản vẽ?
vào

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 ngắn hơn
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 byte

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

Chạy như thế này:

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

Giải trình

Liệu những gì nó nói trên tin. Yêu cầu PHP_GMP cho gcd.

Tinh chỉnh

  • Đã lưu 3 byte bằng cách sử dụng $argn

4

Perl, 64 byte

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

Yêu cầu tùy chọn dòng lệnh -pMntheory=gcd, được tính là 13. Đầu vào được lấy từ stdin.

Sử dụng mẫu

$ 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

Tương đối chậm nhưng vẫn hoạt động. Sao chép N lần một hàm lấy 2 số ngẫu nhiên (từ 1 đến 1e6) và kiểm tra xem gcd của chúng có nhỏ hơn 2 hay không (sử dụng hàm gcd cũ của tôi ).


1
Nếu bạn không lo lắng về các cảnh báo, 1:xsẽ làm việc.
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)

Đưa đầu vào $n, bắt đầu một forvòng lặp cho đến khi $kbằng $n(ẩn $k=0khi lần đầu tiên vào vòng lặp). Mỗi lần lặp, có được mới Randomsố $i$j(các -minimum 1cờ đảm bảo chúng tôi >=1và không có cờ tối đa cho phép lên đến [int]::MaxValue, được phép của OP vì nó lớn hơn 10e6).

Chúng tôi sau đó đi vào một vòng lặp GCDwhile . Sau đó, vì vậy miễn là GCD là 1, $ođược tăng lên. Vào cuối forvòng lặp, chúng tôi thực hiện một [math]::Sqrt()cuộc gọi đơn giản , được để lại trên đường ống và đầu ra là ẩn.

Mất khoảng 15 phút để chạy với đầu vào 10000trên máy tính xách tay Core i5 ~ 1 tuổi của tôi.

Ví dụ

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

Giải trình

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
}

Khai thác thử nghiệm

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

Cập nhật

  • -13 [16-10-05] Nhờ @TNT và thêm khai thác thử nghiệm

1
Bạn không cần dấu ngoặc đơn xung quanh đầu tiên n, t+=1có thể trở thành t++, bạn có thể cô đọng các intkhai báo của mình thành một dòng, nghĩa là int c=n,t=0,x,y;, và !=0(tôi nghĩ) có thể trở thành >0. Điều đó sẽ tiết kiệm 12 byte tổng thể. Tuy nhiên, đó là một cách gọn gàng để tìm GCD của x và y.
TNT


1

Nháy mắt, 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]

Tôi đã may mắn: g = n = ... lưu một byte qua g = 0 n = ... ; và 1% gcd () cho (0,1) so với (1,0) để tôi có thể trừ. Và không may mắn: n được gán trước và một sử dụng vì các biến vòng lặp và giới hạn của họ được địa phương và không xác định bên ngoài vòng lặp.

Rực rỡ

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 ½

Đó là 90 byte và 88 ký tự ...?
Máy

Cảm ơn đã nắm bắt điều đó. Tôi đã không đếm các dòng mới và trong khi ², chỉ có 1 byte là nhiều hơn. Tôi đã sửa nó thành 89 byte mà không có dòng mới cuối cùng.
maybeso

Bạn chưa sửa mã verbose.
Máy

Dù sao, đây không phải là một trận đấu một đối một với khoảng cách, dấu ngoặc kép và số, v.v.
maybeso

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

Hãy thử trực tuyến!

Tôi ngạc nhiên rằng nó chạy trong một khoảng thời gian hợp lý cho 1000000.


1

Pyt , 37 35 byte

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

Giải trình:

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

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

Giải trình:

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

Đã khá may mắn với một 3.14157cho N = 10000000, mà mất 2.44vài giây.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.