Natural Pi # 0 - Rock


39

Obbiettivo

Crea un programma / funzione che accetta un input N, controlla se Ncoppie casuali di numeri interi sono relativamente primi e restituisce sqrt(6 * N / #coprime).

TL; DR

Queste sfide sono simulazioni di algoritmi che richiedono solo la natura e il cervello (e forse alcune risorse riutilizzabili) per approssimare Pi. Se hai davvero bisogno di Pi durante l'apocalisse di zombi, questi metodi non sprecano munizioni ! Ci sono altre otto sfide da affrontare. Controlla il post sandbox per dare consigli.

Simulazione

Cosa stiamo simulando? Bene, la probabilità che due numeri interi casuali siano relativamente primi (cioè coprime o gcd == 1) è 6/Pi/Pi, quindi un modo naturale per calcolare Pi sarebbe quello di raccogliere due secchi (o manciate) di rocce; contali; vedere se il loro gcd è 1; ripetere. Dopo averlo fatto un paio di volte, sqrt(6.0 * total / num_coprimes)tenderà a farlo Pi. Se calcolare la radice quadrata nel mondo post-apocalittico ti rende nervoso, non preoccuparti! C'è il metodo di Newton per questo.

Come stiamo simulando questo?

  • Prendi input N
  • Fai i seguenti Norari:
    • Generare uniformemente numeri interi casuali positivi iej
    • Con 1 <= i , j <= 10^6
    • Se gcd(i , j) == 1:result = 1
    • Altro: result = 0
  • Prendi la somma dei Nrisultati,S
  • Ritorno sqrt(6 * N / S)

inserisci qui la descrizione dell'immagine

specificazione

  • Ingresso
    • Flessibile, accetta input in uno dei modi standard (es. Parametro di funzione, STDIN) e in qualsiasi formato standard (es. String, Binary)
  • Produzione
    • Flessibile, fornisce output in uno dei modi standard (ad es. Ritorno, stampa)
    • Sono ammessi spazi bianchi, finali e spazi bianchi iniziali
    • Precisione, si prega di fornire almeno 4 cifre decimali di precisione (es. 3.1416)
  • punteggio
    • Vince il codice più corto!

Casi test

L'output potrebbe non allinearsi con questi, a causa di possibilità casuali. Ma in media, dovresti ottenere tanta precisione per il valore dato di 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
La nostra risposta deve funzionare N = 1000000o va bene se il programma restituisce ad esempio uno stack overflow se Nè troppo grande?
Fatalizza il

@Fatalizza se si tratta di una limitazione della lingua, certo. Altrimenti, devi gestirlo N=10^6.
NonlinearFruit,


2
L'obiettivo è fuorviante, indica che è stata verificata solo una coppia di numeri interi.
user253751

1
Il limite superiore per i numeri casuali generati deve essere esattamente 1000000? Un limite superiore più ampio sarebbe accettabile?
Sok

Risposte:


12

APL, 23 byte

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

Spiegazione:

  • ?⍵2⍴1e6: genera una matrice 2 per of di numeri casuali nell'intervallo [1..10 6 ]
  • 1+.=∨/: ottieni il GCD di ciascuna coppia e vedi quanti sono uguali a 1. Questo calcola S.
  • .5*⍨6×⍵÷: (6 × ⍵ ÷ S) 0,5

11

Gelatina , 20 18 16 byte

-2 byte grazie a @ Pietu1998 (catena e uso contano 1s, ċ1al posto di meno di due sommati<2S )

-2 byte grazie a @Dennis (ripetere 1e6 più volte prima del campionamento per evitare il concatenamento)

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

(Estremamente lento a causa della funzione casuale)

Come?

Ḥȷ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÷½salva 2 byte. ( ȷ6è 10 ^ 6 in un singolo nilad, ċ1conta quelli)
PurkkaKoodari,

Ah, non sono riuscito a capire come concatenarlo in quel modo (ho provato alcune cose) e ho dimenticato il trucco del conteggio 1 - grazie (penso che ȷ²sia un pochino più veloce di ȷ6)
Jonathan Allan,

Potrebbe essere. Ora che ci penso, ȷ²essere due collegamenti non fa male qui, ma richiederebbe un collegamento aggiuntivo o ¤per alcuni casi d'uso
PurkkaKoodari,

1
Ḥȷ6xX€dovrebbe funzionare per il campionamento casuale.
Dennis,

9

Python 2, 143 140 132 124 122 124 122 byte

È passato un po 'di tempo da quando ho provato a giocare a golf, quindi potrei aver perso qualcosa qui! Si aggiornerà mentre accorgo questo.

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

Mettimi alla prova qui!

grazie a Jonathan Allan per il salvataggio a due byte :)


Secondo OP, 1 <= i , j <= 10^6quindi è necessario utilizzare randrange(1,1e6+1).
mbomb007,

1
Inoltre, è davvero strano avere il link repl.it all'interno del nome della lingua. Un collegamento nel nome della lingua dovrebbe essere alla home page della lingua, se non altro. Inserisci il tuo link repl.it come link separato sotto il tuo codice.
mbomb007,

@ mbomb007 Un buon punto, l'ho risolto :) Sono stato un po '!
Kade,

1
k=lambda:r.randrange(1e6)+1salva due byte
Jonathan Allan il

1
@JonathanAllan buona cattura, grazie!
Kade,

8

Mathematica, 49 48 51 byte

Salvato un byte e corretto un bug grazie a @ LegionMammal978 .

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

1
È possibile salvare un byte:(6#/Count[GCD@@1*^6~RandomInteger~{2,#},1])^.5&
LegionMammal978

1
Inoltre, 1*^6dovrebbe essere sostituito con {1,1*^6}per garantire che i , j ≠ 0.
LegionMammal978

8

R, 103 99 95 99 98 94 byte

Probabilmente si può giocare a golf un po '. Riduci 4 byte a causa di @ antoine-sac e altri 4 byte definendo un alias per sample, usando ^.5invece di sqrte 1e6invece di 10^6. Aggiunti 4 byte per garantire che il campionamento di ie jsia veramente uniforme. Rimosso un byte dopo aver capito che 6*N/sum(x)è lo stesso di 6/mean(x). Utilizzato pryr::fanziché function(x,y)per salvare 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

Uscita campione:

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

1
Puoi semplicemente usare sample(10^6,N). Non solo è più corto, ma è anche molto più efficiente.
asac - Ripristina Monica il

Potrei sbagliarmi, ma il campione non dovrebbe essere usato con replace = T per interi casuali adeguatamente uniformi. Ad esempio, sample(10,10)è garantito che restituisca tutti i numeri in 1:10, mentre sample(10,10,T)produrrà una selezione casuale in cui i numeri possono essere ripetuti.
MickyT,

@MickyT Hai perfettamente ragione, me ne sono appena reso conto qualche minuto fa. Non sono del tutto sicuro di come ciò avvenga matematicamente in questo caso - per quanto ne so, entrambi i metodi sono approssimativamente ugualmente accurati. Modificherò il mio post per aggiungere queste informazioni.
rturnbull,

Entrambi i metodi sono ugualmente precisi quando N << 10 ^ 6. Per gestire una N arbitrariamente grande, devi campionare con una sostituzione, una buona cattura.
asac - Ripristina Monica il

7

In realtà, 19 byte

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

Provalo online!

Spiegazione:

`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

io, j non è permesso essere 0
isaacg

1
@isaacg Non lo sono. Se leggerai la spiegazione, dice che i valori casuali sono selezionati da [0, 10 ** 6), quindi incrementati.
Mego

7

MATL , 22 byte

1e6Hi3$YrZ}Zd1=Ym6w/X^

Provalo 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

Provalo online.

Spiegazione

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

Spiegazione:

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

I <3 Scala! Soprattutto perché a volte ha davvero bisogno di una spiegazione.
Roman Gräf,

@ RomanGräf Ad essere sincero, le uniche cose che penso potrebbero non essere chiare sono 6f, Seq.fille math.random.
corvus_192,

5

Racchetta 92 byte

(λ(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:

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

Produzione:

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

La versione ES6 ha esattamente 99 byte, ma l'operatore esponenziale ES7 **salva 5 byteMath.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));
}

Nella versione Ungolfed gcdchiama la funzioneg
Roman Gräf

r=_=>è quel codice o un disegno?
circa il

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 più corto
l4m2 il

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;

Esegui in questo modo:

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

Spiegazione

Fa quello che dice sulla scatola. Richiede PHP_GMP pergcd .

Ritocchi

  • Salvato 3 byte utilizzando $argn

4

Perl, 64 byte

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

Richiede l'opzione della riga di comando -pMntheory=gcd , conteggiata come 13. L'input viene preso dallo stdin.

Esempio di utilizzo

$ 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

Relativamente lento ma funziona ancora. Replica N volte una funzione che accetta 2 numeri casuali (da 1 a 1e6) e controlla se il loro gcd è inferiore a 2 (usando una mia vecchia funzione gcd ).


1
Se non sei preoccupato per gli avvisi, 1:xfunzionerà.
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)

Accetta input $n, avvia un forloop fino a quando non è $kuguale $n(implicito $k=0al primo accesso al loop). Ogni iterazione, ottenere nuovi Randomnumeri $ie $j(la bandiera -minimum 1assicura che siamo >=1e nessuna bandiera massima consente fino a[int]::MaxValue , cosa che è consentita dall'OP poiché è più grande di 10e6).

Entriamo quindi in un loop GCDwhile . Quindi, fintanto che il GCD è 1, $oviene incrementato. Alla fine difor loop, facciamo una semplice [math]::Sqrt()chiamata, che viene lasciata sulla pipeline e l'output è implicito.

Sono necessari circa 15 minuti per l'esecuzione con input 10000 sul mio laptop Core i5 ~ 1 anno.

Esempi

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

Spiegazione

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
}

Collaudare l'imbragatura

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

Aggiornare

  • -13 [16-10-05] Grazie a @TNT e al cablaggio di prova aggiunto

1
Non hai bisogno delle parentesi intorno alla prima n, t+=1può diventare t++, puoi condensare le tue intdichiarazioni in una riga, cioè int c=n,t=0,x,y;, e !=0(penso) può diventare >0. Ciò dovrebbe consentire un risparmio complessivo di 12 byte. Questo è un modo pulito di trovare il GCD di xey, però.
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]

Sono stato fortunato: g = n = ... salva un byte su g = 0 n = ... ; e 1% gcd () dà (0,1) vs (1,0) in modo che io possa sottrarre. E sfortunato: n è preassegnato e a utilizzato perché le variabili di loop ed i loro limiti sono locali e indefinito di fuori del ciclo.

verboso

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 ½

Sono 90 byte e 88 caratteri ...?
CalculatorFeline

Grazie per averlo colto. Non ho contato i newline e mentre ², ³ sono solo 1 byte ⁶ è maggiore. L'ho corretto a 89 byte senza una nuova riga finale.
Maybeso,

Non hai corretto il codice dettagliato.
CalcolatriceFeline

Non è una corrispondenza uno a uno comunque con spaziatura, virgolette e numeri, ecc.
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

Provalo online!

Sono sorpreso che funzioni in un ragionevole lasso di tempo per 1000000.


1

Pyt , 37 35 byte

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

Spiegazione:

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

Spiegazione:

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

Sono stato abbastanza fortunato con un 3.14157for N = 10000000, che ha richiesto 2.44pochi secondi.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.