Co-primalità e il numero pi


23

introduzione

La teoria dei numeri è piena di meraviglie, sotto forma di connessioni inaspettate. Eccone uno.

Due interi sono co-prime se non hanno fattori in comune diverso da 1. Dato un numero N , prendere in considerazione tutti i numeri interi da 1 a N . Disegna due di questi numeri interi a caso (tutti i numeri interi hanno la stessa probabilità di essere selezionati ad ogni sorteggio; i sorteggi sono indipendenti e con sostituzione). Let p denota la probabilità che i due numeri interi selezionati siano primi di primo grado. Quindi p tende a 6 / π 2 ≈ 0,6079 ... come N tende all'infinito.

La sfida

Lo scopo di questa sfida è quello di calcolare p in funzione di N .

Ad esempio, si consideri N = 4. Esistono 16 coppie possibili ottenute dagli interi 1,2,3,4. 11 di queste coppie sono co-prime, ovvero (1,1), (1,2), (1,3), (1,4), (2,1), (3,1), (4,1 ), (2,3), (3,2), (3,4), (4,3). Quindi p è 11/16 = 0.6875 per N = 4.

Il valore esatto di p deve essere calcolato con almeno quattro decimali. Ciò implica che il calcolo deve essere deterministico (al contrario di Monte Carlo). Ma non è necessario che sia un elenco diretto di tutte le coppie come sopra; qualsiasi metodo può essere utilizzato.

È possibile utilizzare argomenti di funzione o stdin / stdout. Se si visualizza l'output, gli zeri finali possono essere omessi. Quindi ad esempio 0.6300può essere visualizzato come 0.63. Dovrebbe essere visualizzato come un numero decimale, non come una frazione (la visualizzazione della stringa 63/100non è consentita).

Il criterio vincente è il minor numero di byte. Non ci sono restrizioni sull'uso delle funzioni integrate.

Casi test

Input / output (sono obbligatori solo quattro decimali, come indicato sopra):

1    / 1.000000000000000
2    / 0.750000000000000
4    / 0.687500000000000
10   / 0.630000000000000
100  / 0.608700000000000
1000 / 0.608383000000000

Ci sono limiti nella gamma di input?
Eric Towers,

@EricTowers Il programma dovrebbe funzionare per qualsiasi dimensione ragionevole fino a limiti di memoria e tipo di dati. Almeno 1000
Luis Mendo il

Sono ammessi numeri razionali come valori di ritorno (non stringhe)? La mia lingua ha un tipo razionale nativo, in cui 63/100è un valido letterale, utilizzabile nel calcolo. (Langs sto parlando di: fattore , racchetta )
gatto

@cat Certo, vai avanti! Prendi in considerazione la precisione richiesta, però
Luis Mendo,

Risposte:


14

Gelatina , 12 8 byte

RÆṪSḤ’÷²

Provalo online!

Il seguente codice binario funziona con questa versione dell'interprete Jelly .

0000000: 52 91 b0 53 aa b7 9a 8a  R..S....

Idea

Chiaramente, il numero di coppie (j, k) tali che j ≤ k e j e k sono co-prime è uguale al numero di coppie (k, j) che soddisfano le stesse condizioni. Inoltre, se j = k , j = 1 = k .

Pertanto, per contare il numero di coppie co-prime con coordinate comprese tra 1 e n , è sufficiente calcolare la quantità m di coppie (j, k) tale che j ≤ k , quindi calcolare 2m - 1 .

Infine, poiché la funzione totulante di Eulero φ (k) produce numeri interi compresi tra 1 e k che sono primi di k , possiamo calcolare m come φ (1) +… + φ (n) .

Codice

RÆṪSḤ’÷²    Input: n

R           Yield [1, ..., n].
 ÆṪ         Apply Euler's totient function to each k in [1, ..., n].
   S        Compute the sum of all results.
    Ḥ       Multiply the result by 2.
     ’      Subtract 1.
      ÷²    Divide the result by n².

2
Oh, Jelly include la funzione totient !? Bella idea!
Luis Mendo,

2
Il conto alla rovescia fino a quando MATL include un comando completo al T-1 giorno ...
quintopia,

@quintopia (ho finalmente incluso la funzione totient) MrGreen
Luis Mendo,

14

Mathematica 43 42 byte

Ho trovato i punti reticolari visibili dall'origine , da cui è stata scattata la foto sotto, per essere d'aiuto nel riformulare il problema attraverso le seguenti domande riguardanti una data regione quadrata del reticolo unitario:

  • Quale frazione dei punti reticolo unitario ha coordinate co-prime?
  • Quale frazione di punti reticolari unitari può essere vista dall'origine?

grid


N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&

Esempi

Gli zeri finali vengono omessi.

N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&/@Range@10

{1., 0.75, 0.777778, 0.6875, 0.76, 0.638889, 0.714286, 0.671875, 0.679012, 0.63}


sincronizzazione

Il tempismo, in secondi, precede la risposta.

N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&[1000]// AbsoluteTiming

{0.605571, 0.608383}



6

Mathematica, 42 32 byte

Count[GCD~Array~{#,#},1,2]/#^2.&

Funzione anonima, utilizza semplice forza bruta. L'ultimo caso dura circa 0,37 secondi sulla mia macchina. Spiegazione:

                               &   A function taking N and returning
Count[               , , ]           the number of
                      1               ones
                                     in the
                        2             second
                                     level of
         ~Array~                      a matrix of
      GCD                              the greatest common denominators of
                {#,#}                 all 2-tuples in [1..N]
                          /         divided by
                           #          N
                            ^2.      squared.

Puoi pubblicare un esempio e una spiegazione per quelli di noi che non hanno Mathematica?
Luis Mendo,

2
Ciò unisce le nostre osservazioni: Count[Array[GCD,{#, #}],1,2]/#^2.& sii mio ospite.
DavidC,

4

Dyalog APL, 15 byte

(+/÷⍴)∘∊1=⍳∘.∨⍳

Abbastanza diretto. È un treno di funzioni monadico. Iota è i numeri da 1 a input, quindi prendiamo il prodotto esterno per gcd, quindi contiamo la proporzione di quelli.


3

Ottava, 49 47 byte

Basta calcolare il gcddi tutte le coppie e contare.

@(n)mean(mean(gcd(c=kron(ones(n,1),1:n),c')<2))

Il prodotto kronecker è fantastico.


kron! Buona idea!
Luis Mendo il

Prima l'ho usato meshgrid, ma poi ho notato che avrei potuto fare lo stesso con kroninline! (-> funzione anonima)
flawr,

2

JavaScript (ES6), 88 byte

n=>eval(`p=0;for(i=n;i;i--)for(j=n;j;j--,p+=a)for(a=1,k=j;k>1;k--)a=i%k||j%k?a:0;p/n/n`)

Spiegazione

n=>
  eval(`                     // use eval to enable for loop without {} or return
    p=0;                     // p = number of pairs
    for(i=n;i;i--)           // i = 1 to n
      for(j=n;j;j--,p+=a)    // j = i to n, a will equal 1 if i and j are coprime, else 0
        for(a=1,k=j;k>1;k--) // for each number from 0 to j
          a=i%k||j%k?a:0;    // if i%k and j%k are both 0, this pair is not coprime
    p/n/n                    // return result (equivalent to p/(n*n))
  `)

Test

Richiede del tempo per i >100valori grandi ( ) di n.


2

Scherzi a parte, 15 byte

,;ª)u1x`▒`MΣτD/

Dump esadecimale:

2c3ba62975317860b1604de4e7442f

Provalo online

Non mi preoccuperò di spiegarlo poiché usa letteralmente esattamente lo stesso algoritmo della soluzione Jelly di Dennis (anche se l'ho derivato in modo indipendente).


2

J, 19 17 byte

*:%~1-~5+/@p:|@i:

Uso:

   (*:%~1-~5+/@p:|@i:) 4
0.6875

Spiegazione:

*:%~1-~5+/@p:|@i:
               i: [-n..n]
             |@   absolute value of each element ([n..1,0,1,..n])
       5+/@p:     sum of the totient function for each element
    1-~           decreased by one, giving the number of co-prime pairs
*:%~              divided by N^2

La soluzione di Dennis fornisce una bella spiegazione su come possiamo usare la funzione totient.

Provalo online qui.


2

Mathematica, 35 byte

Implementa l'algoritmo di Dennis.

(2`4Plus@@EulerPhi@Range[#]-1)/#^2&

Calcola la somma del totale (funzione phi di Eulero) nell'intervallo da 1 al valore di input. Moltiplicare per virgola mobile due (con quattro cifre di precisione) e sottrarre uno. (È possibile mantenere una maggiore precisione usando invece " 2" e " 1`4".) Questo è il numero totale di coppie coprimi, quindi dividi per il quadrato dell'input per ottenere la frazione desiderata. Poiché i due sono un numero approssimativo, lo è anche il risultato.

Test (con i dati di temporizzazione nella colonna di sinistra poiché almeno uno di noi pensa che sia interessante), con la funzione assegnata a in fmodo che la linea di test sia più facilmente leggibile .:

f=(2`4Plus@@EulerPhi@Range[#]-1)/#^2&
RepeatedTiming[f[#]] & /@ {1, 2, 4, 10, 100, 1000}
(* {{5.71*10^-6, 1.000}, 
    {5.98*10^-6, 0.750}, 
    {0.000010  , 0.6875}, 
    {0.0000235 , 0.6300}, 
    {0.00028   , 0.6087}, 
    {0.0033    , 0.6084} }  *)

Modifica: mostra l'estensione dell'intervallo di input (scambiando la precisione con quella anziché con le due perché altrimenti i risultati diventano piuttosto monotoni) e sfidando gli altri a fare lo stesso ...

f = (2 Plus @@ EulerPhi@Range[#] - 1`4)/#^2 &
{#}~Join~RepeatedTiming[f[#]] & /@ {1, 2, 4, 10, 100, 1000, 10^4, 10^5, 10^6, 10^7}
(*  Results are {input, wall time, output}
    {{       1,  5.3*10^-6, 1.000}, 
     {       2,  6.0*10^-6, 0.7500}, 
     {       4,  0.0000102, 0.68750}, 
     {      10,  0.000023 , 0.63000}, 
     {     100,  0.00028  , 0.6087000}, 
     {    1000,  0.0035   , 0.608383000}, 
     {   10000,  0.040    , 0.60794971000}, 
     {  100000,  0.438    , 0.6079301507000}, 
     { 1000000,  4.811    , 0.607927104783000}, 
     {10000000, 64.0      , 0.60792712854483000}}  *)

RepeatedTiming[]esegue il calcolo più volte e impiega una media dei tempi, tentando di ignorare le cache fredde e altri effetti che causano valori anomali di temporizzazione. Il limite asintotico è

N[6/Pi^2,30]
(*  0.607927101854026628663276779258  *)

quindi per argomenti> 10 ^ 4, possiamo semplicemente restituire "0.6079" e soddisfare i requisiti di precisione e accuratezza specificati.


2

Julia, 95 byte

n->(c=combinations([1:n;1:n],2);((L=length)(collect(filter(x->gcd(x...)<2,c)))÷2+1)/L(∪(c)))

Solo l'approccio diretto per ora; Presto esaminerò soluzioni più brevi / più eleganti. Questa è una funzione anonima che accetta un numero intero e restituisce un float. Per chiamarlo, assegnarlo a una variabile.

Ungolfed:

function f(n::Integer)
    # Get all pairs of the integers from 1 to n
    c = combinations([1:n; 1:n], 2)

    # Get the coprime pairs
    p = filter(x -> gcd(x...) == 1, c)

    # Compute the probability
    return (length(collect(p)) ÷ 2 + 1) / length(unique(c))
end

Per quanto posso dire, non è necessario collectun oggetto pigro per prenderlo length.
gatto

@cat Lo fai per alcuni in cui lengthnon è stato definito un metodo, come nel caso dell'iteratore di combinazioni filtrate. Allo stesso modo endofnon funzionerebbe perché non esiste un metodo per quel tipo getindex.
Alex A.


@cat rangenon restituisce lo stesso tipo di oggetto di combinations. Quest'ultimo restituisce un iteratore su combinazioni che è un tipo separato senza un lengthmetodo definito . Vedi qui . (Anche la :sintassi è preferita rangeper la costruzione di intervalli;))
Alex A.

2

Salvia, 55 byte

lambda a:n((sum(map(euler_phi,range(1,a+1)))*2-1)/a**2)

Grazie a Sage computing tutto simbolicamente, i problemi di epsilon macchina e virgola mobile non emergono. Il compromesso è, per seguire la regola del formato di output, è necessaria una chiamata aggiuntiva a n()(la funzione di approssimazione decimale).

Provalo online


Molto bella! Sembra che tu stia usando Sage abbastanza spesso ultimamente :-)
Luis Mendo,

@LuisMendo Sage è eccezionale e fa tutto. È molto bello da usare nelle sfide matematiche perché ha un'enorme libreria integrata come Mathematica, ma la sintassi è migliore (in virtù del fatto che a) non è Mathematica eb) che è costruita su Python).
Mego

2

MATL , 20 17 byte

Questo utilizza la versione corrente (5.0.0) della lingua.

Approccio basato sulla risposta di @ flawr .

i:tg!X*t!Zd1=Y)Ym

Modifica (28 aprile 2015) : provalo online! Dopo che questa risposta è stata pubblicata, la funzione è Y)stata rinominata in X: ; il collegamento include tale modifica.

Esempio

>> matl i:tg!X*t!Zd1=Y)Ym
> 100
0.6087

Spiegazione

i:         % vector 1, 2, ... up to input number
tg!        % copy, convert into ones, transpose
X*         % Kronecker product. Produces a matrix
t!         % copy, transpose
Zd         % gcd of all pairs
1=         % is it equal to 1?
Y)         % linearize into column array
Ym         % compute mean

Vecchia risposta: 20 byte

Oi:t"t@Zd1=sb+w]n2^/

Spiegazione

O             % produce literal 0. Initiallizes count of co-prime pairs.
i             % input number, say N
:             % create vector 1, 2, ... N
t             % duplicate of vector
"             % for loop
    t         % duplicate of vector
    @         % loop variable: each element from vector
    Zd        % gcd of vector and loop variable. Produces a vector
    1=s       % number of "1" in result. Each "1" indicates co-primality
    b+w       % accumulate into count of co-prime pairs
]             % end
n2^/          % divide by N^2

Non potresti essere ancora più breve con un approccio come quello che ho usato in ottava?
Flawr,

Infatti! Grazie! 3 byte in meno. Avresti dovuto farlo da solo in MATL :-)
Luis Mendo il

Avrei provato se non fosse andata oltre la mia ora di andare a letto =)
flawr

1

PARI / GP , 25 byte

Rendere anonima la funzione risparmierebbe un byte, ma poi dovrei usarla selfrendendola nel complesso più costosa.

f(n)=n^2-sum(j=2,n,f(n\j))

1

Fattore, 120 113 byte

Ho passato questo corso a golf e non posso accorciarlo.

Traduzione di: Julia .

[ [a,b] dup append 2 <combinations> [ members ] keep [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap /f ]

L'esempio viene eseguito sui primi 5 casi di test (un valore di 1000 causa il blocco dell'editor e al momento non posso preoccuparmi di compilare un eseguibile):

! with floating point division
IN: scratchpad auto-use {
      1    
      2    
      4    
      10   
      100  
    }
    [ 
      [1,b] dup append 2 <combinations> [ members ] keep 
      [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap /f 
    ]
    map

--- Data stack:
{ 1.0 0.75 0.6875 0.63 0.6087 }
! with rational division
IN: scratchpad auto-use {
      1    
      2    
      4    
      10   
      100  
    }
    [ 
      [1,b] dup append 2 <combinations> [ members ] keep 
      [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap / 
    ]
    map

--- Data stack:
{ 1.0 0.75 0.6875 0.63 0.6087 }
{ 1 3/4 11/16 63/100 6087/10000 }

Aggiungi un esempio di esecuzione forse?
Luis Mendo,

1
@LuisMendo fatto!
gatto

1

Samau , 12 byte

Disclaimer: non competere perché ho aggiornato la lingua dopo che la domanda è stata pubblicata.

▌;\φΣ2*($2^/

Dump esadecimale (Samau utilizza la codifica CP737):

dd 3b 5c ad 91 32 2a 28 24 32 5e 2f

Usando lo stesso algoritmo della risposta di Dennis in Jelly.


0

Python2 / Pypy, 178 byte

Il xfile:

N={1:set([1])}
n=0
c=1.0
e=input()
while n<e:
 n+=1
 for d in N[n]:
  m=n+d
  try:N[m].add(d)
  except:N[m]=set([d,m])
 for m in range(1,n):
  if N[m]&N[n]==N[1]:c+=2
print c/n/n

In esecuzione:

$ pypy x <<<1
1.0
$ pypy x <<<10
0.63
$ pypy x <<<100
0.6087
$ pypy x <<<1000
0.608383

Il codice conta (n,m) for m<ndue volte le coppie co-prime ( c+=2). Questo ignora ciò (i,i) for i=1..nche è ok tranne (1,1), per cui viene corretto inizializzando il contatore con 1( 1.0per preparare la divisione del galleggiante in seguito) per compensare.

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.